diff options
705 files changed, 38903 insertions, 27469 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 43168e563..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,10 +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..9f62e9779 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" /> @@ -50,15 +49,6 @@ </intent-filter> </activity> - <activity android:name="com.android.inputmethod.deprecated.languageswitcher.InputLanguageSelection" - android:label="@string/language_selection_title"> - <intent-filter> - <action android:name="android.intent.action.MAIN"/> - <action android:name="com.android.inputmethod.latin.INPUT_LANGUAGE_SELECTION"/> - <category android:name="android.intent.category.DEFAULT" /> - </intent-filter> - </activity> - <receiver android:name="SuggestionSpanPickedNotificationReceiver" android:enabled="true"> <intent-filter> <action android:name="android.text.style.SUGGESTION_PICKED" /> diff --git a/java/proguard.flags b/java/proguard.flags index 33af890ec..2ee1a263f 100644 --- a/java/proguard.flags +++ b/java/proguard.flags @@ -1,6 +1,10 @@ -keep class com.android.inputmethod.latin.BinaryDictionary { int mDictLength; - <init>(...); + <init>(...); +} + +-keep class com.android.inputmethod.latin.Flag { + *; } -keep class com.android.inputmethod.latin.Suggest { @@ -8,13 +12,6 @@ com.android.inputmethod.latin.SuggestedWords getSuggestions(...); } --keep class com.android.inputmethod.latin.UserBigramDictionary { - void setDatabaseMax(int); - void setDatabaseDelete(int); - void waitUntilUpdateDBDone(); - void waitForDictionaryLoading(); -} - -keep class com.android.inputmethod.latin.AutoCorrection { java.lang.CharSequence getAutoCorrectionWord(); } @@ -23,18 +20,32 @@ boolean equalsIgnoreCase(...); } --keep class com.android.inputmethod.latin.spellcheck.SpellChecker { - *; -} - -keep class com.android.inputmethod.latin.spellcheck.SpellCheckerSettingsFragment { *; } --keep class com.android.inputmethod.latin.SettingsActivity { - *; +-keep class com.android.inputmethod.keyboard.LatinKeyboardView { + # Keep getter/setter methods for ObjectAnimator + int getLanguageOnSpacebarAnimAlpha(); + void setLanguageOnSpacebarAnimAlpha(int); + int getAltCodeKeyWhileTypingAnimAlhpa(); + void setAltCodeKeyWhileTypingAnimAlpha(int); } --keep class com.android.inputmethod.keyboard.internal.MiniKeyboardBuilder$MiniKeyboardParams { +-keep class com.android.inputmethod.keyboard.MoreKeysKeyboard$Builder$MoreKeysKeyboardParams { <init>(...); } + +-keep class com.android.inputmethod.latin.ResearchLogger { + void setLogFileManager(...); +} + +-keep class com.android.inputmethod.keyboard.KeyboardSet$Builder { + void setTouchPositionCorrectionEnabled(...); +} + +# 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..f8caca313 --- /dev/null +++ b/java/res/anim/alt_code_key_while_typing_fadein.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. +*/ +--> + +<objectAnimator + xmlns:android="http://schemas.android.com/apk/res/android" + android:propertyName="altCodeKeyWhileTypingAnimAlpha" + 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..bad1e7465 --- /dev/null +++ b/java/res/anim/alt_code_key_while_typing_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. +*/ +--> + +<objectAnimator + xmlns:android="http://schemas.android.com/apk/res/android" + android:propertyName="altCodeKeyWhileTypingAnimAlpha" + 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..531f440cc --- /dev/null +++ b/java/res/anim/language_on_spacebar_fadeout.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. +*/ +--> + +<objectAnimator + xmlns:android="http://schemas.android.com/apk/res/android" + android:propertyName="languageOnSpacebarAnimAlpha" + android:valueType="intType" + android:startOffset="1200" + android:duration="200" + android:valueFrom="255" + android:valueTo="@integer/config_language_on_spacebar_final_alpha" /> 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/caution.png b/java/res/drawable-hdpi/caution.png Binary files differdeleted file mode 100644 index 61eb4dd62..000000000 --- a/java/res/drawable-hdpi/caution.png +++ /dev/null diff --git a/java/res/drawable-hdpi/ic_mic_dialog.png b/java/res/drawable-hdpi/ic_mic_dialog.png Binary files differdeleted file mode 100644 index 6107f876e..000000000 --- a/java/res/drawable-hdpi/ic_mic_dialog.png +++ /dev/null diff --git a/java/res/drawable-hdpi/ic_suggest_strip_microphone.png b/java/res/drawable-hdpi/ic_suggest_strip_microphone.png Binary files differdeleted file mode 100644 index 189a861fb..000000000 --- a/java/res/drawable-hdpi/ic_suggest_strip_microphone.png +++ /dev/null diff --git a/java/res/drawable-hdpi/ic_suggest_strip_microphone_swipe.png b/java/res/drawable-hdpi/ic_suggest_strip_microphone_swipe.png Binary files differdeleted file mode 100644 index b4a6e373b..000000000 --- a/java/res/drawable-hdpi/ic_suggest_strip_microphone_swipe.png +++ /dev/null diff --git a/java/res/drawable-hdpi/mic_base.png b/java/res/drawable-hdpi/mic_base.png Binary files differdeleted file mode 100644 index 504a1aa2a..000000000 --- a/java/res/drawable-hdpi/mic_base.png +++ /dev/null diff --git a/java/res/drawable-hdpi/mic_full.png b/java/res/drawable-hdpi/mic_full.png Binary files differdeleted file mode 100644 index 3f4a67657..000000000 --- a/java/res/drawable-hdpi/mic_full.png +++ /dev/null diff --git a/java/res/drawable-hdpi/mic_slash.png b/java/res/drawable-hdpi/mic_slash.png Binary files differdeleted file mode 100644 index c3b10929b..000000000 --- a/java/res/drawable-hdpi/mic_slash.png +++ /dev/null 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-hdpi/sym_keyboard_zwj_holo.png b/java/res/drawable-hdpi/sym_keyboard_zwj_holo.png Binary files differnew file mode 100644 index 000000000..5fa30ceb8 --- /dev/null +++ b/java/res/drawable-hdpi/sym_keyboard_zwj_holo.png diff --git a/java/res/drawable-hdpi/sym_keyboard_zwnj_holo.png b/java/res/drawable-hdpi/sym_keyboard_zwnj_holo.png Binary files differnew file mode 100644 index 000000000..91367f3d2 --- /dev/null +++ b/java/res/drawable-hdpi/sym_keyboard_zwnj_holo.png diff --git a/java/res/drawable-hdpi/vs_dialog_blue.9.png b/java/res/drawable-hdpi/vs_dialog_blue.9.png Binary files differdeleted file mode 100644 index 4f813ead3..000000000 --- a/java/res/drawable-hdpi/vs_dialog_blue.9.png +++ /dev/null diff --git a/java/res/drawable-hdpi/vs_dialog_red.9.png b/java/res/drawable-hdpi/vs_dialog_red.9.png Binary files differdeleted file mode 100644 index a2055600e..000000000 --- a/java/res/drawable-hdpi/vs_dialog_red.9.png +++ /dev/null diff --git a/java/res/drawable-hdpi/vs_dialog_yellow.9.png b/java/res/drawable-hdpi/vs_dialog_yellow.9.png Binary files differdeleted file mode 100644 index ce664b676..000000000 --- a/java/res/drawable-hdpi/vs_dialog_yellow.9.png +++ /dev/null diff --git a/java/res/drawable-hdpi/vs_popup_mic_edge.png b/java/res/drawable-hdpi/vs_popup_mic_edge.png Binary files differdeleted file mode 100644 index 4ff6337a2..000000000 --- a/java/res/drawable-hdpi/vs_popup_mic_edge.png +++ /dev/null diff --git a/java/res/drawable-mdpi/caution.png b/java/res/drawable-mdpi/caution.png Binary files differdeleted file mode 100644 index eaef53425..000000000 --- a/java/res/drawable-mdpi/caution.png +++ /dev/null diff --git a/java/res/drawable-mdpi/ic_mic_dialog.png b/java/res/drawable-mdpi/ic_mic_dialog.png Binary files differdeleted file mode 100644 index 77613ca05..000000000 --- a/java/res/drawable-mdpi/ic_mic_dialog.png +++ /dev/null diff --git a/java/res/drawable-mdpi/ic_suggest_strip_microphone.png b/java/res/drawable-mdpi/ic_suggest_strip_microphone.png Binary files differdeleted file mode 100644 index 18f314a61..000000000 --- a/java/res/drawable-mdpi/ic_suggest_strip_microphone.png +++ /dev/null diff --git a/java/res/drawable-mdpi/ic_suggest_strip_microphone_swipe.png b/java/res/drawable-mdpi/ic_suggest_strip_microphone_swipe.png Binary files differdeleted file mode 100644 index ff629b674..000000000 --- a/java/res/drawable-mdpi/ic_suggest_strip_microphone_swipe.png +++ /dev/null diff --git a/java/res/drawable-mdpi/mic_base.png b/java/res/drawable-mdpi/mic_base.png Binary files differdeleted file mode 100644 index 53e29ff4b..000000000 --- a/java/res/drawable-mdpi/mic_base.png +++ /dev/null diff --git a/java/res/drawable-mdpi/mic_full.png b/java/res/drawable-mdpi/mic_full.png Binary files differdeleted file mode 100644 index e3e3dfac3..000000000 --- a/java/res/drawable-mdpi/mic_full.png +++ /dev/null diff --git a/java/res/drawable-mdpi/mic_slash.png b/java/res/drawable-mdpi/mic_slash.png Binary files differdeleted file mode 100644 index d04b56344..000000000 --- a/java/res/drawable-mdpi/mic_slash.png +++ /dev/null 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-mdpi/sym_keyboard_zwj_holo.png b/java/res/drawable-mdpi/sym_keyboard_zwj_holo.png Binary files differnew file mode 100644 index 000000000..70370d83d --- /dev/null +++ b/java/res/drawable-mdpi/sym_keyboard_zwj_holo.png diff --git a/java/res/drawable-mdpi/sym_keyboard_zwnj_holo.png b/java/res/drawable-mdpi/sym_keyboard_zwnj_holo.png Binary files differnew file mode 100644 index 000000000..a69eade17 --- /dev/null +++ b/java/res/drawable-mdpi/sym_keyboard_zwnj_holo.png diff --git a/java/res/drawable-mdpi/vs_dialog_blue.9.png b/java/res/drawable-mdpi/vs_dialog_blue.9.png Binary files differdeleted file mode 100644 index cf27e8f43..000000000 --- a/java/res/drawable-mdpi/vs_dialog_blue.9.png +++ /dev/null diff --git a/java/res/drawable-mdpi/vs_dialog_red.9.png b/java/res/drawable-mdpi/vs_dialog_red.9.png Binary files differdeleted file mode 100644 index 6c08d5a30..000000000 --- a/java/res/drawable-mdpi/vs_dialog_red.9.png +++ /dev/null diff --git a/java/res/drawable-mdpi/vs_dialog_yellow.9.png b/java/res/drawable-mdpi/vs_dialog_yellow.9.png Binary files differdeleted file mode 100644 index 2fb06c263..000000000 --- a/java/res/drawable-mdpi/vs_dialog_yellow.9.png +++ /dev/null diff --git a/java/res/drawable-mdpi/vs_popup_mic_edge.png b/java/res/drawable-mdpi/vs_popup_mic_edge.png Binary files differdeleted file mode 100644 index 4ff6337a2..000000000 --- a/java/res/drawable-mdpi/vs_popup_mic_edge.png +++ /dev/null diff --git a/java/res/drawable-xhdpi/caution.png b/java/res/drawable-xhdpi/caution.png Binary files differdeleted file mode 100644 index cfc3f7547..000000000 --- a/java/res/drawable-xhdpi/caution.png +++ /dev/null diff --git a/java/res/drawable-xhdpi/ic_mic_dialog.png b/java/res/drawable-xhdpi/ic_mic_dialog.png Binary files differdeleted file mode 100644 index 5d6399c0a..000000000 --- a/java/res/drawable-xhdpi/ic_mic_dialog.png +++ /dev/null diff --git a/java/res/drawable-xhdpi/ic_suggest_strip_microphone.png b/java/res/drawable-xhdpi/ic_suggest_strip_microphone.png Binary files differdeleted file mode 100644 index d65d28708..000000000 --- a/java/res/drawable-xhdpi/ic_suggest_strip_microphone.png +++ /dev/null diff --git a/java/res/drawable-xhdpi/ic_suggest_strip_microphone_swipe.png b/java/res/drawable-xhdpi/ic_suggest_strip_microphone_swipe.png Binary files differdeleted file mode 100644 index 889378a6a..000000000 --- a/java/res/drawable-xhdpi/ic_suggest_strip_microphone_swipe.png +++ /dev/null diff --git a/java/res/drawable-xhdpi/mic_base.png b/java/res/drawable-xhdpi/mic_base.png Binary files differdeleted file mode 100644 index 5c060bec9..000000000 --- a/java/res/drawable-xhdpi/mic_base.png +++ /dev/null diff --git a/java/res/drawable-xhdpi/mic_full.png b/java/res/drawable-xhdpi/mic_full.png Binary files differdeleted file mode 100644 index 32ffe124e..000000000 --- a/java/res/drawable-xhdpi/mic_full.png +++ /dev/null diff --git a/java/res/drawable-xhdpi/mic_slash.png b/java/res/drawable-xhdpi/mic_slash.png Binary files differdeleted file mode 100644 index 18b22542b..000000000 --- a/java/res/drawable-xhdpi/mic_slash.png +++ /dev/null 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-xhdpi/sym_keyboard_zwj_holo.png b/java/res/drawable-xhdpi/sym_keyboard_zwj_holo.png Binary files differnew file mode 100644 index 000000000..26694274e --- /dev/null +++ b/java/res/drawable-xhdpi/sym_keyboard_zwj_holo.png diff --git a/java/res/drawable-xhdpi/sym_keyboard_zwnj_holo.png b/java/res/drawable-xhdpi/sym_keyboard_zwnj_holo.png Binary files differnew file mode 100644 index 000000000..75a22b65f --- /dev/null +++ b/java/res/drawable-xhdpi/sym_keyboard_zwnj_holo.png diff --git a/java/res/drawable-xhdpi/vs_dialog_blue.9.png b/java/res/drawable-xhdpi/vs_dialog_blue.9.png Binary files differdeleted file mode 100644 index 3284d78ef..000000000 --- a/java/res/drawable-xhdpi/vs_dialog_blue.9.png +++ /dev/null diff --git a/java/res/drawable-xhdpi/vs_dialog_red.9.png b/java/res/drawable-xhdpi/vs_dialog_red.9.png Binary files differdeleted file mode 100644 index 5af2465b5..000000000 --- a/java/res/drawable-xhdpi/vs_dialog_red.9.png +++ /dev/null diff --git a/java/res/drawable-xhdpi/vs_dialog_yellow.9.png b/java/res/drawable-xhdpi/vs_dialog_yellow.9.png Binary files differdeleted file mode 100644 index 4f50439de..000000000 --- a/java/res/drawable-xhdpi/vs_dialog_yellow.9.png +++ /dev/null diff --git a/java/res/drawable-xhdpi/vs_popup_mic_edge.png b/java/res/drawable-xhdpi/vs_popup_mic_edge.png Binary files differdeleted file mode 100644 index 1063cb464..000000000 --- a/java/res/drawable-xhdpi/vs_popup_mic_edge.png +++ /dev/null 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-sw768dp/recognition_status.xml b/java/res/layout-sw768dp/recognition_status.xml deleted file mode 100644 index 40bc09823..000000000 --- a/java/res/layout-sw768dp/recognition_status.xml +++ /dev/null @@ -1,101 +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. -*/ ---> -<RelativeLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_height="wrap_content" - android:layout_width="match_parent" - android:background="@drawable/background_voice"> - <LinearLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/popup_layout" - android:orientation="vertical" - android:layout_height="371dip" - android:layout_width="500dip" - android:layout_centerInParent="true" - android:background="@drawable/vs_dialog_red"> - <TextView - android:id="@+id/text" - android:text="@string/voice_error" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:singleLine="true" - android:layout_marginTop="10dip" - android:textSize="28sp" - android:textColor="#ffffff" - android:layout_gravity="center" - android:visibility="invisible"/> - <RelativeLayout - android:layout_height="0dip" - android:layout_width="match_parent" - android:layout_weight="1.0"> - <com.android.inputmethod.deprecated.voice.SoundIndicator - android:id="@+id/sound_indicator" - android:src="@drawable/mic_full" - android:background="@drawable/mic_base" - android:adjustViewBounds="true" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:layout_centerInParent="true" - android:visibility="gone"/> - <ImageView - android:id="@+id/image" - android:src="@drawable/mic_slash" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:layout_centerInParent="true" - android:visibility="visible"/> - <ProgressBar - android:id="@+id/progress" - android:indeterminate="true" - android:indeterminateOnly="false" - android:layout_height="60dip" - android:layout_width="60dip" - android:layout_centerInParent="true" - android:visibility="gone"/> - </RelativeLayout> - <!-- - The text is set by the code. We specify a random text (voice_error), so the - text view does not have a zero height. This is necessary to keep the slash - mic and the recording mic is the same position - --> - <TextView - android:id="@+id/language" - android:text="@string/voice_error" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:singleLine="true" - android:textSize="14sp" - android:layout_marginBottom="3dip" - android:layout_gravity="center" - android:textColor="#ffffff" - android:visibility="invisible"/> - <Button - android:id="@+id/button" - android:layout_width="match_parent" - android:layout_height="54dip" - android:singleLine="true" - android:focusable="true" - android:text="@string/cancel" - android:layout_gravity="center_horizontal" - android:background="@drawable/btn_center" - android:textColor="#ffffff" - android:textSize="19sp" /> - </LinearLayout> -</RelativeLayout> diff --git a/java/res/layout/hint_add_to_dictionary.xml b/java/res/layout/hint_add_to_dictionary.xml new file mode 100644 index 000000000..73de44fae --- /dev/null +++ b/java/res/layout/hint_add_to_dictionary.xml @@ -0,0 +1,36 @@ +<?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. +*/ +--> + +<!-- This is derived from suggestion_word.xml without minWidth attribute and padding --> +<TextView + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:textSize="@dimen/suggestion_text_size" + android:gravity="center" + android:paddingLeft="0dp" + android:paddingTop="0dp" + android:paddingRight="0dp" + android:paddingBottom="0dp" + android:focusable="false" + android:clickable="false" + android:singleLine="true" + android:ellipsize="none" + style="?attr/suggestionBackgroundStyle" /> diff --git a/java/res/layout/input_view.xml b/java/res/layout/input_view.xml index 198e4ca4a..3863534be 100644 --- a/java/res/layout/input_view.xml +++ b/java/res/layout/input_view.xml @@ -28,7 +28,7 @@ <View android:id="@+id/key_preview_backing" android:layout_width="match_parent" - android:layout_height="0dip" /> + android:layout_height="0dp" /> <!-- 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/key_preview.xml b/java/res/layout/key_preview.xml index b620d07d8..6ed892e28 100644 --- a/java/res/layout/key_preview.xml +++ b/java/res/layout/key_preview.xml @@ -20,8 +20,8 @@ <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" - android:layout_height="80sp" - android:textSize="40sp" - android:minWidth="32dip" + android:layout_height="80dp" + android:textSize="40dp" + android:minWidth="32dp" android:gravity="center" /> diff --git a/java/res/layout/mini_keyboard.xml b/java/res/layout/more_keys_keyboard.xml index 6964ec5d6..6b2464b99 100644 --- a/java/res/layout/mini_keyboard.xml +++ b/java/res/layout/more_keys_keyboard.xml @@ -22,12 +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:layout_alignParentBottom="true" + 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 6aa82e197..49a00c6b5 100644 --- a/java/res/layout/more_suggestions.xml +++ b/java/res/layout/more_suggestions.xml @@ -22,12 +22,11 @@ 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_alignParentBottom="true" android:layout_width="wrap_content" android:layout_height="wrap_content" latin:keyLabelSize="@dimen/suggestion_text_size" diff --git a/java/res/layout/recognition_status.xml b/java/res/layout/recognition_status.xml deleted file mode 100644 index a2ddb7c50..000000000 --- a/java/res/layout/recognition_status.xml +++ /dev/null @@ -1,102 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2009, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> -<RelativeLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_height="wrap_content" - android:layout_width="match_parent" - android:background="@drawable/background_voice"> - <LinearLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/popup_layout" - android:orientation="vertical" - android:layout_height="371dip" - android:layout_width="500dip" - android:layout_centerInParent="true" - android:background="@drawable/vs_dialog_red"> - <TextView - android:id="@+id/text" - android:text="@string/voice_error" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:singleLine="true" - android:layout_marginTop="10dip" - android:textSize="20sp" - android:textColor="#ffffff" - android:layout_gravity="center" - android:visibility="invisible"/> - <RelativeLayout - android:layout_height="0dip" - android:layout_width="match_parent" - android:layout_weight="1.0"> - <com.android.inputmethod.deprecated.voice.SoundIndicator - android:id="@+id/sound_indicator" - android:src="@drawable/mic_full" - android:background="@drawable/mic_base" - android:adjustViewBounds="true" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:layout_centerInParent="true" - android:visibility="gone"/> - <ImageView - android:id="@+id/image" - android:src="@drawable/mic_slash" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:layout_centerInParent="true" - android:visibility="visible"/> - <ProgressBar - android:id="@+id/progress" - android:indeterminate="true" - android:indeterminateOnly="false" - android:layout_height="60dip" - android:layout_width="60dip" - android:layout_centerInParent="true" - android:visibility="gone"/> - </RelativeLayout> - <!-- - The text is set by the code. We specify a random text (voice_error), so the - text view does not have a zero height. This is necessary to keep the slash - mic and the recording mic is the same position - --> - <TextView - android:id="@+id/language" - android:text="@string/voice_error" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:singleLine="true" - android:textSize="15sp" - android:layout_marginTop="3dip" - android:layout_marginBottom="3dip" - android:layout_gravity="center" - android:textColor="#ffffff" - android:visibility="invisible"/> - <Button - android:id="@+id/button" - android:layout_width="match_parent" - android:layout_height="30dip" - android:singleLine="true" - android:focusable="true" - android:text="@string/cancel" - android:layout_gravity="center_horizontal" - android:background="@drawable/btn_center" - android:textColor="#ffffff" - android:textSize="15sp" /> - </LinearLayout> -</RelativeLayout> diff --git a/java/res/layout/sound_effect_volume_dialog.xml b/java/res/layout/sound_effect_volume_dialog.xml index c5b2f10e2..294663006 100644 --- a/java/res/layout/sound_effect_volume_dialog.xml +++ b/java/res/layout/sound_effect_volume_dialog.xml @@ -23,22 +23,22 @@ android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_margin="10dip"> + android:layout_margin="10dp"> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" - android:layout_margin="10dip"> + android:layout_margin="10dp"> <TextView android:id="@+id/sound_effect_volume_value" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textSize="20dip"/> + android:textSize="20dp"/> </LinearLayout> <SeekBar android:id="@+id/sound_effect_volume_bar" android:layout_width="match_parent" android:layout_height="wrap_content" android:max="100" - android:layout_margin="10dip"/> + android:layout_margin="10dp"/> </LinearLayout> diff --git a/java/res/layout/suggestion_info.xml b/java/res/layout/suggestion_info.xml index a364d46aa..a4ad6df25 100644 --- a/java/res/layout/suggestion_info.xml +++ b/java/res/layout/suggestion_info.xml @@ -22,6 +22,6 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textSize="6sp" + android:textSize="6dp" android:textColor="@android:color/white" style="?attr/suggestionBackgroundStyle" /> diff --git a/java/res/layout/suggestion_preview.xml b/java/res/layout/suggestion_preview.xml index 3c026ae0e..856447bba 100644 --- a/java/res/layout/suggestion_preview.xml +++ b/java/res/layout/suggestion_preview.xml @@ -21,8 +21,8 @@ <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textSize="18sp" + android:textSize="18dp" android:textColor="?android:attr/textColorPrimaryInverse" - android:minWidth="32dip" + android:minWidth="32dp" android:gravity="center" style="?attr/suggestionPreviewBackgroundStyle" /> diff --git a/java/res/layout/vibration_settings_dialog.xml b/java/res/layout/vibration_settings_dialog.xml index 981ba9be0..c9fb6ec4e 100644 --- a/java/res/layout/vibration_settings_dialog.xml +++ b/java/res/layout/vibration_settings_dialog.xml @@ -23,27 +23,27 @@ android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_margin="10dip"> + android:layout_margin="10dp"> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" - android:layout_margin="10dip"> + android:layout_margin="10dp"> <TextView android:id="@+id/vibration_value" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textSize="20dip"/> + android:textSize="20dp"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/settings_ms" - android:textSize="20dip"/> + android:textSize="20dp"/> </LinearLayout> <SeekBar android:id="@+id/vibration_settings" android:layout_width="match_parent" android:layout_height="wrap_content" android:max="250" - android:layout_margin="10dip"/> + android:layout_margin="10dp"/> </LinearLayout> diff --git a/java/res/layout/voice_punctuation_hint.xml b/java/res/layout/voice_punctuation_hint.xml deleted file mode 100644 index 629a7f2b5..000000000 --- a/java/res/layout/voice_punctuation_hint.xml +++ /dev/null @@ -1,49 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2009, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<LinearLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:orientation="horizontal" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:background="@drawable/keyboard_suggest_strip"> - - <!-- TODO: Use dark mic icon. --> - <ImageView android:id="@+id/image" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:paddingLeft="8dip" - android:paddingRight="8dip" - android:layout_gravity="center_horizontal" - android:src="@drawable/ic_suggest_strip_microphone" - /> - - <TextView android:id="@+id/text" - android:text="@string/voice_punctuation_hint" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:paddingTop="2dip" - android:paddingRight="3dip" - android:textSize="13sp" - android:textColor="#888888" - android:layout_gravity="center_horizontal" - /> - -</LinearLayout> diff --git a/java/res/layout/voice_swipe_hint.xml b/java/res/layout/voice_swipe_hint.xml deleted file mode 100644 index 4e8859a71..000000000 --- a/java/res/layout/voice_swipe_hint.xml +++ /dev/null @@ -1,56 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* -** -** Copyright 2009, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<LinearLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:orientation="horizontal" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:background="@drawable/keyboard_suggest_strip" - android:gravity="center_horizontal" - android:paddingTop="2dip"> - - <TextView android:id="@+id/text" - android:text="@string/voice_swipe_hint" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:paddingTop="10dip" - android:paddingRight="6dip" - android:textSize="13sp" - android:textColor="#888888" - android:layout_gravity="center_horizontal" - /> - - <ImageView - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:layout_gravity="center_horizontal" - android:src="@drawable/ic_suggest_strip_microphone" - /> - - <ImageView - android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:layout_gravity="center_horizontal" - android:src="@drawable/ic_suggest_strip_microphone_swipe" - /> - - -</LinearLayout> diff --git a/java/res/values-af/strings.xml b/java/res/values-af/strings.xml index 4c45efeac..b2525ad2d 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,46 +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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Om steminvoer af te skakel, gaan na invoermetode-instellings."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Om steminvoer te gebruik, druk die mikrofoonknoppie."</string> - <string name="voice_listening" msgid="467518160751321844">"Praat nou"</string> - <string name="voice_working" msgid="6666937792815731889">"Werkend"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Fout. Probeer asseblief weer."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Kon nie koppel nie"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Fout, te veel spraak."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Oudioprobleem"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Bedienerfout"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Geen spraak gehoor nie"</string> - <string name="voice_no_match" msgid="4285117547030179174">"Geen passings gevind nie"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Stemsoek nie geïnstalleer nie"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Wenk:"</b>" Sleep oor die sleutelbord om te praat"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Wenk:"</b>" Probeer volgende keer om leestekens soos \"punt\", \"komma\" of \"vraagteken\" hardop te sê."</string> - <string name="cancel" msgid="6830980399865683324">"Kanselleer"</string> - <string name="ok" msgid="7898366843681727667">"OK"</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_input" msgid="3583258583521397548">"Steminvoerinstellings"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Op hoofsleutelbord"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Op simbolesleutelbord"</string> @@ -135,16 +108,14 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikrofoon op hoofsleutelbord"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikrofoon op simbolesleutelbord"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Steminvoer is gedeaktiveer"</string> - <string name="selectInputMethod" msgid="315076553378705821">"Kies invoermetode"</string> <string name="configure_input_method" msgid="373356270290742459">"Stel invoermetodes op"</string> <string name="language_selection_title" msgid="1651299598555326750">"Invoertale"</string> <string name="select_language" msgid="3693815588777926848">"Invoertale"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Raak weer om te stoor"</string> + <string name="hint_add_to_dictionary" msgid="573678656946085380">"Raak weer om te stoor"</string> <string name="has_dictionary" msgid="6071847973466625007">"Woordeboek beskikbaar"</string> <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> diff --git a/java/res/values-am/strings.xml b/java/res/values-am/strings.xml index d5280bc64..927956851 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,46 +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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"የድምፅ ግቤት ለማጥፋት፣ወደ ግቤት ሜተድ ቅንብሮች ሂድ።"</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"የድምፅግቤት ለመጠቀም፣ የማይክራፎንየድምፅ ማጉያ አዝራር ተጫን።"</string> - <string name="voice_listening" msgid="467518160751321844">"አሁን ተናገር"</string> - <string name="voice_working" msgid="6666937792815731889">"ሥራ ላይ"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"ስህተት፣ እባክዎ እንደገና ይሞክሩ።"</string> - <string name="voice_network_error" msgid="6649556447401862563">"ማያያዝ አልተቻለም"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"ስህተት፣ በጣም ብዙ ንግግር።"</string> - <string name="voice_audio_error" msgid="5072707727016414454">"የድምፅ ችግር"</string> - <string name="voice_server_error" msgid="7807129913977261644">"የአገልጋይ ስህተት"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"ምንም ንግግር አልተሰማም"</string> - <string name="voice_no_match" msgid="4285117547030179174">"ምንም ተመሳሳይ አልተገኘም።"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"የድምፅ ፍለጋአልተጫነም"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"ምክር፡"</b>" ለመናገር በቁልፍሰሌዳ ላይ አንሸራት"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"ምክር፡"</b>" ሌላ ጊዜ፣ እንደ \"period\", \"comma\", ወይም \"question mark\" ያሉ ስርዓተ ነጥቦችን ለመናገር ሞክር።"</string> - <string name="cancel" msgid="6830980399865683324">"ይቅር"</string> - <string name="ok" msgid="7898366843681727667">"እሺ"</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_input" msgid="3583258583521397548">"የድምፅ ግቤት ቁልፍ"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"በዋናቁልፍ ሰሌዳ ላይ"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"በምልክቶች ቁልፍ ሰሌዳ ላይ"</string> @@ -135,16 +108,14 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"ድምፅ ማጉያ በዋናው ቁልፍሰሌዳው ላይ"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"የድምፅ ማጉያ ምልክትበቁልፍ ሰሌዳላይ"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"የድምፅ ግቤት ቦዝኗል"</string> - <string name="selectInputMethod" msgid="315076553378705821">"የግቤት ሜተድ ምረጥ"</string> <string name="configure_input_method" msgid="373356270290742459">"ግቤት ሜተዶችን አዋቀር"</string> <string name="language_selection_title" msgid="1651299598555326750">"ቋንቋዎች አግቤት"</string> <string name="select_language" msgid="3693815588777926848">"ቋንቋዎች አግቤት"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← ለማስቀመጥ ድጋሚ ንካ"</string> + <string name="hint_add_to_dictionary" msgid="573678656946085380">"ለማስቀመጥ እንደገና ንካ"</string> <string name="has_dictionary" msgid="6071847973466625007">"መዝገበ ቃላት አለ"</string> <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-fr-rCA/donottranslate-more-keys.xml b/java/res/values-ar/donottranslate.xml index 80e9d9346..57de2538b 100644 --- a/java/res/values-fr-rCA/donottranslate-more-keys.xml +++ b/java/res/values-ar/donottranslate.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,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> + <!-- 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..9daa01220 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,46 +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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"لإيقاف الإدخال الصوتي، انتقل إلى إعدادات طريقة الإدخال."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"لاستخدام الإدخال الصوتي، اضغط على زر الميكروفون."</string> - <string name="voice_listening" msgid="467518160751321844">"تحدث الآن"</string> - <string name="voice_working" msgid="6666937792815731889">"العمل"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"خطأ. الرجاء المحاولة مرة أخرى."</string> - <string name="voice_network_error" msgid="6649556447401862563">"تعذر الاتصال"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"خطأ، كلام أكثر مما ينبغي."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"مشكلة بالإعدادات الصوتية"</string> - <string name="voice_server_error" msgid="7807129913977261644">"خطأ في الخادم"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"لم يتم سماع كلام"</string> - <string name="voice_no_match" msgid="4285117547030179174">"لم يتمّ العثور على أية تطابقات"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"لم يتم تثبيت البحث الصوتي"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"تلميح:"</b>" مرر عبر لوحة المفاتيح للتحدث"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"تلميح:"</b>" جرب في المرة التالية نطق الترقيم مثل \"نقطة\" أو \"فاصلة\" أو \"علامة استفهام\"."</string> - <string name="cancel" msgid="6830980399865683324">"إلغاء"</string> - <string name="ok" msgid="7898366843681727667">"موافق"</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_input" msgid="3583258583521397548">"مفتاح الإدخال الصوتي"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"لوحة مفاتيح رئيسية"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"لوحة مفاتيح الرموز"</string> @@ -135,16 +108,15 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"ميكروفون على لوحة مفاتيح رئيسية"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"ميكروفون على لوحة مفاتيح الرموز"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"الإدخال الصوتي مُعطل"</string> - <string name="selectInputMethod" msgid="315076553378705821">"تحديد طريقة الإرسال"</string> <string name="configure_input_method" msgid="373356270290742459">"تهيئة طرق الإدخال"</string> <string name="language_selection_title" msgid="1651299598555326750">"لغات الإدخال"</string> <string name="select_language" msgid="3693815588777926848">"لغات الإدخال"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← المس مرة أخرى للحفظ"</string> + <!-- no translation found for hint_add_to_dictionary (573678656946085380) --> + <skip /> <string name="has_dictionary" msgid="6071847973466625007">"القاموس متاح"</string> <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-be/donottranslate-more-keys.xml b/java/res/values-be/donottranslate-more-keys.xml new file mode 100644 index 000000000..835553a1f --- /dev/null +++ b/java/res/values-be/donottranslate-more-keys.xml @@ -0,0 +1,31 @@ +<?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+045E: "ў" CYRILLIC SMALL LETTER SHORT U --> + <string name="keylabel_for_east_slavic_row1_9">ў</string> + <!-- U+044B: "ы" CYRILLIC SMALL LETTER YERU --> + <string name="keylabel_for_east_slavic_row2_1">ы</string> + <!-- U+0456: "і" CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I --> + <string name="keylabel_for_east_slavic_row3_5">і</string> + <!-- U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN --> + <string name="more_keys_for_cyrillic_ha">ъ</string> + <!-- U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN --> + <string name="more_keys_for_cyrillic_soft_sign">ъ</string> +</resources> diff --git a/java/res/values-be/strings.xml b/java/res/values-be/strings.xml index 1ed944caf..ab00be926 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,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">"Функцыi для спецыялістаў"</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">"Кнопка пераключэння мовы звязана i з iншымi спосабамi ўводу"</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"Забаранiць кнопку пераключэння мовы"</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">"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,46 +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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Каб адключыць галасавы ўвод, перайдзіце ў налады метаду ўводу."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Каб выкарыстоўваць галасавы ўвод, націсніце кнопку мікрафона."</string> - <string name="voice_listening" msgid="467518160751321844">"Гаварыце"</string> - <string name="voice_working" msgid="6666937792815731889">"Апрацоўка"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Памылка. Паспрабуйце яшчэ."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Не атрымалася ўсталяваць падключэнне"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Памылка, зашмат гаворкі."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Праблема з гукам"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Памылка сервера"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Не чуваць гаворку"</string> - <string name="voice_no_match" msgid="4285117547030179174">"Няма супадзенняў"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Галасавы пошук не ўсталяваны"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Падказка:"</b>" Правядзіце пальцам праз клавіятуру, каб казаць"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Падказка:"</b>" У наступны раз паспрабуйце прагаворваць такiя знакі пунктуацыі, як \"кропка\", \"коска\" або \"пытальнік\"."</string> - <string name="cancel" msgid="6830980399865683324">"Адмяніць"</string> - <string name="ok" msgid="7898366843681727667">"ОК"</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_input" msgid="3583258583521397548">"Ключ галасавога ўводу"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"На асн. клавіятуры"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"На сімв. клавіятуры"</string> @@ -135,16 +108,15 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Мік. на асн. клав."</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Мік. на сімв. клав."</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Галасавы набор адкл."</string> - <string name="selectInputMethod" msgid="315076553378705821">"Выберыце метад уводу"</string> <string name="configure_input_method" msgid="373356270290742459">"Налада метадаў уводу"</string> <string name="language_selection_title" msgid="1651299598555326750">"Мовы ўводу"</string> <string name="select_language" msgid="3693815588777926848">"Мовы ўводу"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"... Дакраніцеся яшчэ раз, каб захаваць"</string> + <!-- no translation found for hint_add_to_dictionary (573678656946085380) --> + <skip /> <string name="has_dictionary" msgid="6071847973466625007">"Слоўнік даступны"</string> <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..c7c7a2510 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,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">"Код на клавиш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,46 +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">"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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"За да изключите гласовото въвеждане, отворете настройките за метода за въвеждане."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"За да използвате гласово въвеждане, натиснете бутона на микрофона."</string> - <string name="voice_listening" msgid="467518160751321844">"Говорете сега"</string> - <string name="voice_working" msgid="6666937792815731889">"Обработва се"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Грешка. Моля, опитайте отново."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Не можа да се свърже"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Грешка, твърде много речева информация."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Аудиопроблем"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Грешка в сървъра"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Не се чува реч"</string> - <string name="voice_no_match" msgid="4285117547030179174">"Нямаше съответствия"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Не е инсталирано гласово търсене"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Съвет:"</b>" Прокарайте палец през клавиатурата, за да говорите"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Съвет:"</b>" Следващия път опитайте да произнесете знаците за пунктуация, напр. „точка“, „запетая“ или „въпросителен знак“."</string> - <string name="cancel" msgid="6830980399865683324">"Отказ"</string> - <string name="ok" msgid="7898366843681727667">"OK"</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_input" msgid="3583258583521397548">"Клавиш за гласово въвеждане"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"На осн. клавиатура"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"На клав. на симв."</string> @@ -135,16 +108,15 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Микр. на осн. клав."</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Микр. на клав. на симв."</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Глас. въвежд. е деакт."</string> - <string name="selectInputMethod" msgid="315076553378705821">"Избор на метод на въвеждане"</string> <string name="configure_input_method" msgid="373356270290742459">"Конфигуриране на въвеждането"</string> <string name="language_selection_title" msgid="1651299598555326750">"Входни езици"</string> <string name="select_language" msgid="3693815588777926848">"Езици за въвеждане"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Докоснете отново, за да запазите"</string> + <!-- no translation found for hint_add_to_dictionary (573678656946085380) --> + <skip /> <string name="has_dictionary" msgid="6071847973466625007">"Има достъп до речник"</string> <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..a530ac16e 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,10 @@ <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> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Canvia mètode d\'entrada"</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"La tecla de canvi d\'idioma també cobreix altres mètodes d\'entrada"</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"Suprimeix tecla d\'idioma"</string> <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 +55,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 +68,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 +81,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,46 +93,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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Per desactivar l\'entada de veu, vés a la configuració del mètode d\'entrada."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Per utilitzar l\'entrada de veu, prem el botó del micròfon."</string> - <string name="voice_listening" msgid="467518160751321844">"Parleu ara"</string> - <string name="voice_working" msgid="6666937792815731889">"S\'està treballant"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Error. Torneu-ho a provar."</string> - <string name="voice_network_error" msgid="6649556447401862563">"No s\'ha pogut connectar"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Error; s\'ha parlat massa."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Problema d\'àudio"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Error del servidor"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"No s\'escolten paraules"</string> - <string name="voice_no_match" msgid="4285117547030179174">"No hi ha resultats"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Cerca per veu no instal·lada"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Consell:"</b>" Feu lliscar el dit pel teclat per parlar"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Suggeriment:"</b>" La propera vegada, proveu de dir la puntuació, com ara \"punt\", \"coma\" o \"interrogant\"."</string> - <string name="cancel" msgid="6830980399865683324">"Cancel·la"</string> - <string name="ok" msgid="7898366843681727667">"D\'acord"</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_input" msgid="3583258583521397548">"Clau de l\'entrada de veu"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Al teclat principal"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Al tecl. de símb."</string> @@ -135,16 +108,14 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Micro en tecl. princ."</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Micro en tecl. símb."</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Entr. veu desactiv."</string> - <string name="selectInputMethod" msgid="315076553378705821">"Selecciona el mètode d\'entrada"</string> <string name="configure_input_method" msgid="373356270290742459">"Configura mètodes d\'entrada"</string> <string name="language_selection_title" msgid="1651299598555326750">"Idiomes d\'entrada"</string> <string name="select_language" msgid="3693815588777926848">"Idiomes d\'entrada"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Torna a tocar per desar"</string> + <string name="hint_add_to_dictionary" msgid="573678656946085380">"Torna a tocar per desar"</string> <string name="has_dictionary" msgid="6071847973466625007">"Diccionari disponible"</string> <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..0e7ad8bbc 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,10 @@ <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> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Přep. na jiné metody zad."</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Klávesa pro přepínání jazyka ovládá i další metody zadávání"</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"Zakázat kl. přep. jazyka"</string> <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 +55,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 +68,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 +81,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,46 +93,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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Chcete-li vypnout hlasový vstup, přejděte do nastavení metod vstupu."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Chcete-li použít hlasový vstup, stiskněte tlačítko mikrofonu."</string> - <string name="voice_listening" msgid="467518160751321844">"Mluvte"</string> - <string name="voice_working" msgid="6666937792815731889">"Probíhá zpracování"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Chyba. Zkuste to prosím znovu."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Připojení se nezdařilo."</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Chyba, řeč je příliš dlouhá."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Problém se zvukem"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Chyba serveru"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Nebyla detekována žádná řeč."</string> - <string name="voice_no_match" msgid="4285117547030179174">"Nebyly nalezeny žádné shody"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Hlasové vyhledávání není nainstalováno"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Nápověda:"</b>" Chcete-li aktivovat hlasový vstup, přejeďte prstem přes klávesnici."</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Nápověda:"</b>" Příště zkuste vyslovit interpunkci, například „tečka“, „čárka“ nebo „otazník“."</string> - <string name="cancel" msgid="6830980399865683324">"Zrušit"</string> - <string name="ok" msgid="7898366843681727667">"OK"</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_input" msgid="3583258583521397548">"Klíč hlasového vstupu"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Na hlavní klávesnici"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Na klávesnici se symb."</string> @@ -135,16 +108,15 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikr. na hlav. kláv."</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikr. na kláv. se symb."</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Hlasový vstup vypnut"</string> - <string name="selectInputMethod" msgid="315076553378705821">"Výběr metody zadávání dat"</string> <string name="configure_input_method" msgid="373356270290742459">"Konfigurace metod vstupu"</string> <string name="language_selection_title" msgid="1651299598555326750">"Vstupní jazyky"</string> <string name="select_language" msgid="3693815588777926848">"Jazyky vstupu"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Dalším dotykem slovo uložíte"</string> + <!-- no translation found for hint_add_to_dictionary (573678656946085380) --> + <skip /> <string name="has_dictionary" msgid="6071847973466625007">"K dispozici je slovník"</string> <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..acc0c534d 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_nordic_row1_11">å</string> + <!-- U+00E6: "æ" LATIN SMALL LETTER AE --> + <string name="keylabel_for_nordic_row2_10">æ</string> + <!-- U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE --> + <string name="keylabel_for_nordic_row2_11">ø</string> + <!-- U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS --> + <string name="more_keys_for_nordic_row2_10">ä</string> + <!-- U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS --> + <string name="more_keys_for_nordic_row2_11">ö</string> </resources> diff --git a/java/res/values-da/strings.xml b/java/res/values-da/strings.xml index b91acaa90..cccd088da 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,10 @@ <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> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Skift inputmetode"</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Tasten til sprogskift gælder også for andre inputmetoder"</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"Ignorer sprogskifttast"</string> <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 +55,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 +68,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 +81,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,46 +93,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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Slå stemmeinput fra i indstillingerne for inputmetode."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Brug stemmeinput ved at trykke på mikrofonknappen."</string> - <string name="voice_listening" msgid="467518160751321844">"Tal nu"</string> - <string name="voice_working" msgid="6666937792815731889">"Arbejder"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Fejl. Prøv igen."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Kunne ikke oprette forbindelse"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Fejl. For meget tale."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Lydproblem"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Serverfejl"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Der høres ingen tale"</string> - <string name="voice_no_match" msgid="4285117547030179174">"Der blev ikke fundet nogen matches"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Stemmesøgning er ikke installeret"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Tip:"</b>" Glid hen over tastaturet for at tale"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Tip:"</b>" Næste gang kan du forsøge at sige tegnsætning, f.eks. \"punktum\", \"komma\" eller \"spørgsmålstegn\"."</string> - <string name="cancel" msgid="6830980399865683324">"Annuller"</string> - <string name="ok" msgid="7898366843681727667">"OK"</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_input" msgid="3583258583521397548">"Nøgle til stemmeinput"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"På hovedtastatur"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"På symboltastatur"</string> @@ -135,16 +108,14 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mik. på hovedtastatur"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mik. på symboltastatur"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Stemmeinput deaktiveret"</string> - <string name="selectInputMethod" msgid="315076553378705821">"Vælg inputmetode"</string> <string name="configure_input_method" msgid="373356270290742459">"Konfigurer inputmetoder"</string> <string name="language_selection_title" msgid="1651299598555326750">"Inputsprog"</string> <string name="select_language" msgid="3693815588777926848">"Inputsprog"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Tryk igen for at gemme"</string> + <string name="hint_add_to_dictionary" msgid="573678656946085380">"Tryk igen for at gemme"</string> <string name="has_dictionary" msgid="6071847973466625007">"Ordbog er tilgængelig"</string> <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/config.xml b/java/res/values-de/donottranslate-config.xml index 272ff326f..272ff326f 100644 --- a/java/res/values-de/config.xml +++ b/java/res/values-de/donottranslate-config.xml 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..cf0678165 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,10 @@ <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> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Eingabemethoden wechseln"</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Sprachwechseltaste umfasst auch andere Eingabemethoden."</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"Sprachwechsel unterdrücken"</string> <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 +55,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 +68,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 +81,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,46 +93,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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Rufen Sie zum Deaktivieren der Spracheingabe die Einstellungen für die Eingabemethode auf."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Drücken Sie zur Verwendung der Spracheingabe die Mikrofonschaltfläche."</string> - <string name="voice_listening" msgid="467518160751321844">"Jetzt sprechen"</string> - <string name="voice_working" msgid="6666937792815731889">"Vorgang läuft"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Fehler. Versuchen Sie es erneut.."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Keine Verbindung"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Fehler – Text zu lang"</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Audio-Problem"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Serverfehler"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Keine Sprache zu hören"</string> - <string name="voice_no_match" msgid="4285117547030179174">"Keine Treffer gefunden"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Sprachsuche nicht installiert"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Hinweis:"</b>" Ziehen Sie zum Sprechen den Finger über die Tastatur."</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Hinweis:"</b>" Versuchen Sie beim nächsten Mal, Satzzeichen wie \"Punkt\", \"Komma\" oder \"Fragezeichen\" per Sprachbefehl einzugeben."</string> - <string name="cancel" msgid="6830980399865683324">"Abbrechen"</string> - <string name="ok" msgid="7898366843681727667">"OK"</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_input" msgid="3583258583521397548">"Taste für Spracheingabe"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Auf Haupttastatur"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Auf Symboltastatur"</string> @@ -135,16 +108,14 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikro auf Haupttastatur"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikro auf Symboltastatur"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Spracheingabe deaktiviert"</string> - <string name="selectInputMethod" msgid="315076553378705821">"Eingabemethode auswählen"</string> <string name="configure_input_method" msgid="373356270290742459">"Eingabemethoden konfigurieren"</string> <string name="language_selection_title" msgid="1651299598555326750">"Eingabesprachen"</string> <string name="select_language" msgid="3693815588777926848">"Eingabesprachen"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Zum Speichern erneut berühren"</string> + <string name="hint_add_to_dictionary" msgid="573678656946085380">"Zum Speichern erneut berühren"</string> <string name="has_dictionary" msgid="6071847973466625007">"Wörterbuch verfügbar"</string> <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..da0cb3680 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,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">"Πλήκτρο Delete"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Σύμβολα"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Γράμματα:"</string> @@ -88,46 +93,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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Για να απενεργοποιήσετε τις φωνητικές εντολές, μεταβείτε στις ρυθμίσεις της μεθόδου εισαγωγής."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Για τη χρήση φωνητικών εντολών, πατήστε το κουμπί του μικροφώνου."</string> - <string name="voice_listening" msgid="467518160751321844">"Μιλήστε τώρα"</string> - <string name="voice_working" msgid="6666937792815731889">"Σε λειτουργία"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Σφάλμα. Δοκιμάστε ξανά."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Δεν ήταν δυνατή η σύνδεση"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Σφάλμα, πολλές λέξεις."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Πρόβλημα ήχου"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Σφάλμα διακομιστή"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Δεν ακούγεται ομιλία"</string> - <string name="voice_no_match" msgid="4285117547030179174">"Δεν βρέθηκε καμία αντιστοίχιση"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Η Φωνητική αναζήτηση δεν εγκαταστάθηκε"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Υπόδειξη:"</b>" Σύρετε κατά μήκος του πληκτρολογίου για να μιλήσετε"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Υπόδειξη:"</b>" Την επόμενη φορά, προσπαθήστε να προφέρετε σημεία στίξης, όπως \"τελεία\", \"κόμμα\" ή \"ερωτηματικό\"."</string> - <string name="cancel" msgid="6830980399865683324">"Ακύρωση"</string> - <string name="ok" msgid="7898366843681727667">"ΟΚ"</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_input" msgid="3583258583521397548">"Κλειδί φωνητικής εξόδου"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Στο κύριο πληκτρολ."</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Πληκτρ. συμβ. ενερ."</string> @@ -135,16 +108,14 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Μικ. στο κύριο πληκ."</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Μικ. στο πληκ. συμβ."</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Απεν. φωνητ. είσοδος"</string> - <string name="selectInputMethod" msgid="315076553378705821">"Επιλογή μεθόδου εισόδου"</string> <string name="configure_input_method" msgid="373356270290742459">"Διαμόρφωση μεθόδων εισαγωγής"</string> <string name="language_selection_title" msgid="1651299598555326750">"Γλώσσες εισόδου"</string> <string name="select_language" msgid="3693815588777926848">"Γλώσσες εισόδου"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Αγγίξτε ξανά για αποθήκευση"</string> + <string name="hint_add_to_dictionary" msgid="573678656946085380">"Αγγίξτε ξανά για αποθήκευση"</string> <string name="has_dictionary" msgid="6071847973466625007">"Λεξικό διαθέσιμο"</string> <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..0aae21e38 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,46 +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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"To turn off voice input, go to input method settings."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"To use voice input, press the microphone button."</string> - <string name="voice_listening" msgid="467518160751321844">"Speak now"</string> - <string name="voice_working" msgid="6666937792815731889">"Working"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Error: Please try again."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Couldn\'t connect"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Error, too much speech."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Audio problem"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Server error"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"No speech heard"</string> - <string name="voice_no_match" msgid="4285117547030179174">"No matches found"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Voice search not installed"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Hint:"</b>" Swipe across keyboard to speak"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Hint:"</b>" Next time, try speaking punctuation marks, like \"full stop\", \"comma\" or \"question mark\"."</string> - <string name="cancel" msgid="6830980399865683324">"Cancel"</string> - <string name="ok" msgid="7898366843681727667">"OK"</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_input" msgid="3583258583521397548">"Voice input key"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"On main keyboard"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"On symbols keyboard"</string> @@ -135,16 +108,15 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mic on main keyboard"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mic on symbols keyboard"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Voice input is disabled"</string> - <string name="selectInputMethod" msgid="315076553378705821">"Select input method"</string> <string name="configure_input_method" msgid="373356270290742459">"Configure input methods"</string> <string name="language_selection_title" msgid="1651299598555326750">"Input languages"</string> <string name="select_language" msgid="3693815588777926848">"Input languages"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Touch again to save"</string> + <!-- no translation found for hint_add_to_dictionary (573678656946085380) --> + <skip /> <string name="has_dictionary" msgid="6071847973466625007">"Dictionary available"</string> <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/donottranslate-more-keys.xml b/java/res/values-en/donottranslate-more-keys.xml index bc26c6aa0..6e43e86d7 100644 --- a/java/res/values-en/donottranslate-more-keys.xml +++ b/java/res/values-en/donottranslate-more-keys.xml @@ -18,12 +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_s">ß</string> - <string name="more_keys_for_u">7,û,ü,ù,ú,ū</string> - <string name="more_keys_for_n">ñ</string> - <string name="more_keys_for_c">ç</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 --> + <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+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+00ED: "í" LATIN SMALL LETTER I WITH ACUTE + U+012B: "ī" LATIN SMALL LETTER I WITH MACRON + U+00EC: "ì" LATIN SMALL LETTER I WITH GRAVE --> + <string name="more_keys_for_i">î,ï,í,ī,ì</string> + <!-- U+00F4: "ô" LATIN SMALL LETTER O WITH CIRCUMFLEX + 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+0153: "œ" LATIN SMALL LIGATURE OE + U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + U+014D: "ō" LATIN SMALL LETTER O WITH MACRON + U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE --> + <string name="more_keys_for_o">ô,ö,ò,ó,œ,øō,õ</string> + <!-- 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+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 --> + <string name="more_keys_for_s">ß</string> + <!-- U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE --> + <string name="more_keys_for_n">ñ</string> + <!-- U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA --> + <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 b04a441ef..b9c4963a4 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,7 +36,10 @@ <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="advanced_settings_summary" msgid="4487980456152830271">"Opciones para expertos"</string> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Otros métodos de entrada"</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"La tecla de cambio de idioma abarca otros métodos de entrada."</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"Supr. tecla cambio idioma"</string> <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> @@ -50,7 +55,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 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 las teclas de puntuación insertan automáticamente la palabra corregida"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Desactivado"</string> @@ -64,6 +68,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 +81,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,46 +93,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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Para desactivar la entrada de voz, ve a la configuración de métodos de entrada."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Para utilizar entrada de voz, presiona el botón micrófono."</string> - <string name="voice_listening" msgid="467518160751321844">"Habla ahora"</string> - <string name="voice_working" msgid="6666937792815731889">"Procesando"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Error. Vuelve a intentarlo."</string> - <string name="voice_network_error" msgid="6649556447401862563">"No se pudo establecer la conexión."</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Error, demasiado discurso."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Problema de audio"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Error del servidor"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"No se oyó la voz"</string> - <string name="voice_no_match" msgid="4285117547030179174">"No se encontraron coincidencias"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Búsqueda por voz no instalada"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Sugerencia:"</b>" Deslizar en el teclado para hablar"</string> - <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="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_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> @@ -135,16 +108,15 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Micrófono en el teclado principal"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Micrófono en el teclado de símbolos"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"La entrada por voz está inhabilitada"</string> - <string name="selectInputMethod" msgid="315076553378705821">"Seleccionar método de entrada"</string> <string name="configure_input_method" msgid="373356270290742459">"Configurar métodos de entrada"</string> <string name="language_selection_title" msgid="1651299598555326750">"Idiomas de entrada"</string> <string name="select_language" msgid="3693815588777926848">"Idiomas de entrada"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Tocar de nuevo para guardar"</string> + <!-- no translation found for hint_add_to_dictionary (573678656946085380) --> + <skip /> <string name="has_dictionary" msgid="6071847973466625007">"Diccionario disponible"</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..a746c3710 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,10 @@ <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> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Otros métodos de introducción"</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"La tecla de cambio de idioma sirve también para otros métodos."</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"Eliminar tecla cambiar idioma"</string> <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 +55,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 +68,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 +81,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,46 +93,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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Para desactivar la función de entrada de voz, accede a los ajustes del método de introducción de texto."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Para utilizar la entrada de voz, pulsa el botón de micrófono."</string> - <string name="voice_listening" msgid="467518160751321844">"Habla ahora"</string> - <string name="voice_working" msgid="6666937792815731889">"En curso"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Se ha producido un error. Inténtalo de nuevo."</string> - <string name="voice_network_error" msgid="6649556447401862563">"No se ha podido establecer conexión."</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Se ha producido un error debido a un exceso de introducción de datos de voz."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Problema de audio"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Error del servidor"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Ninguna conversación escuchada"</string> - <string name="voice_no_match" msgid="4285117547030179174">"No se ha encontrado ninguna coincidencia."</string> - <string name="voice_not_installed" msgid="5552450909753842415">"La búsqueda por voz no está instalada."</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Sugerencia:"</b>" muévete por el teclado para hablar."</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Sugerencia:"</b>" la próxima vez, prueba a indicar signos de puntuación como, por ejemplo, \"punto\", \"coma\" o \"signo de interrogación\"."</string> - <string name="cancel" msgid="6830980399865683324">"Cancelar"</string> - <string name="ok" msgid="7898366843681727667">"Aceptar"</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_input" msgid="3583258583521397548">"Tecla de entrada de voz"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"En teclado principal"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"En teclado de símbolos"</string> @@ -135,16 +108,14 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Micrófono en teclado principal"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Micro en teclado de símbolos"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Entrada de voz inhabilitada"</string> - <string name="selectInputMethod" msgid="315076553378705821">"Selecciona un método de introducción de texto"</string> <string name="configure_input_method" msgid="373356270290742459">"Configurar métodos de introducción"</string> <string name="language_selection_title" msgid="1651299598555326750">"Idiomas"</string> <string name="select_language" msgid="3693815588777926848">"Idiomas de entrada"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Volver a tocar para guardar"</string> + <string name="hint_add_to_dictionary" msgid="573678656946085380">"Toca otra vez para guardar."</string> <string name="has_dictionary" msgid="6071847973466625007">"Hay un diccionario disponible"</string> <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..69cf654a6 --- /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_nordic_row1_11">ü</string> + <!-- U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS --> + <string name="keylabel_for_nordic_row2_10">ö</string> + <!-- U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS --> + <string name="keylabel_for_nordic_row2_11">ä</string> + <!-- U+00F5: "õ" LATIN SMALL LETTER O WITH TILDE --> + <string name="more_keys_for_nordic_row2_10">õ</string> +</resources> diff --git a/java/res/values-et/strings.xml b/java/res/values-et/strings.xml index 2c69c99d3..1c7f14e17 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,10 @@ <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> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Vaheta sisestusmeetodit"</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Keelevahetuse võti hõlmab ka muid sisestusmeetodeid"</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"Keela keelevahetuse võti"</string> <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 +55,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 +68,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 +81,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,46 +93,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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Kõnesisendi väljalülitamiseks minge sisestusmeetodi seadete juurde."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Kõnesisendi kasutamiseks vajutage mikrofoni nuppu."</string> - <string name="voice_listening" msgid="467518160751321844">"Alustage rääkimist"</string> - <string name="voice_working" msgid="6666937792815731889">"Töötab"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Viga. Proovige uuesti."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Ühendamine nurjus."</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Viga. Liiga palju kõnet."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Heli probleem"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Serveri viga"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Kõne pole kuuldav"</string> - <string name="voice_no_match" msgid="4285117547030179174">"Ühtki vastet ei leitud"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Hääleotsing pole installitud"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Vihje:"</b>" rääkimiseks libistage sõrme üle ekraani"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Vihje:"</b>" proovige järgmine kord kirjavahemärkide ütlemist, nt „punkt”, „koma” või „küsimärk”."</string> - <string name="cancel" msgid="6830980399865683324">"Tühista"</string> - <string name="ok" msgid="7898366843681727667">"OK"</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_input" msgid="3583258583521397548">"Häälesisendi klahv"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Peamisel klaviatuuril"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Sümbol. klaviatuuril"</string> @@ -135,16 +108,15 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikr. peam. klaviat."</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikr. sümb. klaviat."</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Kõnesisend on keelatud"</string> - <string name="selectInputMethod" msgid="315076553378705821">"Sisestusmeet. valim."</string> <string name="configure_input_method" msgid="373356270290742459">"Sisestusmeetodite seadistamine"</string> <string name="language_selection_title" msgid="1651299598555326750">"Sisestuskeeled"</string> <string name="select_language" msgid="3693815588777926848">"Sisestuskeeled"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"←Salvestamiseks puudutage uuesti"</string> + <!-- no translation found for hint_add_to_dictionary (573678656946085380) --> + <skip /> <string name="has_dictionary" msgid="6071847973466625007">"Sõnastik saadaval"</string> <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..1fb1846d9 --- /dev/null +++ b/java/res/values-fa/donottranslate-more-keys.xml @@ -0,0 +1,162 @@ +<?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+06F1: "۱" EXTENDED ARABIC-INDIC DIGIT ONE --> + <string name="keylabel_for_symbols_1">۱</string> + <!-- U+06F2: "۲" EXTENDED ARABIC-INDIC DIGIT TWO --> + <string name="keylabel_for_symbols_2">۲</string> + <!-- U+06F3: "۳" EXTENDED ARABIC-INDIC DIGIT THREE --> + <string name="keylabel_for_symbols_3">۳</string> + <!-- U+06F4: "۴" EXTENDED ARABIC-INDIC DIGIT FOUR --> + <string name="keylabel_for_symbols_4">۴</string> + <!-- U+06F5: "۵" EXTENDED ARABIC-INDIC DIGIT FIVE --> + <string name="keylabel_for_symbols_5">۵</string> + <!-- U+06F6: "۶" EXTENDED ARABIC-INDIC DIGIT SIX --> + <string name="keylabel_for_symbols_6">۶</string> + <!-- U+06F7: "۷" EXTENDED ARABIC-INDIC DIGIT SEVEN --> + <string name="keylabel_for_symbols_7">۷</string> + <!-- U+06F8: "۸" EXTENDED ARABIC-INDIC DIGIT EIGHT --> + <string name="keylabel_for_symbols_8">۸</string> + <!-- U+06F9: "۹" EXTENDED ARABIC-INDIC DIGIT NINE --> + <string name="keylabel_for_symbols_9">۹</string> + <!-- U+06F0: "۰" EXTENDED 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_tablet_comma">"،"</string> + <string name="keyhintlabel_for_tablet_comma">"!"</string> + <string name="more_keys_for_tablet_comma">"!,\\,"</string> + <string name="keyhintlabel_for_tablet_period">"؟"</string> + <string name="more_keys_for_tablet_period">"؟,\?"</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-fr-rCH/donottranslate-more-keys.xml b/java/res/values-fa/donottranslate.xml index 561c5e52f..57de2538b 100644 --- a/java/res/values-fr-rCH/donottranslate-more-keys.xml +++ b/java/res/values-fa/donottranslate.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,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> + <!-- 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..fb3654e83 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,46 +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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"برای خاموش کردن ورودی صدا، به تنظیمات روش ورودی بروید."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"برای استفاده از ورودی صوتی، دکمه میکروفن را فشار دهید."</string> - <string name="voice_listening" msgid="467518160751321844">"اکنون صحبت کنید"</string> - <string name="voice_working" msgid="6666937792815731889">"در حال کار"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"خطا: لطفاً دوباره امتحان کنید."</string> - <string name="voice_network_error" msgid="6649556447401862563">"متصل نشد"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"خطا، گفتار بسیار زیاد است."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"مشکل صوتی"</string> - <string name="voice_server_error" msgid="7807129913977261644">"خطای سرور"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"گفتاری شنیده نشد"</string> - <string name="voice_no_match" msgid="4285117547030179174">"مورد منطبقی یافت نشد"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"جستجوی صوتی نصب نشده است"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"نکته: "</b>" برای صحبت روی صفحه کلید ضربه بزنید"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"نکته: دفعه دیگر، از نشانه گذاری های گفتاری مانند \"نقطه\"، \"کاما\" یا \"علامت سؤال\" استفاده کنید."</b></string> - <string name="cancel" msgid="6830980399865683324">"لغو"</string> - <string name="ok" msgid="7898366843681727667">"تأیید"</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_input" msgid="3583258583521397548">"کلید ورودی صدا"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"در صفحه کلید اصلی"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"در صفحه کلید نمادها"</string> @@ -139,16 +112,15 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"میکروفن در صفحه کلید اصلی"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"میکروفن در صفحه کلید نمادها"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"ورودی صدا غیرفعال است"</string> - <string name="selectInputMethod" msgid="315076553378705821">"انتخاب روش ورودی"</string> <string name="configure_input_method" msgid="373356270290742459">"پیکربندی روش های ورودی"</string> <string name="language_selection_title" msgid="1651299598555326750">"زبان های ورودی"</string> <string name="select_language" msgid="3693815588777926848">"زبانهای ورودی"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← جهت ذخیره دوباره لمس کنید"</string> + <!-- no translation found for hint_add_to_dictionary (573678656946085380) --> + <skip /> <string name="has_dictionary" msgid="6071847973466625007">"دیکشنری موجود است"</string> <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..25b785845 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_nordic_row1_11">å</string> + <!-- U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS --> + <string name="keylabel_for_nordic_row2_10">ö</string> + <!-- U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS --> + <string name="keylabel_for_nordic_row2_11">ä</string> + <!-- U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE --> + <string name="more_keys_for_nordic_row2_10">ø</string> + <!-- U+00E6: "æ" LATIN SMALL LETTER AE --> + <string name="more_keys_for_nordic_row2_11">æ</string> </resources> diff --git a/java/res/values-fi/strings.xml b/java/res/values-fi/strings.xml index d7c319942..774817872 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,10 @@ <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> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Käytä toista syöttötapaa"</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Kielenvaihtonäppäin kattaa myös muut syöttötavat"</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"Piilota kielenvaihtonäpp."</string> <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 +55,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 +68,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 +81,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,46 +93,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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Siirry syöttöasetuksiin poistaaksesi äänisyötteen käytöstä."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Ota äänisyöte käyttöön painamalla mikrofonikuvaketta."</string> - <string name="voice_listening" msgid="467518160751321844">"Puhu nyt"</string> - <string name="voice_working" msgid="6666937792815731889">"Työstetään"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Virhe. Yritä uudelleen."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Ei yhteyttä"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Virhe, liikaa puhetta."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Ääniongelma"</string> - <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">"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> - <string name="ok" msgid="7898366843681727667">"OK"</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_input" msgid="3583258583521397548">"Ääniohjausavain"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Päänäppäimistössä"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Symbolinäppäimistössä"</string> @@ -135,16 +108,15 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikr. päänäppäim."</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikr. symbolinäppäim."</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Ääniohjaus on pois käytöstä"</string> - <string name="selectInputMethod" msgid="315076553378705821">"Valitse syöttötapa"</string> <string name="configure_input_method" msgid="373356270290742459">"Määritä syöttötavat"</string> <string name="language_selection_title" msgid="1651299598555326750">"Syöttökielet"</string> <string name="select_language" msgid="3693815588777926848">"Syöttökielet"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Tallenna koskettamalla uudelleen"</string> + <!-- no translation found for hint_add_to_dictionary (573678656946085380) --> + <skip /> <string name="has_dictionary" msgid="6071847973466625007">"Sanakirja saatavilla"</string> <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-de-rZZ/donottranslate-more-keys.xml b/java/res/values-fr/donottranslate-config.xml index e7ec5e152..1f446d584 100644 --- a/java/res/values-de-rZZ/donottranslate-more-keys.xml +++ b/java/res/values-fr/donottranslate-config.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. @@ -17,7 +17,7 @@ ** limitations under the License. */ --> -<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> + +<resources> + <bool name="config_require_ligatures_processing">true</bool> </resources> 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..f2c7fbe85 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,10 @@ <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> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Autres modes de saisie"</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"La touche de sélection de langue couvre d\'autres modes de saisie."</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"Suppr. touche sélect. langue"</string> <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 +55,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 +68,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 +81,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,46 +93,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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Pour désactiver la saisie vocale, accédez aux paramètres du mode de saisie."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Pour utiliser la saisie vocale, appuyez sur la touche du microphone."</string> - <string name="voice_listening" msgid="467518160751321844">"Parlez maintenant"</string> - <string name="voice_working" msgid="6666937792815731889">"Traitement en cours"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Erreur. Veuillez réessayer."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Connexion impossible"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Erreur, discours trop long."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Problème audio"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Erreur serveur"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Aucune requête vocale détectée"</string> - <string name="voice_no_match" msgid="4285117547030179174">"Aucune correspondance n\'a été trouvée."</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Recherche vocale non installée"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Astuce :"</b>" Faites glisser votre doigt sur le clavier pour parler."</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Astuce :"</b>" La prochaine fois, essayez de prononcer la ponctuation, en énonçant des termes tels que \"point\", \"virgule\" ou \"point d\'interrogation\"."</string> - <string name="cancel" msgid="6830980399865683324">"Annuler"</string> - <string name="ok" msgid="7898366843681727667">"OK"</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_input" msgid="3583258583521397548">"Touche de saisie vocale"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Sur clavier principal"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Sur clavier symboles"</string> @@ -135,16 +108,14 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Micro sur le clavier principal"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Micro sur clavier symboles"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Saisie vocale désactivée"</string> - <string name="selectInputMethod" msgid="315076553378705821">"Sélectionner un mode de saisie."</string> <string name="configure_input_method" msgid="373356270290742459">"Configurer les modes de saisie"</string> <string name="language_selection_title" msgid="1651299598555326750">"Langues de saisie"</string> <string name="select_language" msgid="3693815588777926848">"Langues de saisie"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Appuyer de nouveau pour enregistrer"</string> + <string name="hint_add_to_dictionary" msgid="573678656946085380">"Appuyer de nouveau pour enregistrer"</string> <string name="has_dictionary" msgid="6071847973466625007">"Dictionnaire disponible"</string> <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/donottranslate-more-keys.xml b/java/res/values-hi/donottranslate-more-keys.xml new file mode 100644 index 000000000..19bcb9dda --- /dev/null +++ b/java/res/values-hi/donottranslate-more-keys.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. +*/ +--> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- U+0967: "१" DEVANAGARI DIGIT ONE --> + <string name="keylabel_for_symbols_1">१</string> + <!-- U+0968: "२" DEVANAGARI DIGIT TWO --> + <string name="keylabel_for_symbols_2">२</string> + <!-- U+0969: "३" DEVANAGARI DIGIT THREE --> + <string name="keylabel_for_symbols_3">३</string> + <!-- U+096A: "४" DEVANAGARI DIGIT FOUR --> + <string name="keylabel_for_symbols_4">४</string> + <!-- U+096B: "५" DEVANAGARI DIGIT FIVE --> + <string name="keylabel_for_symbols_5">५</string> + <!-- U+096C: "६" DEVANAGARI DIGIT SIX --> + <string name="keylabel_for_symbols_6">६</string> + <!-- U+096D: "७" DEVANAGARI DIGIT SEVEN --> + <string name="keylabel_for_symbols_7">७</string> + <!-- U+096E: "८" DEVANAGARI DIGIT EIGHT --> + <string name="keylabel_for_symbols_8">८</string> + <!-- U+096F: "९" DEVANAGARI DIGIT NINE --> + <string name="keylabel_for_symbols_9">९</string> + <!-- U+0966: "०" DEVANAGARI 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> + <string name="additional_more_keys_for_symbols_0">0</string> +</resources> diff --git a/java/res/values-hi/strings.xml b/java/res/values-hi/strings.xml index de95ab8d7..2e2b77607 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,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">"Spacebar और विराम चिह्न गलत लिखे गए शब्दों को स्वचालित रूप से ठीक करते हैं"</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">"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,46 +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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"ध्वनि इनपुट बंद करने के लिए, इनपुट पद्धति सेटिंग पर जाएं."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"ध्वनि इनपुट का उपयोग करने के लिए, माइक्रोफ़ोन बटन दबाएं."</string> - <string name="voice_listening" msgid="467518160751321844">"अब बोलें"</string> - <string name="voice_working" msgid="6666937792815731889">"कार्य कर रहा है"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"त्रुटि. कृपया पुन: प्रयास करें."</string> - <string name="voice_network_error" msgid="6649556447401862563">"कनेक्ट नहीं कर सका"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"त्रुटि, बहुत अधिक बातचीत."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"ऑडियो समस्या"</string> - <string name="voice_server_error" msgid="7807129913977261644">"सर्वर त्रुटि"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"कोई बातचीत नहीं सुनाई दी"</string> - <string name="voice_no_match" msgid="4285117547030179174">"कोई मिलान नहीं मिले"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"ध्वनि खोज इंस्टॉल नहीं है"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"संकेत:"</b>" बोलने के लिए कीबोर्ड पर स्वाइप करें"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"संकेत:"</b>" अगली बार, विरामचिन्ह बोलने का प्रयास करें जैसे \"पूर्णविराम\", \"अल्पविराम\", या \"प्रश्नचिह्न\"."</string> - <string name="cancel" msgid="6830980399865683324">"रद्द करें"</string> - <string name="ok" msgid="7898366843681727667">"ठीक"</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_input" msgid="3583258583521397548">"ध्वनि इनपुट कुंजी"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"मुख्य कीबोर्ड पर"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"प्रतीक कीबोर्ड पर"</string> @@ -135,16 +108,15 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"मुख्य कीबोर्ड पर माइक"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"प्रतीक कीबोर्ड पर माइक"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"ध्वनि इनपुट अक्षम है"</string> - <string name="selectInputMethod" msgid="315076553378705821">"इनपुट विधि का चयन करें"</string> <string name="configure_input_method" msgid="373356270290742459">"इनपुट पद्धति कॉन्फ़िगर करें"</string> <string name="language_selection_title" msgid="1651299598555326750">"इनपुट भाषा"</string> <string name="select_language" msgid="3693815588777926848">"इनपुट भाषाएं"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← सहेजने के लिए फिर से स्पर्श करें"</string> + <!-- no translation found for hint_add_to_dictionary (573678656946085380) --> + <skip /> <string name="has_dictionary" msgid="6071847973466625007">"शब्दकोश उपलब्ध है"</string> <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 cf63880dc..e416816b2 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,7 +36,10 @@ <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="advanced_settings_summary" msgid="4487980456152830271">"Opcije za stručnjake"</string> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Prebaci na druge unose"</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Tipka za prebacivanje jezika pokriva i druge načine unosa"</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"Spriječi tipku za jezike"</string> <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> @@ -50,7 +55,6 @@ <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">"Razmak i interpunkcija automatski ispravljaju krive riječi"</string> <string name="auto_correction_threshold_mode_off" msgid="8470882665417944026">"Isključeno"</string> @@ -64,6 +68,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 +81,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,46 +93,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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Za isključivanje glasovnog unosa idite na postavke načina unosa."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Za upotrebu glasovnog unosa pritisnite gumb mikrofona."</string> - <string name="voice_listening" msgid="467518160751321844">"Govorite sad"</string> - <string name="voice_working" msgid="6666937792815731889">"Obrada"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Pogreška. Pokušajte ponovo."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Spajanje nije bilo moguće"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Pogreška, predugi govor."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Problem sa zvukom"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Pogreška na poslužitelju"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Nije se čuo govor"</string> - <string name="voice_no_match" msgid="4285117547030179174">"Nisu pronađeni rezultati"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Glasovno pretraživanje nije instalirano"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Savjet:"</b>" Prijeđite preko tipkovnice pa govorite"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Savjet:"</b>" Sljedeći put pokušajte izgovoriti znakove interpunkcije poput \"točka, \"zarez\" ili \"upitnik\"."</string> - <string name="cancel" msgid="6830980399865683324">"Odustani"</string> - <string name="ok" msgid="7898366843681727667">"U redu"</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_input" msgid="3583258583521397548">"Tipka za glasovni unos"</string> <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> @@ -135,16 +108,15 @@ <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> <string name="configure_input_method" msgid="373356270290742459">"Konfiguriraj načine ulaza"</string> <string name="language_selection_title" msgid="1651299598555326750">"Jezici unosa"</string> <string name="select_language" msgid="3693815588777926848">"Jezici unosa"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Dodirnite opet za spremanje"</string> + <!-- no translation found for hint_add_to_dictionary (573678656946085380) --> + <skip /> <string name="has_dictionary" msgid="6071847973466625007">"Rječnik je dostupan"</string> <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..7e466ed40 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,10 @@ <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> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Váltás más beviteli módra"</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"A nyelvkapcsoló gomb egyéb beviteli módokat is tartalmaz"</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"A nyelvkapcsoló elrejtése"</string> <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 +55,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 +68,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 +81,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,46 +93,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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"A hangbevitelt a beviteli mód beállításai között lehet kikapcsolni."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"A hangbevitel használatához nyomja meg a mikrofon gombot."</string> - <string name="voice_listening" msgid="467518160751321844">"Most beszéljen"</string> - <string name="voice_working" msgid="6666937792815731889">"Feldolgozás"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Hiba történt. Kérjük, próbálja újra."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Nem sikerült kapcsolódni"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Hiba történt; túl sokat beszélt."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Hangprobléma"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Szerverhiba"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Nem hallatszott beszéd"</string> - <string name="voice_no_match" msgid="4285117547030179174">"Nem található egyezés"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"A hangalapú keresés nincs telepítve"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Tipp:"</b>" húzza végig az ujját a billentyűzeten a beszédhez"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Tipp:"</b>" következő alkalommal próbálja ki az írásjelek kimondását is, pl. \"period\", \"comma\" vagy \"question mark\"."</string> - <string name="cancel" msgid="6830980399865683324">"Mégse"</string> - <string name="ok" msgid="7898366843681727667">"OK"</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_input" msgid="3583258583521397548">"Hangbeviteli gomb"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"A fő billentyűzeten"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Szimbólumoknál"</string> @@ -135,16 +108,15 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikr. a billentyűzeten"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikr. a szimbólumoknál"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Hangbevivel KI"</string> - <string name="selectInputMethod" msgid="315076553378705821">"Beviteli mód kiválasztása"</string> <string name="configure_input_method" msgid="373356270290742459">"Beviteli módok beállítása"</string> <string name="language_selection_title" msgid="1651299598555326750">"Beviteli nyelvek"</string> <string name="select_language" msgid="3693815588777926848">"Beviteli nyelvek"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Érintse meg újra a mentéshez"</string> + <!-- no translation found for hint_add_to_dictionary (573678656946085380) --> + <skip /> <string name="has_dictionary" msgid="6071847973466625007">"Van elérhető szótár"</string> <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..39b41c021 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,13 @@ <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> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Beralih ke metode masukan lain"</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Tombol beralih bahasa juga mencakup metode masukan lain"</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"Redam tombol alih bahasa"</string> <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 +55,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 +68,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 +81,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,46 +93,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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Untuk mematikan masukan suara, buka setelan metode masukan."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Untuk menggunakan masukan suara, tekan tombol mikrofon."</string> - <string name="voice_listening" msgid="467518160751321844">"Ucapkan sekarang"</string> - <string name="voice_working" msgid="6666937792815731889">"Bekerja"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Galat: Coba lagi."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Tidak dapat menyambung"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Galat, terlalu banyak ucapan."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Masalah audio"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Galat server"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Tidak terdengar ucapan"</string> - <string name="voice_no_match" msgid="4285117547030179174">"Tak ditemukan yang cocok"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Penelusuran suara tidak terpasang"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Petunjuk:"</b>" Gesek keyboard untuk berbicara"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Petunjuk:"</b>" Selanjutnya, coba ucapkan tanda baca seperti \"titik\", \"koma\", atau \"tanda tanya\"."</string> - <string name="cancel" msgid="6830980399865683324">"Batal"</string> - <string name="ok" msgid="7898366843681727667">"OK"</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_input" msgid="3583258583521397548">"Tombol masukan suara"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Pada keyboard utama"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Pada keyboard simbol"</string> @@ -135,16 +108,15 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mik pada keyboard utama"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mik pada keyboard simbol"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Masukan suara dinonaktifkan"</string> - <string name="selectInputMethod" msgid="315076553378705821">"Pilih metode masukan"</string> <string name="configure_input_method" msgid="373356270290742459">"Konfigurasikan metode masukan"</string> <string name="language_selection_title" msgid="1651299598555326750">"Bahasa masukan"</string> <string name="select_language" msgid="3693815588777926848">"Bahasa masukan"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Sentuh sekali lagi untuk menyimpan"</string> + <!-- no translation found for hint_add_to_dictionary (573678656946085380) --> + <skip /> <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-is/donottranslate-more-keys.xml b/java/res/values-is/donottranslate-more-keys.xml new file mode 100644 index 000000000..284aae930 --- /dev/null +++ b/java/res/values-is/donottranslate-more-keys.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. +*/ +--> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- 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+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 + U+00E8: "è" LATIN SMALL LETTER E WITH GRAVE + 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+00EE: "î" LATIN SMALL LETTER I WITH CIRCUMFLEX + 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+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+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+00FE: "þ" LATIN SMALL LETTER THORN --> + <string name="more_keys_for_t">þ</string> + <!-- U+00F0: "ð" LATIN SMALL LETTER ETH --> + <string name="keylabel_for_nordic_row1_11">ð</string> + <!-- U+00E6: "æ" LATIN SMALL LETTER AE --> + <string name="keylabel_for_nordic_row2_10">æ</string> + <!-- U+00FE: "þ" LATIN SMALL LETTER THORN --> + <string name="keylabel_for_nordic_row2_11">þ</string> +</resources> 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..3e27f4eb8 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,10 @@ <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> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Altri metodi immissione"</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Il tasto per cambiare lingua offre altri metodi di immissione"</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"Elimina tasto cambio lingua"</string> <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 +55,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 +68,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 +81,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,46 +93,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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Per disattivare l\'input vocale, vai alle impostazioni del metodo di input."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Per utilizzare l\'input vocale, premi il pulsante del microfono."</string> - <string name="voice_listening" msgid="467518160751321844">"Parla ora"</string> - <string name="voice_working" msgid="6666937792815731889">"Elaborazione..."</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Errore. Riprova più tardi."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Impossibile connettersi."</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Errore: conversazione troppo lunga."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Problema audio"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Errore del server"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Nessuna frase vocale rilevata"</string> - <string name="voice_no_match" msgid="4285117547030179174">"Nessuna corrispondenza trovata"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Ricerca vocale non installata"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Suggerimento."</b>" Fai scorrere il dito sulla tastiera per parlare"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Suggerimento."</b>" La prossima volta, prova a pronunciare termini relativi alla punteggiatura come \"punto\", \"virgola\" o \"punto di domanda\"."</string> - <string name="cancel" msgid="6830980399865683324">"Annulla"</string> - <string name="ok" msgid="7898366843681727667">"OK"</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_input" msgid="3583258583521397548">"Tasto immissione vocale"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Su tastiera principale"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Su tastiera simboli"</string> @@ -135,16 +108,14 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mic su tastiera principale"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mic su tastiera simboli"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Comandi vocali disatt."</string> - <string name="selectInputMethod" msgid="315076553378705821">"Seleziona metodo di inserimento"</string> <string name="configure_input_method" msgid="373356270290742459">"Configura metodi di immissione"</string> <string name="language_selection_title" msgid="1651299598555326750">"Lingue comandi"</string> <string name="select_language" msgid="3693815588777926848">"Lingue comandi"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Tocca di nuovo per salvare"</string> + <string name="hint_add_to_dictionary" msgid="573678656946085380">"Tocca di nuovo per salvare"</string> <string name="has_dictionary" msgid="6071847973466625007">"Dizionario disponibile"</string> <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..2d8f8dc1c 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,46 +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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"כדי לכבות את הקלט הקולי, עבור להגדרות של שיטת קלט."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"כדי להשתמש בקלט קולי, לחץ על לחצן המיקרופון."</string> - <string name="voice_listening" msgid="467518160751321844">"דבר עכשיו"</string> - <string name="voice_working" msgid="6666937792815731889">"פועל"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"שגיאה. נסה שוב."</string> - <string name="voice_network_error" msgid="6649556447401862563">"אין אפשרות להתחבר"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"שגיאה, קטע דיבור ארוך מדי."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"בעיה באודיו"</string> - <string name="voice_server_error" msgid="7807129913977261644">"שגיאת שרת"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"לא ניתן לשמוע דיבור"</string> - <string name="voice_no_match" msgid="4285117547030179174">"לא נמצאו התאמות"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"חיפוש קולי לא מותקן"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"רמז:"</b>" העבר על המקלדת כדי לדבר"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"רמז:"</b>" בפעם הבאה, נסה לומר את סימני הפיסוק כגון \"נקודה\", \"פסיק\" או \"סימן שאלה\"."</string> - <string name="cancel" msgid="6830980399865683324">"ביטול"</string> - <string name="ok" msgid="7898366843681727667">"אישור"</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_input" msgid="3583258583521397548">"מקש קלט קולי"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"במקלדת הראשית"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"במקלדת סמלים"</string> @@ -135,16 +108,15 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"מיקרופון במקלדת הראשית"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"מיקרופון במקלדת סמלים"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"הקלט הקולי מושבת"</string> - <string name="selectInputMethod" msgid="315076553378705821">"בחר שיטת קלט"</string> <string name="configure_input_method" msgid="373356270290742459">"הגדרת שיטות קלט"</string> <string name="language_selection_title" msgid="1651299598555326750">"שפות קלט"</string> <string name="select_language" msgid="3693815588777926848">"שפות קלט"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← גע פעם נוספת לשמירה"</string> + <!-- no translation found for hint_add_to_dictionary (573678656946085380) --> + <skip /> <string name="has_dictionary" msgid="6071847973466625007">"מילון זמין"</string> <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..439a652e0 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,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">"OFF"</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">"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,46 +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">"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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"音声入力をOFFにするには、入力方法の設定を開きます。"</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"音声入力するには、マイクボタンを押してください。"</string> - <string name="voice_listening" msgid="467518160751321844">"お話しください"</string> - <string name="voice_working" msgid="6666937792815731889">"処理中"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"エラーです。もう一度お試しください。"</string> - <string name="voice_network_error" msgid="6649556447401862563">"接続できませんでした"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"音声が長すぎてエラーになりました。"</string> - <string name="voice_audio_error" msgid="5072707727016414454">"オーディオエラー"</string> - <string name="voice_server_error" msgid="7807129913977261644">"サーバーエラー"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"音声が聞き取れません"</string> - <string name="voice_no_match" msgid="4285117547030179174">"該当なし"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Voice Searchはインストールされていません"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"ヒント:"</b>" 音声入力するにはキーボードをスワイプします"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"ヒント:"</b>" 次回は句読点として「period」、「comma」、「question mark」などの音声入力を試してみてください。"</string> - <string name="cancel" msgid="6830980399865683324">"キャンセル"</string> - <string name="ok" msgid="7898366843681727667">"OK"</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_input" msgid="3583258583521397548">"音声入力キー"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"メインキーボード上"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"記号キーボード上"</string> @@ -135,16 +108,15 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"メインキーボードのマイク"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"記号キーボードのマイク"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"音声入力は無効です"</string> - <string name="selectInputMethod" msgid="315076553378705821">"入力方法の選択"</string> <string name="configure_input_method" msgid="373356270290742459">"入力方法を設定"</string> <string name="language_selection_title" msgid="1651299598555326750">"入力言語"</string> <string name="select_language" msgid="3693815588777926848">"入力言語"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"←保存するにはもう一度タップ"</string> + <!-- no translation found for hint_add_to_dictionary (573678656946085380) --> + <skip /> <string name="has_dictionary" msgid="6071847973466625007">"辞書を利用できます"</string> <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..a2863c7e8 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,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">"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,46 +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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"음성 입력을 사용하지 않으려면 입력 방법 설정으로 이동하세요."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"음성 입력을 사용하려면 마이크 버튼을 누르세요."</string> - <string name="voice_listening" msgid="467518160751321844">"지금 말하세요."</string> - <string name="voice_working" msgid="6666937792815731889">"인식 중"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"오류가 발생했습니다. 다시 시도해 보세요."</string> - <string name="voice_network_error" msgid="6649556447401862563">"연결할 수 없습니다."</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"음성을 너무 많이 입력했습니다."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"오디오 문제"</string> - <string name="voice_server_error" msgid="7807129913977261644">"서버 오류"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"음성이 인식되지 않았습니다."</string> - <string name="voice_no_match" msgid="4285117547030179174">"일치하는 항목 없음"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"음성 검색이 설치되지 않았습니다."</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"도움말:"</b>" 키보드 위로 손가락을 미끄러지듯 움직이고 나서 말하세요."</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"도움말:"</b>" 다음 번에는 \'마침표\', \'쉼표\', \'물음표\'와 같은 구두점을 말해 보세요."</string> - <string name="cancel" msgid="6830980399865683324">"취소"</string> - <string name="ok" msgid="7898366843681727667">"확인"</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_input" msgid="3583258583521397548">"음성 입력 키"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"기본 키보드"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"기호 키보드"</string> @@ -135,16 +108,15 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"기본 키보드의 마이크"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"기호 키보드의 마이크"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"음성 입력이 사용 중지됨"</string> - <string name="selectInputMethod" msgid="315076553378705821">"입력 방법 선택"</string> <string name="configure_input_method" msgid="373356270290742459">"입력 방법 설정"</string> <string name="language_selection_title" msgid="1651299598555326750">"입력 언어"</string> <string name="select_language" msgid="3693815588777926848">"입력 언어"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← 저장하려면 다시 터치하세요."</string> + <!-- no translation found for hint_add_to_dictionary (573678656946085380) --> + <skip /> <string name="has_dictionary" msgid="6071847973466625007">"사전 사용 가능"</string> <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..fd90248b2 --- /dev/null +++ b/java/res/values-ky/donottranslate-more-keys.xml @@ -0,0 +1,37 @@ +<?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+0449: "щ" CYRILLIC SMALL LETTER SHCHA --> + <string name="keylabel_for_east_slavic_row1_9">щ</string> + <!-- U+044B: "ы" CYRILLIC SMALL LETTER YERU --> + <string name="keylabel_for_east_slavic_row2_1">ы</string> + <!-- U+0438: "и" CYRILLIC SMALL LETTER I --> + <string name="keylabel_for_east_slavic_row3_5">и</string> + <!-- 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+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN --> + <string name="more_keys_for_cyrillic_ha">ъ</string> + <!-- U+04E9: "ө" CYRILLIC SMALL LETTER BARRED O --> + <string name="more_keys_for_cyrillic_o">ө</string> + <!-- U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN --> + <string name="more_keys_for_cyrillic_soft_sign">ъ</string> +</resources> diff --git a/java/res/values-land/dimens.xml b/java/res/values-land/dimens.xml index 593cb0ae4..1157b2733 100644 --- a/java/res/values-land/dimens.xml +++ b/java/res/values-land/dimens.xml @@ -19,19 +19,18 @@ --> <resources> - <!-- keyboardHeight = key_height*4 + key_bottom_gap*3, key_height=0.260in --> - <dimen name="keyboardHeight">1.100in</dimen> + <!-- Preferable keyboard height in absolute scale: 1.100in --> + <!-- This keyboardHeight value should match with keyboard-heights.xml --> + <dimen name="keyboardHeight">176.0dp</dimen> <fraction name="minKeyboardHeight">45%p</fraction> <!-- key_height + key_bottom_gap = popup_key_height --> -<!-- <dimen name="key_height">0.260in</dimen>--> - <dimen name="popup_key_height">0.280in</dimen> + <dimen name="popup_key_height">44.8dp</dimen> <fraction name="keyboard_top_padding">1.818%p</fraction> <fraction name="keyboard_bottom_padding">0.0%p</fraction> <fraction name="key_bottom_gap">4.330%p</fraction> <fraction name="key_horizontal_gap">0.405%p</fraction> - <dimen name="keyboardHeight_stone">0.984in</dimen> <fraction name="key_bottom_gap_stone">5.010%p</fraction> <fraction name="key_horizontal_gap_stone">1.159%p</fraction> @@ -44,7 +43,7 @@ <fraction name="key_horizontal_gap_ics">1.020%p</fraction> <!-- left or right padding of label alignment --> - <dimen name="key_label_horizontal_padding">8dip</dimen> + <dimen name="key_label_horizontal_padding">8dp</dimen> <fraction name="key_letter_ratio">65%</fraction> <fraction name="key_large_letter_ratio">74%</fraction> @@ -53,17 +52,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> - <dimen name="key_preview_offset">0.08in</dimen> + <fraction name="spacebar_text_ratio">40.000%</fraction> + <dimen name="key_preview_offset">12.8dp</dimen> - <dimen name="key_preview_offset_ics">0.01in</dimen> + <dimen name="key_preview_offset_ics">1.6dp</dimen> + <!-- popup_key_height x -0.5 --> + <dimen name="more_keys_keyboard_vertical_correction_ics">-22.4dp</dimen> - <dimen name="suggestions_strip_height">36dip</dimen> - <dimen name="more_suggestions_row_height">36dip</dimen> + <dimen name="suggestions_strip_height">36dp</dimen> + <dimen name="more_suggestions_row_height">36dp</dimen> <integer name="max_more_suggestions_row">2</integer> <fraction name="min_more_suggestions_width">60%</fraction> <!-- 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">53.76dp</dimen> <!-- popup_key_height x -1.0 --> - <dimen name="mini_keyboard_vertical_correction">-0.280in</dimen> + <dimen name="more_keys_keyboard_vertical_correction">-44.8dp</dimen> </resources> diff --git a/java/res/values-land/keyboard-heights.xml b/java/res/values-land/keyboard-heights.xml new file mode 100644 index 000000000..12c3e3951 --- /dev/null +++ b/java/res/values-land/keyboard-heights.xml @@ -0,0 +1,34 @@ +<?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. +*/ +--> + +<!-- Preferable keyboard height in absolute scale: 1.100in --> +<resources> + <!-- Build.HARDWARE,keyboard_height_in_dp --> + <string-array name="keyboard_heights" translatable="false"> + <!-- Droid --> + <item>sholes,194.3333</item> + <!-- Nexus One --> + <item>mahimahi,186.2667</item> + <!-- Nexus S --> + <item>herring,171.9385</item> + <!-- Galaxy Nexus --> + <item>tuna,173.4207</item> + </string-array> +</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..8349dcdad 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,10 @@ <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> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Perj. į kt. įvesties būd."</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Kalbos perjungimo klavišu taip pat perjungiami įvesties būdai"</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"Nerodyti klb. keit. klav."</string> <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 +55,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 +68,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 +81,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,46 +93,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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Jei norite išjungti balso įvestį, eikite į įvesties metodo nustatymus."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Jei norite naudoti balso įvestį, paspauskite mikrofono mygtuką."</string> - <string name="voice_listening" msgid="467518160751321844">"Kalbėkite dabar"</string> - <string name="voice_working" msgid="6666937792815731889">"Veikia"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Klaida. Bandykite dar kartą."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Nepavyko prijungti"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Klaida, per daug kalbos."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Problema su garsu"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Serverio klaida"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Negirdima jokia kalba"</string> - <string name="voice_no_match" msgid="4285117547030179174">"Atitikmenų nerasta"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Balso paieška neįdiegta"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Užuomina:"</b>" perbraukite klaviatūra, kad galėtumėte kalbėti"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Užuomina:"</b>" kitą kartą pabandykite sakyti skyrybos ženklų pavadinimus, pvz., „taškas“, „kablelis“ arba „klaustukas“."</string> - <string name="cancel" msgid="6830980399865683324">"Atšaukti"</string> - <string name="ok" msgid="7898366843681727667">"Gerai"</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_input" msgid="3583258583521397548">"Įvesties balsu klavišas"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Pagr. klaviatūroje"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Simbolių klaviatūr."</string> @@ -135,16 +108,15 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikrof. pagr. klav."</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikrof. simb. klav."</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Balso įv. neleidž."</string> - <string name="selectInputMethod" msgid="315076553378705821">"Pasirinkti įvesties metodą"</string> <string name="configure_input_method" msgid="373356270290742459">"Konfigūruoti įvesties metodus"</string> <string name="language_selection_title" msgid="1651299598555326750">"Įvesties kalbos"</string> <string name="select_language" msgid="3693815588777926848">"Įvesties kalbos"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Kad išsaugotumėte, dar kartą palieskite"</string> + <!-- no translation found for hint_add_to_dictionary (573678656946085380) --> + <skip /> <string name="has_dictionary" msgid="6071847973466625007">"Žodynas galimas"</string> <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..b406692dc 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,10 @@ <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> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Pārsl. uz citām iev. met."</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Valodas pārslēgš. taustiņu var lietot arī citām ievades metodēm."</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"Atsp. val. pārsl. taust."</string> <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 +55,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 +68,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 +81,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,46 +93,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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Lai izslēgtu balss ievadi, atveriet ievades metodes iestatījumus."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Lai izmantotu balss ievadi, nospiediet mikrofona taustiņu."</string> - <string name="voice_listening" msgid="467518160751321844">"Runājiet!"</string> - <string name="voice_working" msgid="6666937792815731889">"Notiek apstrāde"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Kļūda. Lūdzu, mēģiniet vēlreiz."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Nevar izveidot savienojumu."</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Kļūda, pārāk ilga balss ievade."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Audio problēma"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Servera kļūda"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Nekas nav dzirdams."</string> - <string name="voice_no_match" msgid="4285117547030179174">"Nav atrasta neviena atbilstība."</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Balss meklēšana nav instalēta."</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Ieteikums:"</b>" slidiniet pirkstu pār tastatūru, lai veiktu balss ievadi."</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Ieteikums:"</b>" nākamreiz mēģiniet izrunāt pieturzīmes, piemēram, “punkts”, “komats” vai “jautājuma zīme”."</string> - <string name="cancel" msgid="6830980399865683324">"Atcelt"</string> - <string name="ok" msgid="7898366843681727667">"Labi"</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_input" msgid="3583258583521397548">"Balss ievades atslēga"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Uz galv. tastatūras"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Uz simbolu tastat."</string> @@ -135,16 +108,14 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikr.uz galv.tastat."</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikr.uz simb.tastat."</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Balss iev. atspējota"</string> - <string name="selectInputMethod" msgid="315076553378705821">"Atlasīt ievades metodi"</string> <string name="configure_input_method" msgid="373356270290742459">"Ievades metožu konfigurēšana"</string> <string name="language_selection_title" msgid="1651299598555326750">"Ievades valodas"</string> <string name="select_language" msgid="3693815588777926848">"Ievades valodas"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Pieskarieties vēlreiz, lai saglabātu"</string> + <string name="hint_add_to_dictionary" msgid="573678656946085380">"Pieskarieties vēlreiz, lai saglabātu."</string> <string name="has_dictionary" msgid="6071847973466625007">"Ir pieejama vārdnīca."</string> <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..d0cccf61b --- /dev/null +++ b/java/res/values-mk/donottranslate-more-keys.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. +*/ +--> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- U+0455: "ѕ" CYRILLIC SMALL LETTER DZE --> + <string name="keylabel_for_south_slavic_row1_6">ѕ</string> + <!-- U+045C: "ќ" CYRILLIC SMALL LETTER KJE --> + <string name="keylabel_for_south_slavic_row2_11">ќ</string> + <!-- U+0437: "з" CYRILLIC SMALL LETTER ZE --> + <string name="keylabel_for_south_slavic_row3_1">з</string> + <!-- U+0453: "ѓ" CYRILLIC SMALL LETTER GJE --> + <string name="keylabel_for_south_slavic_row3_8">ѓ</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..71cceff33 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 alih bahasa"</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,46 +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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Untuk mematikan input suara, pergi ke tetapan kaedah input."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Untuk menggunakan input suara, tekan butang mikrofon."</string> - <string name="voice_listening" msgid="467518160751321844">"Sebutkan sekarang"</string> - <string name="voice_working" msgid="6666937792815731889">"Berfungsi"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Ralat. Sila cuba lagi."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Tidak boleh disambungkan"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Ralat, terlalu banyak pertuturan."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Masalah audio"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Ralat pelayan"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Tiada pertuturan didengari"</string> - <string name="voice_no_match" msgid="4285117547030179174">"Tiada padanan ditemui"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Carian suara tidak dipasang"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021">"Petunjuk"<b>":"</b>" Leret merentasi papan kekunci untuk bercakap"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Petunjuk:"</b>" Lain kali, cuba ucapkan tanda baca seperti \"titik\", \"koma\" atau \"tanda soal\"."</string> - <string name="cancel" msgid="6830980399865683324">"Batal"</string> - <string name="ok" msgid="7898366843681727667">"OK"</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_input" msgid="3583258583521397548">"Kunci input suara"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Hidpkn kekunci utama"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Pd ppn k’unci simbol"</string> @@ -135,16 +108,15 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mik. pd kekunci utma"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mik. pd kekunci smbl"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Input suara dilmphkn"</string> - <string name="selectInputMethod" msgid="315076553378705821">"Pilih kaedah input"</string> <string name="configure_input_method" msgid="373356270290742459">"Konfigurasikan kaedah input"</string> <string name="language_selection_title" msgid="1651299598555326750">"Bahasa input"</string> <string name="select_language" msgid="3693815588777926848">"Bahasa input"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Sentuh sekali lagi untuk menyimpan"</string> + <!-- no translation found for hint_add_to_dictionary (573678656946085380) --> + <skip /> <string name="has_dictionary" msgid="6071847973466625007">"Kamus tersedia"</string> <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..49e6d5faf 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_nordic_row1_11">å</string> + <!-- U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE --> + <string name="keylabel_for_nordic_row2_10">ø</string> + <!-- U+00E6: "æ" LATIN SMALL LETTER AE --> + <string name="keylabel_for_nordic_row2_11">æ</string> + <!-- U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS --> + <string name="more_keys_for_nordic_row2_10">ö</string> + <!-- U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS --> + <string name="more_keys_for_nordic_row2_11">ä</string> </resources> diff --git a/java/res/values-nb/strings.xml b/java/res/values-nb/strings.xml index acd636bdd..c412ea0dd 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,10 @@ <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> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Bytt inndatametode"</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Tasten for språkbytte dekker også andre inndatametoder"</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"Skjul språkbyttetasten"</string> <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 +55,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 +66,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 +81,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,46 +93,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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Gå til innstillinger for inndatametode for å slå av stemmedata."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Trykk på mikrofonknappen for å aktivere stemmedata."</string> - <string name="voice_listening" msgid="467518160751321844">"Snakk nå"</string> - <string name="voice_working" msgid="6666937792815731889">"Arbeider"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Feil. Prøv på nytt."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Kunne ikke koble til"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Feil – for mye tale"</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Lydproblem"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Tjenerfeil"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Ingen tale høres"</string> - <string name="voice_no_match" msgid="4285117547030179174">"Ingen treff"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Talesøk ikke installert"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021">"Hint:"<b>" Sveip over tastaturet for å snakke"</b></string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Hint:"</b>" Neste gang kan du prøve å tale inn tegnsettingen ved for eksempel å si «punktum», «komma» eller «spørsmålstegn»."</string> - <string name="cancel" msgid="6830980399865683324">"Avbryt"</string> - <string name="ok" msgid="7898366843681727667">"OK"</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_input" msgid="3583258583521397548">"Tast for taleinndata"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"På hovedtastatur"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"På talltastatur"</string> @@ -135,16 +108,15 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikrofon på hovedtast."</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikrofon på talltastatur"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Taleinndata er deaktiv."</string> - <string name="selectInputMethod" msgid="315076553378705821">"Velg inndatametode"</string> <string name="configure_input_method" msgid="373356270290742459">"Konfigurer inndatametoder"</string> <string name="language_selection_title" msgid="1651299598555326750">"Inndataspråk"</string> <string name="select_language" msgid="3693815588777926848">"Inndataspråk"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"Trykk på nytt for å lagre"</string> + <!-- no translation found for hint_add_to_dictionary (573678656946085380) --> + <skip /> <string name="has_dictionary" msgid="6071847973466625007">"Ordbok tilgjengelig"</string> <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..73768aff2 100644 --- a/java/res/values-nl/donottranslate-more-keys.xml +++ b/java/res/values-nl/donottranslate-more-keys.xml @@ -18,10 +18,49 @@ */ --> <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 + U+0133: "ij" LATIN SMALL LIGATURE IJ --> + <string name="more_keys_for_i">í,ï,ì,î,į,ī,ij</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> + <!-- U+0133: "ij" LATIN SMALL LIGATURE IJ --> + <string name="more_keys_for_y">ij</string> </resources> diff --git a/java/res/values-nl/strings.xml b/java/res/values-nl/strings.xml index 7f0ff7eaf..8f33aa963 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,10 @@ <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> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Invoermeth. overschakelen"</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Schakelknop voor taal ook van toepassing op andere invoermethoden"</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"Taal schakelen onderdr."</string> <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 +55,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 +68,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 +81,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,46 +93,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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Als u spraakinvoer wilt uitschakelen, gaat u naar de instellingen voor invoermethoden."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Druk op de microfoontoets om spraakinvoer te gebruiken."</string> - <string name="voice_listening" msgid="467518160751321844">"Nu spreken"</string> - <string name="voice_working" msgid="6666937792815731889">"Wordt uitgevoerd"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Fout. Probeer het opnieuw."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Kan geen verbinding maken"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Fout, te lange spraakinvoer."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Audioprobleem"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Serverfout"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Geen spraak te horen"</string> - <string name="voice_no_match" msgid="4285117547030179174">"Geen resultaten gevonden"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Spraakgestuurd zoeken is niet geïnstalleerd"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Hint:"</b>" schuif over het toetsenbord om te spreken"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Hint:"</b>" spreek de volgende keer interpunctie uit, zoals \'period\' (punt), \'comma\' (komma) of \'question mark\' (vraagteken)."</string> - <string name="cancel" msgid="6830980399865683324">"Annuleren"</string> - <string name="ok" msgid="7898366843681727667">"OK"</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_input" msgid="3583258583521397548">"Sleutel voor spraakinvoer"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Op hoofdtoetsenbord"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Op symbooltoetsenb."</string> @@ -135,16 +108,14 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mic op hoofdtoetsb."</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mic op symb.toetsb."</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Spraakinvoer is uit"</string> - <string name="selectInputMethod" msgid="315076553378705821">"Invoermethode selecteren"</string> <string name="configure_input_method" msgid="373356270290742459">"Invoermethoden configureren"</string> <string name="language_selection_title" msgid="1651299598555326750">"Invoertalen"</string> <string name="select_language" msgid="3693815588777926848">"Invoertalen"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Raak nogmaals aan om op te slaan"</string> + <string name="hint_add_to_dictionary" msgid="573678656946085380">"Raak nogmaals aan om op te slaan"</string> <string name="has_dictionary" msgid="6071847973466625007">"Woordenboek beschikbaar"</string> <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 d737ebd8f..ea358c0c6 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,10 @@ <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> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Włącz inne metody wprowadzania"</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Klawisz zmiany języka obejmuje też inne metody wprowadzania"</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"Wyłącz klawisz zmiany języka"</string> <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 +55,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 +68,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 +81,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,46 +93,14 @@ <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="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 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> - <string name="voice_working" msgid="6666937792815731889">"W toku"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Błąd. Spróbuj ponownie."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Nie można nawiązać połączenia"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Błąd, zbyt długa wypowiedź."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Problem z dźwiękiem"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Błąd serwera"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Nie wykryto mowy"</string> - <string name="voice_no_match" msgid="4285117547030179174">"Brak wyników"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Wyszukiwanie głosowe nie jest zainstalowane"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Wskazówka:"</b>" przesuń palcem po klawiaturze, aby mówić."</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Wskazówka:"</b>" następnym razem spróbuj wypowiadać nazwy znaków interpunkcyjnych: „kropka”, „przecinek” lub „pytajnik”."</string> - <string name="cancel" msgid="6830980399865683324">"Anuluj"</string> - <string name="ok" msgid="7898366843681727667">"OK"</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_input" msgid="3583258583521397548">"Klawisz rozpoznawania mowy"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Na klawiaturze głównej"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Na klawiaturze z symbolami"</string> @@ -135,16 +108,15 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikrofon na klawiaturze głównej"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikrofon na klawiaturze z symbolami"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Wprowadzanie głosowe jest wyłączone"</string> - <string name="selectInputMethod" msgid="315076553378705821">"Wybierz sposób wprowadzania tekstu"</string> <string name="configure_input_method" msgid="373356270290742459">"Konfiguruj metody wprowadzania"</string> <string name="language_selection_title" msgid="1651299598555326750">"Języki wprowadzania"</string> <string name="select_language" msgid="3693815588777926848">"Języki wprowadzania"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Dotknij ponownie, aby zapisać"</string> + <!-- no translation found for hint_add_to_dictionary (573678656946085380) --> + <skip /> <string name="has_dictionary" msgid="6071847973466625007">"Słownik dostępny"</string> <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..7a0c6c20d 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,10 @@ <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> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Mudar p/ outros mét. ent."</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"A tecla de mudança de idioma abrange outros métodos de entrada"</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"Suprimir tecla mud idioma"</string> <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 +55,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 +68,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 +81,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,46 +93,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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Para desactivar a entrada de voz, aceda às definições do método de entrada."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Para utilizar a entrada de voz, prima o botão do microfone."</string> - <string name="voice_listening" msgid="467518160751321844">"Falar agora"</string> - <string name="voice_working" msgid="6666937792815731889">"A executar"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Erro. Tente novamente."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Não foi possível ligar"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Erro, discurso demasiado longo."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Problema de áudio"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Erro no servidor"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Nenhuma voz ouvida"</string> - <string name="voice_no_match" msgid="4285117547030179174">"Não foram encontradas correspondências"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Pesquisa de voz não instalada"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Sugestão:"</b>" Deslize no teclado para falar"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Sugestão:"</b>" Da próxima vez, experimente dizer a pontuação como \"ponto final\", \"vírgula\" ou \"ponto de interrogação\"."</string> - <string name="cancel" msgid="6830980399865683324">"Cancelar"</string> - <string name="ok" msgid="7898366843681727667">"OK"</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_input" msgid="3583258583521397548">"Chave de entrada de voz"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"No teclado principal"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"No teclado símbolos"</string> @@ -135,16 +108,14 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mic. tecl. principal"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mic. tecl. símbolos"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Entr. voz desact."</string> - <string name="selectInputMethod" msgid="315076553378705821">"Selecionar método de entrada"</string> <string name="configure_input_method" msgid="373356270290742459">"Configurar métodos de introdução"</string> <string name="language_selection_title" msgid="1651299598555326750">"Idiomas de entrada"</string> <string name="select_language" msgid="3693815588777926848">"Idiomas de introdução"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Toque novamente para guardar"</string> + <string name="hint_add_to_dictionary" msgid="573678656946085380">"Toque novamente para guardar"</string> <string name="has_dictionary" msgid="6071847973466625007">"Dicionário disponível"</string> <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..9a0cf30de 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,10 @@ <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> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Outros métodos de entrada"</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"A tecla p/ mudar o idioma também cobre outros métodos de entrada"</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"Ocult. tecla mudar idioma"</string> <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 +55,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 +68,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 +81,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,46 +93,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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Para desativar a entrada de texto por voz, vá para configurações do método de entrada."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Para usar a entrada de texto por voz, pressione o botão do microfone."</string> - <string name="voice_listening" msgid="467518160751321844">"Fale agora"</string> - <string name="voice_working" msgid="6666937792815731889">"Trabalhando"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Erro. Tente novamente."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Não foi possível conectar"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Erro, fala muito longa."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Problema com o áudio"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Erro do servidor"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Nenhuma fala ouvida"</string> - <string name="voice_no_match" msgid="4285117547030179174">"Não há resultados compatíveis"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"A pesquisa por voz não está instalada"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Dica:"</b>" Deslize sobre o teclado para falar"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Dica:"</b>" Da próxima vez, tente falar o nome da pontuação como \"ponto\", \"vírgula\" ou \"ponto de interrogação\"."</string> - <string name="cancel" msgid="6830980399865683324">"Cancelar"</string> - <string name="ok" msgid="7898366843681727667">"OK"</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_input" msgid="3583258583521397548">"Chave de entrada de texto por voz"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"No teclado principal"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"No teclado de símb."</string> @@ -135,16 +108,14 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mic. no teclado"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mic. no teclado"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Texto por voz desat."</string> - <string name="selectInputMethod" msgid="315076553378705821">"Selecionar método de entrada"</string> <string name="configure_input_method" msgid="373356270290742459">"Configurar métodos de entrada"</string> <string name="language_selection_title" msgid="1651299598555326750">"Idiomas de entrada"</string> <string name="select_language" msgid="3693815588777926848">"Idiomas de entrada"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Toque novamente para salvar"</string> + <string name="hint_add_to_dictionary" msgid="573678656946085380">"Toque novamente para salvar"</string> <string name="has_dictionary" msgid="6071847973466625007">"Dicionário disponível"</string> <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 ad35da880..bacb7d47c 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,8 +84,6 @@ <skip /> <!-- no translation found for prefs_suggestion_visibility_hide_name (6309143926422234673) --> <skip /> - <!-- no translation found for prefs_settings_key (4623341240804046498) --> - <skip /> <!-- no translation found for auto_correction (4979925752001319458) --> <skip /> <!-- no translation found for auto_correction_summary (5625751551134658006) --> @@ -98,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) --> @@ -120,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 /> @@ -144,69 +154,22 @@ <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) --> + <!-- no translation found for spoken_description_mode_phone_shift (5499629753962641227) --> <skip /> - <!-- no translation found for spoken_description_low_double_quote (3551394572784840975) --> - <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> - <!-- 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> - <string name="voice_error" msgid="5140896300312186162">"Errur. Empruvai anc ina giada."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Impussibel da connectar."</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Errur - discurrì memia ditg."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Problem audio"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Errur dal server"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Betg udì ina frasa vocala"</string> - <string name="voice_no_match" msgid="4285117547030179174">"Betg chattà correspundenzas"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Betg installà la tschertga vocala"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Commentari:"</b>" Stritgai cun il det sur la tastatura per discurrer."</string> - <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> <!-- no translation found for voice_input (3583258583521397548) --> <skip /> <!-- no translation found for voice_input_modes_main_keyboard (3360660341121083174) --> @@ -221,22 +184,18 @@ <skip /> <!-- no translation found for voice_input_modes_summary_off (63875609591897607) --> <skip /> - <!-- no translation found for selectInputMethod (315076553378705821) --> - <skip /> <!-- no translation found for configure_input_method (373356270290742459) --> <skip /> <string name="language_selection_title" msgid="1651299598555326750">"Linguas da cumonds vocals"</string> <!-- no translation found for select_language (3693815588777926848) --> <skip /> - <!-- no translation found for hint_add_to_dictionary (9006292060636342317) --> + <!-- no translation found for hint_add_to_dictionary (573678656946085380) --> <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> <!-- no translation found for keyboard_layout (8451164783510487501) --> <skip /> - <!-- no translation found for subtype_de_qwerty (3358900499589259491) --> - <skip /> <!-- no translation found for subtype_en_GB (88170601942311355) --> <skip /> <!-- no translation found for subtype_en_US (6160452336634534239) --> 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..a33805160 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,10 @@ <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> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Comut. alte metode de introd."</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Tasta de comutare între limbi include şi alte metode de introd."</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"Suprim. tasta comut. limbi"</string> <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 +55,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 +68,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 +81,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,46 +93,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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Pentru a dezactiva intrarea vocală, accesaţi setările metodei de intrare."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Pentru a utiliza intrarea vocală, apăsaţi pe butonul Microfon."</string> - <string name="voice_listening" msgid="467518160751321844">"Vorbiţi acum"</string> - <string name="voice_working" msgid="6666937792815731889">"Se analizează"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Eroare. Încercaţi din nou."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Conectare imposibilă"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Eroare, discurs prea lung."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Problemă audio"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Eroare de server"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Nu s-a auzit vorbirea"</string> - <string name="voice_no_match" msgid="4285117547030179174">"Nicio potrivire"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Căutarea vocală nu este instalată"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Indiciu:"</b>" glisaţi de-a lungul tastaturii pentru a vorbi"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Indiciu:"</b>" data viitoare, încercaţi să rostiţi şi punctuaţia, cum ar fi „punct”, „virgulă”, sau „semn de întrebare”."</string> - <string name="cancel" msgid="6830980399865683324">"Anulaţi"</string> - <string name="ok" msgid="7898366843681727667">"OK"</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_input" msgid="3583258583521397548">"Tastă pentru intrarea vocală"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Pe tastat. princip."</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Pe tastat. simbol."</string> @@ -135,16 +108,15 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mic. pe tast. princ."</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Micr. pe tast. simb."</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Intr. vocală dezact."</string> - <string name="selectInputMethod" msgid="315076553378705821">"Selectaţi metoda de introducere a textului"</string> <string name="configure_input_method" msgid="373356270290742459">"Configuraţi metodele de intrare"</string> <string name="language_selection_title" msgid="1651299598555326750">"Selectaţi limba"</string> <string name="select_language" msgid="3693815588777926848">"Limbi de intrare"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Atingeţi din nou pentru a salva"</string> + <!-- no translation found for hint_add_to_dictionary (573678656946085380) --> + <skip /> <string name="has_dictionary" msgid="6071847973466625007">"Dicţionar disponibil"</string> <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..0bb57074c 100644 --- a/java/res/values-ru/donottranslate-more-keys.xml +++ b/java/res/values-ru/donottranslate-more-keys.xml @@ -18,7 +18,16 @@ */ --> <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+0449: "щ" CYRILLIC SMALL LETTER SHCHA --> + <string name="keylabel_for_east_slavic_row1_9">щ</string> + <!-- U+044B: "ы" CYRILLIC SMALL LETTER YERU --> + <string name="keylabel_for_east_slavic_row2_1">ы</string> + <!-- U+0438: "и" CYRILLIC SMALL LETTER I --> + <string name="keylabel_for_east_slavic_row3_5">и</string> + <!-- U+0451: "ё" CYRILLIC SMALL LETTER IO --> + <string name="more_keys_for_cyrillic_ye">ё</string> + <!-- U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN --> + <string name="more_keys_for_cyrillic_ha">ъ</string> + <!-- U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN --> + <string name="more_keys_for_cyrillic_soft_sign">ъ</string> </resources> diff --git a/java/res/values-ru/strings.xml b/java/res/values-ru/strings.xml index 855e95ef4..3ec5daf7e 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="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">"Включена фиксация верхнего регистра"</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,46 +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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Функция голосового ввода отключается в настройках способа ввода."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Чтобы использовать голосовой ввод, нажмите кнопку микрофона."</string> - <string name="voice_listening" msgid="467518160751321844">"Говорите"</string> - <string name="voice_working" msgid="6666937792815731889">"Обработка запроса"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Ошибка. Повторите попытку."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Ошибка подключения"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Слишком длинная фраза"</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Неполадка со звуком"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Ошибка сервера"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Речи не слышно"</string> - <string name="voice_no_match" msgid="4285117547030179174">"Ничего не найдено"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Голосовой поиск не установлен"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Совет"</b>". Проведите пальцем по клавиатуре для голосового ввода."</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Совет"</b>". В следующий раз проговаривайте знаки препинания, например \"точка\", \"запятая\", \"вопросительный знак\"."</string> - <string name="cancel" msgid="6830980399865683324">"Отмена"</string> - <string name="ok" msgid="7898366843681727667">"ОК"</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_input" msgid="3583258583521397548">"Ключ голосового ввода"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Значок на основной клавиатуре"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Значок на клавиатуре символов"</string> @@ -135,16 +108,15 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Значок на основной клавиатуре"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Значок на клавиатуре символов"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Голосовой ввод откл."</string> - <string name="selectInputMethod" msgid="315076553378705821">"Выбрать способ ввода"</string> <string name="configure_input_method" msgid="373356270290742459">"Настройка способов ввода"</string> <string name="language_selection_title" msgid="1651299598555326750">"Языки ввода"</string> <string name="select_language" msgid="3693815588777926848">"Языки ввода"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Нажмите, чтобы сохранить"</string> + <!-- no translation found for hint_add_to_dictionary (573678656946085380) --> + <skip /> <string name="has_dictionary" msgid="6071847973466625007">"Доступен словарь"</string> <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-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..95ebad1bf 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,10 @@ <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> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Prepnúť na iné metódy vstupu"</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Kláves na prepnutie jazyka pokrýva aj ďalšie metódy vstupu"</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"Blok. kláves prep. jazyka"</string> <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 +55,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 +68,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 +81,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,46 +93,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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Ak chcete vypnúť hlasový vstup, prejdite na nastavenia metódy vstupu."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Ak chcete použiť hlasový vstup, stlačte tlačidlo mikrofón."</string> - <string name="voice_listening" msgid="467518160751321844">"Hovorte"</string> - <string name="voice_working" msgid="6666937792815731889">"Prebieha spracovanie"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Chyba. Skúste to znova."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Pripojenie sa nepodarilo."</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Chyba, reč je príliš dlhá."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Problém so zvukom"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Chyba servera"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Nebola zistená žiadna reč."</string> - <string name="voice_no_match" msgid="4285117547030179174">"Nenašli sa žiadne zhody"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Hlasové vyhľadávanie nie je nainštalované"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Tip:"</b>" Ak chcete aktivovať hlasový vstup, prejdite prstom po klávesnici."</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Tip:"</b>" Nabudúce skúste vysloviť interpunkciu, napríklad „bodka“, „čiarka“ alebo „otáznik“."</string> - <string name="cancel" msgid="6830980399865683324">"Zrušiť"</string> - <string name="ok" msgid="7898366843681727667">"OK"</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_input" msgid="3583258583521397548">"Kľúč hlasového vstupu"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Na hlavnej klávesnici"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Na klávesnici so symbolmi"</string> @@ -135,16 +108,15 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mikrofón na hlavnej klávesnici"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mikrofón na klávesnici so symbolmi"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Hlasový vstup je zakázaný"</string> - <string name="selectInputMethod" msgid="315076553378705821">"Výber metódy vstupu"</string> <string name="configure_input_method" msgid="373356270290742459">"Konfigurovať metódy vstupu"</string> <string name="language_selection_title" msgid="1651299598555326750">"Jazyky vstupu"</string> <string name="select_language" msgid="3693815588777926848">"Jazyky vstupu"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Ďalším dotykom slovo uložíte"</string> + <!-- no translation found for hint_add_to_dictionary (573678656946085380) --> + <skip /> <string name="has_dictionary" msgid="6071847973466625007">"K dispozícii je slovník"</string> <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..636894844 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,10 @@ <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> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Prekl. na drug nač. vnosa"</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Tipka za preklop jezika, ki vključuje tudi druge načine vnosa"</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"Onemogoči tipko za preklop jezika"</string> <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 +55,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 +68,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 +81,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,46 +93,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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Glasovni vnos izklopite v nastavitvah načina vnosa."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Če želite uporabljati glasovni vnos, pritisnite gumb z mikrofonom."</string> - <string name="voice_listening" msgid="467518160751321844">"Začnite govoriti"</string> - <string name="voice_working" msgid="6666937792815731889">"Obdelava"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Napaka. Poskusite znova."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Povezava ni mogoča"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Napaka, preveč govora."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Težave z zvokom"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Napaka strežnika"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Govora se ne sliši"</string> - <string name="voice_no_match" msgid="4285117547030179174">"Ni rezultatov"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Glasovno iskanje ni nameščeno"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Nasvet:"</b>" za govorjenje s prstom povlecite po tipkovnici"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Nasvet:"</b>" naslednjič poskusite ločila izgovoriti, npr. »pika«, »vejica« ali »vprašaj«."</string> - <string name="cancel" msgid="6830980399865683324">"Prekliči"</string> - <string name="ok" msgid="7898366843681727667">"V redu"</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_input" msgid="3583258583521397548">"Tipka za glasovni vnos"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Na glavni tipkovnici"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Na tipk. s simboli"</string> @@ -135,16 +108,14 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mik. na glavni tipk."</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mik. na tipk. s sim."</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Glas. vnos je onem."</string> - <string name="selectInputMethod" msgid="315076553378705821">"Izberite način vnosa"</string> <string name="configure_input_method" msgid="373356270290742459">"Nastavitev načinov vnosa"</string> <string name="language_selection_title" msgid="1651299598555326750">"Jeziki vnosa"</string> <string name="select_language" msgid="3693815588777926848">"Jeziki vnosa"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Še enkrat se dotaknite, da shranite"</string> + <string name="hint_add_to_dictionary" msgid="573678656946085380">"Dotaknite se še enkrat, da shranite"</string> <string name="has_dictionary" msgid="6071847973466625007">"Slovar je na voljo"</string> <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/donottranslate-more-keys.xml b/java/res/values-sr/donottranslate-more-keys.xml new file mode 100644 index 000000000..e85d3d7a2 --- /dev/null +++ b/java/res/values-sr/donottranslate-more-keys.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. +*/ +--> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + <!-- U+0437: "з" CYRILLIC SMALL LETTER ZE --> + <string name="keylabel_for_south_slavic_row1_6">з</string> + <!-- U+045B: "ћ" CYRILLIC SMALL LETTER TSHE --> + <string name="keylabel_for_south_slavic_row2_11">ћ</string> + <!-- U+0455: "ѕ" CYRILLIC SMALL LETTER DZE --> + <string name="keylabel_for_south_slavic_row3_1">ѕ</string> + <!-- U+0452: "ђ" CYRILLIC SMALL LETTER DJE --> + <string name="keylabel_for_south_slavic_row3_8">ђ</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-sr/strings.xml b/java/res/values-sr/strings.xml index 0906fce6e..49aefd156 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,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">"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,46 +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">"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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Да бисте искључили гласовни унос, идите на подешавања за начин уноса."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Да бисте користили гласовни унос, притисните дугме за микрофон."</string> - <string name="voice_listening" msgid="467518160751321844">"Говорите сада"</string> - <string name="voice_working" msgid="6666937792815731889">"Обрада"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Грешка. Покушајте поново."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Повезивање није могуће"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Грешка, говорите предуго."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Проблем са звуком"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Грешка сервера"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Не чује се говор"</string> - <string name="voice_no_match" msgid="4285117547030179174">"Нема подударања"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Гласовна претрага није инсталирана"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Савет:"</b>" Превуците прстом преко тастатуре за гласовни унос"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Савет:"</b>" Следећи пут покушајте да изговорите знакове интерпункције као што су „тачка“, „зарез“ или „знак питања“."</string> - <string name="cancel" msgid="6830980399865683324">"Откажи"</string> - <string name="ok" msgid="7898366843681727667">"Потврди"</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_input" msgid="3583258583521397548">"Тастер за гласовни унос"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"На главној тастатури"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"На тастатури са симболима"</string> @@ -135,16 +108,15 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Микрофон на главној тастатури"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Микрофон на тастатури са симболима"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Гласовни унос је онемогућен"</string> - <string name="selectInputMethod" msgid="315076553378705821">"Изаберите метод уноса"</string> <string name="configure_input_method" msgid="373356270290742459">"Конфигурисање метода уноса"</string> <string name="language_selection_title" msgid="1651299598555326750">"Језици за унос"</string> <string name="select_language" msgid="3693815588777926848">"Језици уноса"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Поново додирните да бисте сачували"</string> + <!-- no translation found for hint_add_to_dictionary (573678656946085380) --> + <skip /> <string name="has_dictionary" msgid="6071847973466625007">"Речник је доступан"</string> <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..d479191f4 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_nordic_row1_11">å</string> + <!-- U+00F6: "ö" LATIN SMALL LETTER O WITH DIAERESIS --> + <string name="keylabel_for_nordic_row2_10">ö</string> + <!-- U+00E4: "ä" LATIN SMALL LETTER A WITH DIAERESIS --> + <string name="keylabel_for_nordic_row2_11">ä</string> + <!-- U+00F8: "ø" LATIN SMALL LETTER O WITH STROKE --> + <string name="more_keys_for_nordic_row2_10">ø</string> + <!-- U+00E6: "æ" LATIN SMALL LETTER AE --> + <string name="more_keys_for_nordic_row2_11">æ</string> </resources> diff --git a/java/res/values-sv/strings.xml b/java/res/values-sv/strings.xml index 46760bbe2..3c5ecd526 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,10 @@ <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> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Byt till annan inmatning"</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Språkbytesknappen omfattar även andra inmatningsmetoder"</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"Stäng av språkbytesknapp"</string> <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 +55,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 +68,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 +81,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,46 +93,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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Om du vill stänga av röstinmatning öppnar du inställningarna för inmatningsmetod."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Om du vill använda röstinmatning trycker du på mikrofonknappen."</string> - <string name="voice_listening" msgid="467518160751321844">"Tala nu"</string> - <string name="voice_working" msgid="6666937792815731889">"Fungerar"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Fel. Försök igen."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Det gick inte att ansluta"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Fel, för mycket tal."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Ljudproblem"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Serverfel"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Hörde inget tal"</string> - <string name="voice_no_match" msgid="4285117547030179174">"Inga träffar hittades"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Voice Search är inte installerat"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Tips!"</b>" Dra över tangentbordet om du vill tala"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Tips!"</b>" Nästa gång testar du att säga skiljetecknen, som \"punkt\", \"komma\" eller \"frågetecken\"."</string> - <string name="cancel" msgid="6830980399865683324">"Avbryt"</string> - <string name="ok" msgid="7898366843681727667">"OK"</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_input" msgid="3583258583521397548">"Röstinmatningsknapp"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"På huvudtangentbord"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"På symboltangentbord"</string> @@ -135,16 +108,14 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mick huvudtangentbord"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mick bland symboler"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Röstinmatning inaktiv"</string> - <string name="selectInputMethod" msgid="315076553378705821">"Välj inmatningsmetod"</string> <string name="configure_input_method" msgid="373356270290742459">"Konfigurera inmatningsmetoder"</string> <string name="language_selection_title" msgid="1651299598555326750">"Inmatningsspråk"</string> <string name="select_language" msgid="3693815588777926848">"Inmatningsspråk"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Tryck igen för att spara"</string> + <string name="hint_add_to_dictionary" msgid="573678656946085380">"Spara genom att trycka igen"</string> <string name="has_dictionary" msgid="6071847973466625007">"En ordlista är tillgänglig"</string> <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..e849ade44 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,10 @@ <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> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Badilisha kwa mbinu zingine za ingizo"</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Ufunguo wa kubadilisha lugha unashughulikia mbinu zingine za ingizo pia"</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"Zuia ufunguo wa kubadili lugha"</string> <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 +55,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 +68,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 +81,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,46 +93,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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Ili kuzima uingizaji sauti, nenda kwa mipangilio ya mbinu ya uingizaji."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Ili kutumia uingizaji wa sauti, bonyeza kitufe cha maikrofoni."</string> - <string name="voice_listening" msgid="467518160751321844">"Ongea sasa"</string> - <string name="voice_working" msgid="6666937792815731889">"Inafanya kazi"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Hitilafu. Tafadhali jaribu tena."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Haiwezi kuunganisha"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Hitilafu, usemi ni zaidi."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Tatizo la sauti"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Hitilafu ya Seva"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Hakuna matamshi yaliyosikizwa"</string> - <string name="voice_no_match" msgid="4285117547030179174">"Hakuna zinazolingana zilizopatikana."</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Utafutaji wa sauti haujawekwa"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Kidokezo:"</b>" Telezesha kidole kwenye kibodi ili utamke"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Kidokezo:"</b>" Wakati mwingine, jaribu kutamka uakifishaji kama vile \"kituo\", \"koma\", au \"kiulizio cha swali\"."</string> - <string name="cancel" msgid="6830980399865683324">"Ghairi"</string> - <string name="ok" msgid="7898366843681727667">"Sawa"</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_input" msgid="3583258583521397548">"Kibao cha kuingizia sauti"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Kwenye kibodi kuu"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Kwenye kibodi ya ishara"</string> @@ -135,16 +108,14 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Maikrofoni kwenye kibodi kuu"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Maikrofoni kwenye kibodi ya ishara"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Uingizaji sauti umelemazwa"</string> - <string name="selectInputMethod" msgid="315076553378705821">"Chagua mtindo wa uingizaji"</string> <string name="configure_input_method" msgid="373356270290742459">"Sanidi mbinu za uingizaji"</string> <string name="language_selection_title" msgid="1651299598555326750">"Lugha za uingizaji"</string> <string name="select_language" msgid="3693815588777926848">"Lugha zinazoruhusiwa"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Gusa tena ili kuhifadhi"</string> + <string name="hint_add_to_dictionary" msgid="573678656946085380">"Gusa tena ili kuhifadhi"</string> <string name="has_dictionary" msgid="6071847973466625007">"Kamusi inapatikana"</string> <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 c945ea143..8a59c9b54 100644 --- a/java/res/values-sw600dp-land/dimens.xml +++ b/java/res/values-sw600dp-land/dimens.xml @@ -19,8 +19,9 @@ --> <resources> - <!-- keyboardHeight = key_height*4 + key_bottom_gap*3 --> - <dimen name="keyboardHeight">45.0mm</dimen> + <!-- Preferable keyboard height in absolute scale: 45.0mm --> + <!-- This keyboardHeight value should match with keyboard-heights.xml --> + <dimen name="keyboardHeight">283.5dp</dimen> <fraction name="minKeyboardHeight">45%p</fraction> <fraction name="keyboard_top_padding">2.444%p</fraction> @@ -28,19 +29,19 @@ <fraction name="key_bottom_gap">4.911%p</fraction> <fraction name="key_horizontal_gap">1.284%p</fraction> - <dimen name="keyboardHeight_stone">45.0mm</dimen> <fraction name="key_bottom_gap_stone">4.355%p</fraction> <fraction name="key_horizontal_gap_stone">1.505%p</fraction> <fraction name="key_bottom_gap_gb">5.200%p</fraction> <fraction name="key_horizontal_gap_gb">1.447%p</fraction> + <fraction name="key_bottom_gap_ics">4.0%p</fraction> <fraction name="keyboard_bottom_padding_ics">0.0%p</fraction> - <dimen name="popup_key_height">13.0mm</dimen> + <dimen name="popup_key_height">81.9dp</dimen> <!-- left or right padding of label alignment --> - <dimen name="key_label_horizontal_padding">18dip</dimen> + <dimen name="key_label_horizontal_padding">18dp</dimen> <fraction name="key_letter_ratio">45%</fraction> <fraction name="key_large_letter_ratio">48%</fraction> @@ -48,8 +49,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> + <dimen name="suggestions_strip_padding">252.0dp</dimen> <integer name="max_more_suggestions_row">5</integer> <fraction name="min_more_suggestions_width">50%</fraction> </resources> diff --git a/java/res/values-sw600dp-land/keyboard-heights.xml b/java/res/values-sw600dp-land/keyboard-heights.xml new file mode 100644 index 000000000..93f9824d1 --- /dev/null +++ b/java/res/values-sw600dp-land/keyboard-heights.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. +*/ +--> + +<!-- Preferable keyboard height in absolute scale: 45.0mm --> +<resources> + <!-- Build.HARDWARE,keyboard_height_in_dp --> + <string-array name="keyboard_heights" translatable="false"> + <!-- Xoom --> + <item>stingray,265.4378</item> + </string-array> +</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 f33e9f28b..cb2a86153 100644 --- a/java/res/values-sw600dp/dimens.xml +++ b/java/res/values-sw600dp/dimens.xml @@ -19,36 +19,37 @@ --> <resources> - <!-- keyboardHeight = key_height*4 + key_bottom_gap*3 --> - <dimen name="keyboardHeight">48.0mm</dimen> - <fraction name="maxKeyboardHeight">50%p</fraction> + <!-- Preferable keyboard height in absolute scale: 48.0mm --> + <!-- This keyboardHeight value should match with keyboard-heights.xml --> + <dimen name="keyboardHeight">302.4dp</dimen> + <fraction name="maxKeyboardHeight">46%p</fraction> <fraction name="minKeyboardHeight">-35.0%p</fraction> - <dimen name="popup_key_height">10.0mm</dimen> + <dimen name="popup_key_height">63.0dp</dimen> <fraction name="keyboard_top_padding">2.291%p</fraction> <fraction name="keyboard_bottom_padding">0.0%p</fraction> <fraction name="key_bottom_gap">3.750%p</fraction> <fraction name="key_horizontal_gap">1.857%p</fraction> - <dimen name="keyboardHeight_stone">48.0mm</dimen> <fraction name="key_bottom_gap_stone">3.75%p</fraction> <fraction name="key_horizontal_gap_stone">1.602%p</fraction> <fraction name="key_bottom_gap_gb">4.625%p</fraction> <fraction name="key_horizontal_gap_gb">2.113%p</fraction> + <fraction name="key_bottom_gap_ics">4.0%p</fraction> <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">6dp</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">98.3dp</dimen> <!-- popup_key_height x -1.0 --> - <dimen name="mini_keyboard_vertical_correction">-13.0mm</dimen> + <dimen name="more_keys_keyboard_vertical_correction">-81.9dp</dimen> <!-- left or right padding of label alignment --> - <dimen name="key_label_horizontal_padding">6dip</dimen> + <dimen name="key_label_horizontal_padding">6dp</dimen> <dimen name="key_hint_letter_padding">3dp</dimen> <dimen name="key_uppercase_letter_padding">3dp</dimen> @@ -59,19 +60,21 @@ <fraction name="key_hint_label_ratio">28%</fraction> <fraction name="key_uppercase_letter_ratio">26%</fraction> <fraction name="key_preview_text_ratio">50%</fraction> - <dimen name="key_preview_height">15.0mm</dimen> - <dimen name="key_preview_offset">0.1in</dimen> + <fraction name="spacebar_text_ratio">32.14%</fraction> + <dimen name="key_preview_height">94.5dp</dimen> + <dimen name="key_preview_offset">16.0dp</dimen> - <dimen name="key_preview_height_ics">15.0mm</dimen> - <dimen name="key_preview_offset_ics">0.05in</dimen> + <dimen name="key_preview_offset_ics">8.0dp</dimen> + <!-- popup_key_height x -0.5 --> + <dimen name="more_keys_keyboard_vertical_correction_ics">-31.5dp</dimen> - <dimen name="suggestions_strip_height">44dip</dimen> - <dimen name="more_suggestions_row_height">44dip</dimen> + <dimen name="suggestions_strip_height">44dp</dimen> + <dimen name="more_suggestions_row_height">44dp</dimen> <integer name="max_more_suggestions_row">6</integer> <fraction name="min_more_suggestions_width">90%</fraction> - <dimen name="suggestions_strip_padding">15.0mm</dimen> - <dimen name="suggestion_min_width">0.3in</dimen> - <dimen name="suggestion_padding">12dip</dimen> - <dimen name="suggestion_text_size">22dip</dimen> - <dimen name="more_suggestions_hint_text_size">33dip</dimen> + <dimen name="suggestions_strip_padding">94.5dp</dimen> + <dimen name="suggestion_min_width">48.0dp</dimen> + <dimen name="suggestion_padding">12dp</dimen> + <dimen name="suggestion_text_size">22dp</dimen> + <dimen name="more_suggestions_hint_text_size">33dp</dimen> </resources> diff --git a/java/res/values-sw600dp/keyboard-heights.xml b/java/res/values-sw600dp/keyboard-heights.xml new file mode 100644 index 000000000..77e52be2f --- /dev/null +++ b/java/res/values-sw600dp/keyboard-heights.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. +*/ +--> + +<!-- Preferable keyboard height in absolute scale: 48.0mm --> +<resources> + <!-- Build.HARDWARE,keyboard_height_in_dp --> + <string-array name="keyboard_heights" translatable="false"> + <!-- Xoom --> + <item>stingray,283.1337</item> + </string-array> +</resources> diff --git a/java/res/values-sw768dp-land/dimens.xml b/java/res/values-sw768dp-land/dimens.xml index 664e8c159..b95c858dc 100644 --- a/java/res/values-sw768dp-land/dimens.xml +++ b/java/res/values-sw768dp-land/dimens.xml @@ -19,8 +19,9 @@ --> <resources> - <!-- keyboardHeight = key_height*4 + key_bottom_gap*3, key_height=14.5mm --> - <dimen name="keyboardHeight">58.0mm</dimen> + <!-- Preferable keyboard height in absolute scale: 58.0mm --> + <!-- This keyboardHeight value should match with keyboard-heights.xml --> + <dimen name="keyboardHeight">365.4dp</dimen> <fraction name="minKeyboardHeight">45%p</fraction> <fraction name="keyboard_top_padding">1.896%p</fraction> @@ -29,7 +30,6 @@ <fraction name="key_bottom_gap">4.103%p</fraction> <fraction name="key_horizontal_gap">1.034%p</fraction> - <dimen name="keyboardHeight_stone">58.0mm</dimen> <fraction name="key_bottom_gap_stone">3.379%p</fraction> <fraction name="key_horizontal_gap_stone">1.062%p</fraction> @@ -41,10 +41,10 @@ <fraction name="key_bottom_gap_ics">3.690%p</fraction> <fraction name="key_horizontal_gap_ics">1.030%p</fraction> - <dimen name="popup_key_height">13.0mm</dimen> + <dimen name="popup_key_height">81.9dp</dimen> <!-- left or right padding of label alignment --> - <dimen name="key_label_horizontal_padding">18dip</dimen> + <dimen name="key_label_horizontal_padding">18dp</dimen> <fraction name="key_letter_ratio">43%</fraction> <fraction name="key_large_letter_ratio">42%</fraction> @@ -52,11 +52,11 @@ <fraction name="key_hint_letter_ratio">23%</fraction> <fraction name="key_hint_label_ratio">28%</fraction> <fraction name="key_uppercase_letter_ratio">24%</fraction> - <dimen name="key_preview_height">17.0mm</dimen> + <fraction name="spacebar_text_ratio">24.00%</fraction> + <dimen name="key_preview_height">107.1dp</dimen> - <dimen name="key_preview_height_ics">26.5mm</dimen> - <dimen name="key_preview_offset_ics">0.05in</dimen> + <dimen name="key_preview_offset_ics">8.0dp</dimen> - <dimen name="suggestions_strip_padding">40.0mm</dimen> + <dimen name="suggestions_strip_padding">252.0dp</dimen> <fraction name="min_more_suggestions_width">50%</fraction> </resources> diff --git a/java/res/values-sw768dp-land/keyboard-heights.xml b/java/res/values-sw768dp-land/keyboard-heights.xml new file mode 100644 index 000000000..692c5a0fb --- /dev/null +++ b/java/res/values-sw768dp-land/keyboard-heights.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. +*/ +--> + +<!-- Preferable keyboard height in absolute scale: 58.0mm --> +<resources> + <!-- Build.HARDWARE,keyboard_height_in_dp --> + <string-array name="keyboard_heights" translatable="false"> + <!-- Xoom --> + <item>stingray,342.1198</item> + </string-array> +</resources> 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 0d302c6a5..01e228499 100644 --- a/java/res/values-sw768dp/dimens.xml +++ b/java/res/values-sw768dp/dimens.xml @@ -19,9 +19,10 @@ --> <resources> - <!-- keyboardHeight = key_height*4 + key_bottom_gap*3, key_height=12mm --> - <dimen name="keyboardHeight">48.0mm</dimen> - <fraction name="maxKeyboardHeight">50%p</fraction> + <!-- Preferable keyboard height in absolute scale: 48.0mm --> + <!-- This keyboardHeight value should match with keyboard-heights.xml --> + <dimen name="keyboardHeight">302.4dp</dimen> + <fraction name="maxKeyboardHeight">46%p</fraction> <fraction name="minKeyboardHeight">-35.0%p</fraction> <fraction name="keyboard_top_padding">2.291%p</fraction> @@ -30,7 +31,6 @@ <fraction name="key_bottom_gap">4.270%p</fraction> <fraction name="key_horizontal_gap">1.551%p</fraction> - <dimen name="keyboardHeight_stone">48.0mm</dimen> <fraction name="key_bottom_gap_stone">3.75%p</fraction> <fraction name="key_horizontal_gap_stone">1.059%p</fraction> @@ -41,17 +41,17 @@ <fraction name="key_bottom_gap_ics">3.312%p</fraction> <fraction name="key_horizontal_gap_ics">1.066%p</fraction> - <dimen name="popup_key_height">10.0mm</dimen> + <dimen name="popup_key_height">63.0dp</dimen> - <dimen name="mini_keyboard_key_horizontal_padding">12dip</dimen> + <dimen name="more_keys_keyboard_key_horizontal_padding">12dp</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">98.3dp</dimen> <!-- popup_key_height x -1.0 --> - <dimen name="mini_keyboard_vertical_correction">-13.0mm</dimen> + <dimen name="more_keys_keyboard_vertical_correction">-81.9dp</dimen> <!-- left or right padding of label alignment --> - <dimen name="key_label_horizontal_padding">6dip</dimen> + <dimen name="key_label_horizontal_padding">6dp</dimen> <dimen name="key_hint_letter_padding">3dp</dimen> <dimen name="key_uppercase_letter_padding">3dp</dimen> @@ -62,19 +62,21 @@ <fraction name="key_hint_label_ratio">28%</fraction> <fraction name="key_uppercase_letter_ratio">26%</fraction> <fraction name="key_preview_text_ratio">50%</fraction> - <dimen name="key_preview_height">15.0mm</dimen> - <dimen name="key_preview_offset">0.1in</dimen> + <fraction name="spacebar_text_ratio">29.03%</fraction> + <dimen name="key_preview_height">94.5dp</dimen> + <dimen name="key_preview_offset">16.0dp</dimen> - <dimen name="key_preview_height_ics">15.0mm</dimen> - <dimen name="key_preview_offset_ics">0.05in</dimen> + <dimen name="key_preview_offset_ics">8.0dp</dimen> + <!-- popup_key_height x -0.5 --> + <dimen name="more_keys_keyboard_vertical_correction_ics">-31.5dp</dimen> - <dimen name="suggestions_strip_height">44dip</dimen> - <dimen name="more_suggestions_row_height">44dip</dimen> + <dimen name="suggestions_strip_height">44dp</dimen> + <dimen name="more_suggestions_row_height">44dp</dimen> <integer name="max_more_suggestions_row">6</integer> <fraction name="min_more_suggestions_width">90%</fraction> - <dimen name="suggestions_strip_padding">15.0mm</dimen> - <dimen name="suggestion_min_width">46dip</dimen> - <dimen name="suggestion_padding">8dip</dimen> - <dimen name="suggestion_text_size">22dip</dimen> - <dimen name="more_suggestions_hint_text_size">33dip</dimen> + <dimen name="suggestions_strip_padding">94.5dp</dimen> + <dimen name="suggestion_min_width">46dp</dimen> + <dimen name="suggestion_padding">8dp</dimen> + <dimen name="suggestion_text_size">22dp</dimen> + <dimen name="more_suggestions_hint_text_size">33dp</dimen> </resources> diff --git a/java/res/values-sw768dp/keyboard-heights.xml b/java/res/values-sw768dp/keyboard-heights.xml new file mode 100644 index 000000000..77e52be2f --- /dev/null +++ b/java/res/values-sw768dp/keyboard-heights.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. +*/ +--> + +<!-- Preferable keyboard height in absolute scale: 48.0mm --> +<resources> + <!-- Build.HARDWARE,keyboard_height_in_dp --> + <string-array name="keyboard_heights" translatable="false"> + <!-- Xoom --> + <item>stingray,283.1337</item> + </string-array> +</resources> diff --git a/java/res/values-th/strings.xml b/java/res/values-th/strings.xml index 53f56606c..15157c245 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,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">"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,46 +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">"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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"หากต้องการปิดการป้อนข้อมูลด้วยเสียง ไปที่การตั้งค่าวิธีการป้อนข้อมูล"</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"หากต้องการใช้การป้อนข้อมูลด้วยเสียง ให้กดปุ่มไมโครโฟน"</string> - <string name="voice_listening" msgid="467518160751321844">"พูดได้เลย"</string> - <string name="voice_working" msgid="6666937792815731889">"กำลังทำงาน"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"ข้อผิดพลาด โปรดลองอีกครั้ง"</string> - <string name="voice_network_error" msgid="6649556447401862563">"ไม่สามารถเชื่อมต่อได้"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"ข้อผิดพลาด คำพูดยาวเกินไป"</string> - <string name="voice_audio_error" msgid="5072707727016414454">"ปัญหาด้านเสียง"</string> - <string name="voice_server_error" msgid="7807129913977261644">"ข้อผิดพลาดของเซิร์ฟเวอร์"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"ไม่ได้ยินเสียง"</string> - <string name="voice_no_match" msgid="4285117547030179174">"ไม่พบรายการที่ตรงกัน"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"ไม่ได้ติดตั้ง Voice Search"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"คำแนะนำ:"</b>" กวาดผ่านแป้นพิมพ์เพื่อพูด"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"คำแนะนำ:"</b>" ครั้งต่อไป ให้ลองเอ่ยถึงเครื่องหมายวรรคตอน เช่น \"มหัพภาค\" \"จุลภาค\" หรือ \"เครื่องหมายคำถาม\""</string> - <string name="cancel" msgid="6830980399865683324">"ยกเลิก"</string> - <string name="ok" msgid="7898366843681727667">"ตกลง"</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_input" msgid="3583258583521397548">"แป้นการป้อนข้อมูลด้วยเสียง"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"บนแป้นพิมพ์หลัก"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"บนแป้นพิมพ์สัญลักษณ์"</string> @@ -135,16 +108,15 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"ไมค์บนแป้นพิมพ์หลัก"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"ไมค์บนแป้นพิมพ์สัญลักษณ์"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"ปิดใช้งานป้อนข้อมูลด้วยเสียง"</string> - <string name="selectInputMethod" msgid="315076553378705821">"เลือกวิธีการป้อนข้อมูล"</string> <string name="configure_input_method" msgid="373356270290742459">"กำหนดค่าวิธีการป้อนข้อมูล"</string> <string name="language_selection_title" msgid="1651299598555326750">"ภาษาในการป้อนข้อมูล"</string> <string name="select_language" msgid="3693815588777926848">"ภาษาสำหรับการป้อนข้อมูล"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← แตะอีกครั้งเพื่อบันทึก"</string> + <!-- no translation found for hint_add_to_dictionary (573678656946085380) --> + <skip /> <string name="has_dictionary" msgid="6071847973466625007">"มีพจนานุกรมให้ใช้งาน"</string> <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..36f9002f4 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,10 @@ <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> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Lipat iba paraan ng input"</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Saklaw din ng key ng pagpalit ng wika ang ibang paraan ng input"</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"Pigilan key pagpalit wika"</string> <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 +55,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 +68,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 +81,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,46 +93,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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Upang i-off ang pag-input ng boses, pumunta sa mga setting ng pamamaraan ng pag-input."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Upang gamitin ang pag-input ng boses, pindutin ang pindutan na mikropono."</string> - <string name="voice_listening" msgid="467518160751321844">"Magsalita ngayon"</string> - <string name="voice_working" msgid="6666937792815731889">"Nagtatrabaho"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Error. Pakisubukang muli."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Hindi makakonekta"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Error, masyadong maraming pananalita."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Problema sa audio"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Error sa server"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Walang narinig na pananalita"</string> - <string name="voice_no_match" msgid="4285117547030179174">"Walang nakitang mga tugma"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Hindi naka-install ang paghahanap ng boses"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Pahiwatig:"</b>" Mag-swipe sa keyboard upang magsalita"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Pahiwatig:"</b>" Sa susunod, subukang magsalita ng bantas tulad ng \"tuldok\", \"kuwit\", o \"tandang pananong\"."</string> - <string name="cancel" msgid="6830980399865683324">"Kanselahin"</string> - <string name="ok" msgid="7898366843681727667">"OK"</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_input" msgid="3583258583521397548">"Voice input key"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Sa pangunahing keyboard"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Sa keyboard ng mga simbolo"</string> @@ -135,16 +108,15 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Mic sa pangunahing keyboard"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Mic sa keyboard ng mga simbolo"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Hindi pinagana ang voice input"</string> - <string name="selectInputMethod" msgid="315076553378705821">"Pumili ng paraan ng pag-input"</string> <string name="configure_input_method" msgid="373356270290742459">"I-configure ang mga pamamaraan ng pag-input"</string> <string name="language_selection_title" msgid="1651299598555326750">"Mag-input ng mga wika"</string> <string name="select_language" msgid="3693815588777926848">"Mga wika ng input"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Pinduting muli upang i-save"</string> + <!-- no translation found for hint_add_to_dictionary (573678656946085380) --> + <skip /> <string name="has_dictionary" msgid="6071847973466625007">"Available ang diksyunaryo"</string> <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..1978a6f1e 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,10 @@ <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> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Diğ. giriş yöntem. geç"</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Dil geçiş tuşu diğer giriş yöntemlerini de kapsar"</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"Dil geçiş tuşunu gösterme"</string> <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 +55,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 +68,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 +81,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,46 +93,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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Ses girişini kapatmak için giriş yöntemi ayarlarına gidin."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Ses girişini kullanmak için mikrofon düğmesine basın."</string> - <string name="voice_listening" msgid="467518160751321844">"Şimdi konuşun"</string> - <string name="voice_working" msgid="6666937792815731889">"Çalışıyor"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Hata. Lütfen tekrar deneyin."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Bağlanamadı"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Hata, çok uzun konuşma."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Ses sorunu"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Sunucu hatası"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Konuşma duyulmadı"</string> - <string name="voice_no_match" msgid="4285117547030179174">"Eşleşme bulunamadı"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Sesle arama yüklenmedi"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"İpucu:"</b>" Konuşmak için parmağınızı klavye üzerinde kaydırın"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"İpucu:"</b>" Sonraki sefer, \"nokta\", \"virgül\" veya \"soru işareti\" gibi noktalama işaretlerini telaffuz etmeyi deneyin."</string> - <string name="cancel" msgid="6830980399865683324">"İptal"</string> - <string name="ok" msgid="7898366843681727667">"Tamam"</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_input" msgid="3583258583521397548">"Ses girişi tuşu"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Ana klavyede"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Simge klavyesinde"</string> @@ -135,16 +108,15 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Ana klavyede mikrfn"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Simge klavysnd mikrf"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Sesle grş devre dışı"</string> - <string name="selectInputMethod" msgid="315076553378705821">"Giriş yöntemini seç"</string> <string name="configure_input_method" msgid="373356270290742459">"Giriş yöntemlerini yapılandır"</string> <string name="language_selection_title" msgid="1651299598555326750">"Giriş dilleri"</string> <string name="select_language" msgid="3693815588777926848">"Giriş dilleri"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Kaydetmek için tekrar dokunun"</string> + <!-- no translation found for hint_add_to_dictionary (573678656946085380) --> + <skip /> <string name="has_dictionary" msgid="6071847973466625007">"Sözlük kullanılabilir"</string> <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-uk/donottranslate-more-keys.xml b/java/res/values-uk/donottranslate-more-keys.xml new file mode 100644 index 000000000..32397049a --- /dev/null +++ b/java/res/values-uk/donottranslate-more-keys.xml @@ -0,0 +1,33 @@ +<?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+0449: "щ" CYRILLIC SMALL LETTER SHCHA --> + <string name="keylabel_for_east_slavic_row1_9">щ</string> + <!-- U+0456: "і" CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I --> + <string name="keylabel_for_east_slavic_row2_1">і</string> + <!-- U+0438: "и" CYRILLIC SMALL LETTER I --> + <string name="keylabel_for_east_slavic_row3_5">и</string> + <!-- U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN --> + <string name="more_keys_for_cyrillic_ha">ъ</string> + <!-- U+0457: "ї" CYRILLIC SMALL LETTER YI --> + <string name="more_keys_for_east_slavic_row2_1">ї</string> + <!-- U+044A: "ъ" CYRILLIC SMALL LETTER HARD SIGN --> + <string name="more_keys_for_cyrillic_soft_sign">ъ</string> +</resources> diff --git a/java/res/values-uk/strings.xml b/java/res/values-uk/strings.xml index 234a9c56a..6541c945d 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,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">"Клавіша Delete"</string> <string name="spoken_description_to_symbol" msgid="5486340107500448969">"Символи"</string> <string name="spoken_description_to_alpha" msgid="23129338819771807">"Літери"</string> @@ -88,46 +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">"Клавіша 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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Щоб вимкнути голосовий ввід, перейдіть до налаштувань методів введення."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Щоб використовувати голосовий ввід, натисніть кнопку мікрофона."</string> - <string name="voice_listening" msgid="467518160751321844">"Диктуйте"</string> - <string name="voice_working" msgid="6666937792815731889">"Працює"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Помилка. Спробуйте ще раз."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Неможл. під\'єднатися"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Помилка. Забагато продикт."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Проблема з аудіо"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Помилка сервера"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Не чути диктув."</string> - <string name="voice_no_match" msgid="4285117547030179174">"Збігів не знайдено"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Голос. пошук не встановлено"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Підк:"</b>" горт. на клавіат., щоб продикт."</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Підказка:"</b>" наступного разу продикт. знаки пункт. такі як \"крапка\", \"кома\" чи \"знак пит\"."</string> - <string name="cancel" msgid="6830980399865683324">"Скасувати"</string> - <string name="ok" msgid="7898366843681727667">"OK"</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_input" msgid="3583258583521397548">"Ключ голосового вводу"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"На основ. клавіатурі"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Символьна клавіатура"</string> @@ -135,16 +108,14 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Miкр. на осн. клав."</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Miкр. на симв. клавіат."</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Голос. ввід вимкнено"</string> - <string name="selectInputMethod" msgid="315076553378705821">"Вибрати метод введення"</string> <string name="configure_input_method" msgid="373356270290742459">"Налаштування методів введення"</string> <string name="language_selection_title" msgid="1651299598555326750">"Мови вводу"</string> <string name="select_language" msgid="3693815588777926848">"Мови введення"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Торкн. ще, щоб збер."</string> + <string name="hint_add_to_dictionary" msgid="573678656946085380">"Торкніться знову, щоб зберегти"</string> <string name="has_dictionary" msgid="6071847973466625007">"Словник доступний"</string> <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..f37372991 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,10 @@ <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> + <string name="include_other_imes_in_language_switch_list" msgid="4533689960308565519">"Phương thức nhập khác"</string> + <string name="include_other_imes_in_language_switch_list_summary" msgid="840637129103317635">"Khóa chuyển ngôn ngữ bao gồm cả các phương thức nhập liệu khác"</string> + <string name="suppress_language_switch_key" msgid="8003788410354806368">"Bỏ khóa chuyển ngôn ngữ"</string> <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 +55,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 +68,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 +81,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,46 +93,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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Để tắt nhập liệu bằng giọng nói, đi tới cài đặt phương pháp nhập liệu."</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Để sử dụng nhập liệu bằng giọng nói, hãy nhấn nút micrô."</string> - <string name="voice_listening" msgid="467518160751321844">"Nói ngay"</string> - <string name="voice_working" msgid="6666937792815731889">"Đang hoạt động"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Lỗi. Vui lòng thử lại."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Không thể kết nối"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Lỗi, quá nhiều câu thoại."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Sự cố âm thanh"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Lỗi máy chủ"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Không nghe thấy tiếng nói nào"</string> - <string name="voice_no_match" msgid="4285117547030179174">"Không tìm thấy kết quả phù hợp"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Tìm kiếm bằng giọng nói chưa được cài đặt"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Gợi ý:"</b>" Trượt qua bàn phím để nói"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Gợi ý:"</b>" Lần tới, thử nói dấu câu như \"dấu chấm\", \"dấu phẩy\" hoặc \"dấu hỏi\"."</string> - <string name="cancel" msgid="6830980399865683324">"Hủy"</string> - <string name="ok" msgid="7898366843681727667">"OK"</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_input" msgid="3583258583521397548">"Khóa nhập giọng nói"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Trên bàn phím chính"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Trên bàn phím biểu tượng"</string> @@ -135,16 +108,15 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"Micrô trên bàn phím chính"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Micrô trên bàn phím biểu tượng"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Nhập liệu bằng giọng nói đã bị tắt"</string> - <string name="selectInputMethod" msgid="315076553378705821">"Chọn phương thức nhập"</string> <string name="configure_input_method" msgid="373356270290742459">"Định cấu hình phương thức nhập"</string> <string name="language_selection_title" msgid="1651299598555326750">"Ngôn ngữ nhập"</string> <string name="select_language" msgid="3693815588777926848">"Ngôn ngữ nhập"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Chạm lại để lưu"</string> + <!-- no translation found for hint_add_to_dictionary (573678656946085380) --> + <skip /> <string name="has_dictionary" msgid="6071847973466625007">"Có sẵn từ điển"</string> <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..876056b96 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,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">"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,46 +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">"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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"要关闭语音输入功能,请转至输入法设置。"</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"要使用语音输入功能,请按“麦克风”按钮。"</string> - <string name="voice_listening" msgid="467518160751321844">"请开始说话"</string> - <string name="voice_working" msgid="6666937792815731889">"正在处理"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"出错,请重试。"</string> - <string name="voice_network_error" msgid="6649556447401862563">"无法连接"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"出错,语音过长。"</string> - <string name="voice_audio_error" msgid="5072707727016414454">"音频问题"</string> - <string name="voice_server_error" msgid="7807129913977261644">"服务器出错"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"未听到语音"</string> - <string name="voice_no_match" msgid="4285117547030179174">"未找到匹配项"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"未安装语音搜索"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"提示:"</b>"在键盘上滑动手指可激活语音功能"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"提示:"</b>"稍后,请尝试使用语音输入标点符号,如“句号”、“逗号”或“问号”。"</string> - <string name="cancel" msgid="6830980399865683324">"取消"</string> - <string name="ok" msgid="7898366843681727667">"确定"</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_input" msgid="3583258583521397548">"语音输入键"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"主键盘上"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"符号键盘上"</string> @@ -135,16 +108,15 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"主键盘上的麦克风"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"符号键盘上的麦克风"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"语音输入功能已停用"</string> - <string name="selectInputMethod" msgid="315076553378705821">"选择输入法"</string> <string name="configure_input_method" msgid="373356270290742459">"配置输入法"</string> <string name="language_selection_title" msgid="1651299598555326750">"输入语言"</string> <string name="select_language" msgid="3693815588777926848">"输入语言"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← 再次触摸即可保存"</string> + <!-- no translation found for hint_add_to_dictionary (573678656946085380) --> + <skip /> <string name="has_dictionary" msgid="6071847973466625007">"提供字典"</string> <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 0542efca3..88e53b4d4 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,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">"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,46 +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">"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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"如要關閉語音輸入,請前往輸入法設定。"</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"如要使用語音輸入,請按下麥克風按鈕。"</string> - <string name="voice_listening" msgid="467518160751321844">"請說話"</string> - <string name="voice_working" msgid="6666937792815731889">"辨識中"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"發生錯誤,請再試一次。"</string> - <string name="voice_network_error" msgid="6649556447401862563">"無法連線"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"錯誤:語音內容過長。"</string> - <string name="voice_audio_error" msgid="5072707727016414454">"音訊問題"</string> - <string name="voice_server_error" msgid="7807129913977261644">"伺服器錯誤"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"沒有聽到任何聲音"</string> - <string name="voice_no_match" msgid="4285117547030179174">"找不到相符的項目"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"未安裝語音搜尋"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"提示:"</b>"滑過鍵盤即可說話"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"提示:"</b>"下次可嘗試說出標點符號,例如「句號」、「逗號」或「問號」。"</string> - <string name="cancel" msgid="6830980399865683324">"取消"</string> - <string name="ok" msgid="7898366843681727667">"確定"</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_input" msgid="3583258583521397548">"語音輸入按鍵"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"主鍵盤上"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"符號鍵盤上"</string> @@ -135,16 +108,15 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"主鍵盤上的麥克風"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"符號鍵盤上的麥克風"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"語音輸入已停用"</string> - <string name="selectInputMethod" msgid="315076553378705821">"選擇輸入法"</string> <string name="configure_input_method" msgid="373356270290742459">"設定輸入法"</string> <string name="language_selection_title" msgid="1651299598555326750">"輸入語言"</string> <string name="select_language" msgid="3693815588777926848">"輸入語言"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← 再次輕觸即可儲存"</string> + <!-- no translation found for hint_add_to_dictionary (573678656946085380) --> + <skip /> <string name="has_dictionary" msgid="6071847973466625007">"可使用字典"</string> <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..79b1f2514 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 ulimi 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,46 +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="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> - <string name="voice_warning_how_to_turn_off" msgid="3190378129944934856">"Ukuvala okufakwayo ngezwi, iya kuzilungiselelo zendlela yokufakwayo"</string> - <string name="voice_hint_dialog_message" msgid="1420686286820661548">"Ukusebenzisa okufakwayo ngezwi, cindezela inkinobho yemakrofoni."</string> - <string name="voice_listening" msgid="467518160751321844">"Khuluma manje"</string> - <string name="voice_working" msgid="6666937792815731889">"Kuyasebenza"</string> - <string name="voice_initializing" msgid="661962047129906646"></string> - <string name="voice_error" msgid="5140896300312186162">"Iphutha. Sicela uzame futhi."</string> - <string name="voice_network_error" msgid="6649556447401862563">"Ayikwazanga ukuxhuma"</string> - <string name="voice_too_much_speech" msgid="5746973620134227376">"Iphutha, kunamagama amaningi."</string> - <string name="voice_audio_error" msgid="5072707727016414454">"Inkinga yomsindo"</string> - <string name="voice_server_error" msgid="7807129913977261644">"Iphutha leseva"</string> - <string name="voice_speech_timeout" msgid="8461817525075498795">"Awekho amagama azwakele"</string> - <string name="voice_no_match" msgid="4285117547030179174">"Akukho okufanayo okutholiwe"</string> - <string name="voice_not_installed" msgid="5552450909753842415">"Ukusesha ngezwi akufakiwe"</string> - <string name="voice_swipe_hint" msgid="6943546180310682021"><b>"Isexwayiso:"</b>"Shintshela kwikhibhodi ukuze ukhulume"</string> - <string name="voice_punctuation_hint" msgid="1611389463237317754"><b>"Isixwayiso: "</b>"Esikhathini esilandelayo, zama ukukhuluma izimpimiselo ezinjengo \"isikhathi, \"ikhefu\" noma \"uphawu lombuzo\"."</string> - <string name="cancel" msgid="6830980399865683324">"Khansela"</string> - <string name="ok" msgid="7898366843681727667">"KULUNGILE"</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_input" msgid="3583258583521397548">"Inkinobho yokufaka izwi"</string> <string name="voice_input_modes_main_keyboard" msgid="3360660341121083174">"Kwikhibhodi eyisisekelo"</string> <string name="voice_input_modes_symbols_keyboard" msgid="7203213240786084067">"Ikhibhodi yezimpawu"</string> @@ -135,16 +108,14 @@ <string name="voice_input_modes_summary_main_keyboard" msgid="6586544292900314339">"I-mic kwikhibhodi eyisisekelo"</string> <string name="voice_input_modes_summary_symbols_keyboard" msgid="5233725927281932391">"Ikhibhodi yezimpawu ze-mic"</string> <string name="voice_input_modes_summary_off" msgid="63875609591897607">"Okufakwayo ngezwi kuvinjelwe"</string> - <string name="selectInputMethod" msgid="315076553378705821">"Khetha indlela yokufaka"</string> <string name="configure_input_method" msgid="373356270290742459">"Misa izindlela zokufakwayo"</string> <string name="language_selection_title" msgid="1651299598555326750">"Izilimi zokufakwayo"</string> <string name="select_language" msgid="3693815588777926848">"Izilimi zokufakwayo"</string> - <string name="hint_add_to_dictionary" msgid="9006292060636342317">"← Thinta futhi ukulondoloza"</string> + <string name="hint_add_to_dictionary" msgid="573678656946085380">"Thinta futhi ukuze ulondoloze"</string> <string name="has_dictionary" msgid="6071847973466625007">"Isichazamazwi siyatholakala"</string> <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-zz/donottranslate-more-keys.xml b/java/res/values-zz/donottranslate-more-keys.xml new file mode 100644 index 000000000..eb984a469 --- /dev/null +++ b/java/res/values-zz/donottranslate-more-keys.xml @@ -0,0 +1,139 @@ +<?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+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+0101: "ā" LATIN SMALL LETTER A WITH MACRON + U+0103: "ă" LATIN SMALL LETTER A WITH BREVE + U+0105: "ą" LATIN SMALL LETTER A WITH OGONEK + 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+0113: "ē" LATIN SMALL LETTER E WITH MACRON + U+0115: "ĕ" LATIN SMALL LETTER E WITH BREVE + U+0117: "ė" LATIN SMALL LETTER E WITH DOT ABOVE + U+0119: "ę" LATIN SMALL LETTER E WITH OGONEK + U+011B: "ě" LATIN SMALL LETTER E WITH CARON --> + <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+0129: "ĩ" LATIN SMALL LETTER I WITH TILDE + U+012B: "ī" LATIN SMALL LETTER I WITH MACRON + U+012D: "ĭ" LATIN SMALL LETTER I WITH BREVE + U+012F: "į" LATIN SMALL LETTER I WITH OGONEK + U+0131: "ı" LATIN SMALL LETTER DOTLESS I + U+0133: "ij" LATIN SMALL LIGATURE IJ --> + <string name="more_keys_for_i">ì,í,î,ï,ĩ,ī,ĭ,į,ı,ij</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+00F8: "ø" LATIN SMALL LETTER O WITH STROKE + U+014D: "ō" LATIN SMALL LETTER O WITH MACRON + U+014F: "ŏ" LATIN SMALL LETTER O WITH BREVE + U+0151: "ő" LATIN SMALL LETTER O WITH DOUBLE ACUTE + U+0153: "œ" LATIN SMALL LIGATURE OE + 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+0169: "ũ" LATIN SMALL LETTER U WITH TILDE + U+016B: "ū" LATIN SMALL LETTER U WITH MACRON + U+016D: "ŭ" LATIN SMALL LETTER U WITH BREVE + U+016F: "ů" LATIN SMALL LETTER U WITH RING ABOVE + U+0171: "ű" LATIN SMALL LETTER U WITH DOUBLE ACUTE + U+0173: "ų" LATIN SMALL LETTER U WITH OGONEK --> + <string name="more_keys_for_u">ù,ú,û,ü,ũ,ū,ŭ,ů,ű,ų</string> + <!-- U+00DF: "ß" LATIN SMALL LETTER SHARP S + U+015B: "ś" LATIN SMALL LETTER S WITH ACUTE + U+015D: "ŝ" LATIN SMALL LETTER S WITH CIRCUMFLEX + U+015F: "ş" LATIN SMALL LETTER S WITH CEDILLA + U+0161: "š" LATIN SMALL LETTER S WITH CARON + U+017F: "ſ" LATIN SMALL LETTER LONG S --> + <string name="more_keys_for_s">ß,ś,ŝ,ş,š,ſ</string> + <!-- U+00F1: "ñ" LATIN SMALL LETTER N WITH TILDE + U+0144: "ń" LATIN SMALL LETTER N WITH ACUTE + U+0146: "ņ" LATIN SMALL LETTER N WITH CEDILLA + U+0148: "ň" LATIN SMALL LETTER N WITH CARON + U+0149: "ʼn" LATIN SMALL LETTER N PRECEDED BY APOSTROPHE + U+014B: "ŋ" LATIN SMALL LETTER ENG --> + <string name="more_keys_for_n">ñ,ń,ņ,ň,ʼn,ŋ</string> + <!-- U+00E7: "ç" LATIN SMALL LETTER C WITH CEDILLA + U+0107: "ć" LATIN SMALL LETTER C WITH ACUTE + U+0109: "ĉ" LATIN SMALL LETTER C WITH CIRCUMFLEX + U+010B: "ċ" LATIN SMALL LETTER C WITH DOT ABOVE + U+010D: "č" LATIN SMALL LETTER C WITH CARON --> + <string name="more_keys_for_c">ç,ć,ĉ,ċ,č</string> + <!-- U+00FD: "ý" LATIN SMALL LETTER Y WITH ACUTE + U+0177: "ŷ" LATIN SMALL LETTER Y WITH CIRCUMFLEX + U+00FF: "ÿ" LATIN SMALL LETTER Y WITH DIAERESIS + U+0133: "ij" LATIN SMALL LIGATURE IJ --> + <string name="more_keys_for_y">ý,ŷ,ÿ,ij</string> + <!-- U+010F: "ď" LATIN SMALL LETTER D WITH CARON + U+0111: "đ" LATIN SMALL LETTER D WITH STROKE + U+00F0: "ð" LATIN SMALL LETTER ETH --> + <string name="more_keys_for_d">ď,đ,ð</string> + <!-- U+0155: "ŕ" LATIN SMALL LETTER R WITH ACUTE + U+0157: "ŗ" LATIN SMALL LETTER R WITH CEDILLA + U+0159: "ř" LATIN SMALL LETTER R WITH CARON --> + <string name="more_keys_for_r">ŕ,ŗ,ř</string> + <!-- U+00FE: "þ" LATIN SMALL LETTER THORN + U+0163: "ţ" LATIN SMALL LETTER T WITH CEDILLA + U+0165: "ť" LATIN SMALL LETTER T WITH CARON + U+0167: "ŧ" LATIN SMALL LETTER T WITH STROKE --> + <string name="more_keys_for_t">þ,ţ,ť,ŧ</string> + <!-- U+017A: "ź" LATIN SMALL LETTER Z WITH ACUTE + U+017C: "ż" LATIN SMALL LETTER Z WITH DOT ABOVE + U+017E: "ž" LATIN SMALL LETTER Z WITH CARON --> + <string name="more_keys_for_z">ź,ż,ž</string> + <!-- U+0137: "ķ" LATIN SMALL LETTER K WITH CEDILLA + U+0138: "ĸ" LATIN SMALL LETTER KRA --> + <string name="more_keys_for_k">ķ,ĸ</string> + <!-- U+013A: "ĺ" LATIN SMALL LETTER L WITH ACUTE + U+013C: "ļ" LATIN SMALL LETTER L WITH CEDILLA + U+013E: "ľ" LATIN SMALL LETTER L WITH CARON + U+0140: "ŀ" LATIN SMALL LETTER L WITH MIDDLE DOT + U+0142: "ł" LATIN SMALL LETTER L WITH STROKE --> + <string name="more_keys_for_l">ĺ,ļ,ľ,ŀ,ł</string> + <!-- U+011D: "ĝ" LATIN SMALL LETTER G WITH CIRCUMFLEX + U+011F: "ğ" LATIN SMALL LETTER G WITH BREVE + U+0121: "ġ" LATIN SMALL LETTER G WITH DOT ABOVE + U+0123: "ģ" LATIN SMALL LETTER G WITH CEDILLA --> + <string name="more_keys_for_g">ĝ,ğ,ġ,ģ</string> + <!-- U+0125: "ĥ" LATIN SMALL LETTER H WITH CIRCUMFLEX --> + <string name="more_keys_for_h">ĥ</string> + <!-- U+0135: "ĵ" LATIN SMALL LETTER J WITH CIRCUMFLEX --> + <string name="more_keys_for_j">ĵ</string> + <!-- U+0175: "ŵ" LATIN SMALL LETTER W WITH CIRCUMFLEX --> + <string name="more_keys_for_w">ŵ</string> +</resources> diff --git a/java/res/values/attrs.xml b/java/res/values/attrs.xml index 0c9ca4f4a..b3f30c638 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,43 @@ </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="languageOnSpacebarFinalAlpha" format="integer" /> + <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 +169,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" /> @@ -158,16 +202,13 @@ <!-- Default height of a row (key height + vertical gap), in pixels or percentage of keyboard height. --> <attr name="rowHeight" format="dimension|fraction" /> - <!-- Default horizontal gap between keys. --> + <!-- Default horizontal gap between keys, in pixels or percentage of keyboard width. --> <attr name="horizontalGap" format="dimension|fraction" /> - <!-- Default vertical gap between rows of keys. --> + <!-- Default vertical gap between rows of keys, in pixels or percentage of keyboard + height. --> <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 +219,28 @@ <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" /> + <attr name="iconZwnjKey" format="reference" /> + <attr name="iconZwjKey" 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 +248,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 +277,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 +308,24 @@ <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" /> + <enum name="iconZwnjKey" value="15" /> + <enum name="iconZwjKey" value="16" /> </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 +350,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 +372,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 +390,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 +403,27 @@ <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" /> + <declare-styleable name="KeyboardSet"> + <!-- Disable shortcut key. Shortcut key is enabled by default. --> + <attr name="disableShortcutKey" format="boolean" /> + </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"/> + <!-- Enable proximity characters correction. Disabled by default. --> + <attr name="enableProximityCharsCorrection" format="boolean" /> </declare-styleable> </resources> diff --git a/java/res/values/config.xml b/java/res/values/config.xml index 3f676ab25..f0b12e92b 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,44 @@ <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_language_on_spacebar_final_alpha">128</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">8.0dp</dimen> + <integer name="config_touch_noise_threshold_time">40</integer> + <dimen name="config_touch_noise_threshold_distance">12.6dp</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 +85,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" @@ -93,5 +99,4 @@ 4 = ? --> <integer name="log_screen_metrics">0</integer> - <bool name="config_require_umlaut_processing">false</bool> </resources> diff --git a/java/res/values/dimens.xml b/java/res/values/dimens.xml index d1067f39e..7eb57c3cf 100644 --- a/java/res/values/dimens.xml +++ b/java/res/values/dimens.xml @@ -19,15 +19,16 @@ --> <resources> - <!-- keyboardHeight = row_height*4 + key_bottom_gap*3 --> - <dimen name="keyboardHeight">1.285in</dimen> - <fraction name="maxKeyboardHeight">50%p</fraction> + <!-- Preferable keyboard height in absolute scale: 1.285in --> + <!-- This keyboardHeight value should match with keyboard-heights.xml --> + <dimen name="keyboardHeight">205.6dp</dimen> + <fraction name="maxKeyboardHeight">46%p</fraction> <fraction name="minKeyboardHeight">-61.8%p</fraction> - <dimen name="popup_key_height">0.330in</dimen> + <dimen name="popup_key_height">52.8dp</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">16dp</dimen> + <dimen name="more_keys_keyboard_key_horizontal_padding">8dp</dimen> <fraction name="keyboard_top_padding">1.556%p</fraction> <fraction name="keyboard_bottom_padding">4.669%p</fraction> @@ -35,7 +36,6 @@ <fraction name="key_bottom_gap">6.250%p</fraction> <fraction name="key_horizontal_gap">1.352%p</fraction> - <dimen name="keyboardHeight_stone">1.317in</dimen> <fraction name="keyboard_top_padding_stone">1.556%p</fraction> <fraction name="keyboard_bottom_padding_stone">0.778%p</fraction> <fraction name="key_bottom_gap_stone">7.506%p</fraction> @@ -48,16 +48,14 @@ <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">4dp</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">63.36dp</dimen> <!-- popup_key_height x -1.0 --> - <dimen name="mini_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> + <dimen name="more_keys_keyboard_vertical_correction">-52.8dp</dimen> + <dimen name="keyboard_vertical_correction">0.0dp</dimen> <fraction name="key_letter_ratio">55%</fraction> <fraction name="key_large_letter_ratio">65%</fraction> @@ -66,33 +64,33 @@ <fraction name="key_hint_label_ratio">44%</fraction> <fraction name="key_uppercase_letter_ratio">35%</fraction> <fraction name="key_preview_text_ratio">82%</fraction> - <dimen name="key_preview_height">80sp</dimen> - <dimen name="key_preview_offset">0.1in</dimen> + <fraction name="spacebar_text_ratio">33.735%</fraction> + <dimen name="key_preview_height">80dp</dimen> + <dimen name="key_preview_offset">16.0dp</dimen> - <dimen name="key_label_horizontal_padding">4dip</dimen> + <dimen name="key_label_horizontal_padding">4dp</dimen> <dimen name="key_hint_letter_padding">1dp</dimen> <dimen name="key_popup_hint_letter_padding">2dp</dimen> <dimen name="key_uppercase_letter_padding">2dp</dimen> - <dimen name="key_preview_height_ics">80sp</dimen> - <dimen name="key_preview_offset_ics">0.05in</dimen> + <dimen name="key_preview_offset_ics">8.0dp</dimen> + <!-- popup_key_height x -0.5 --> + <dimen name="more_keys_keyboard_vertical_correction_ics">-26.4dp</dimen> - <dimen name="suggestions_strip_height">40dip</dimen> - <dimen name="more_suggestions_key_horizontal_padding">12dip</dimen> - <dimen name="more_suggestions_row_height">40dip</dimen> - <dimen name="more_suggestions_bottom_gap">6dip</dimen> - <dimen name="more_suggestions_modal_tolerance">0.2in</dimen> - <dimen name="more_suggestions_slide_allowance">0.1in</dimen> + <dimen name="suggestions_strip_height">40dp</dimen> + <dimen name="more_suggestions_key_horizontal_padding">12dp</dimen> + <dimen name="more_suggestions_row_height">40dp</dimen> + <dimen name="more_suggestions_bottom_gap">6dp</dimen> + <dimen name="more_suggestions_modal_tolerance">32.0dp</dimen> + <dimen name="more_suggestions_slide_allowance">16.0dp</dimen> <integer name="max_more_suggestions_row">6</integer> <fraction name="min_more_suggestions_width">90%</fraction> <fraction name="more_suggestions_info_ratio">18%</fraction> - <dimen name="suggestions_strip_padding">0dip</dimen> - <dimen name="suggestion_min_width">44dip</dimen> - <dimen name="suggestion_padding">6dip</dimen> - <dimen name="suggestion_text_size">18dip</dimen> - <dimen name="more_suggestions_hint_text_size">27dip</dimen> + <dimen name="suggestions_strip_padding">0dp</dimen> + <dimen name="suggestion_min_width">44dp</dimen> + <dimen name="suggestion_padding">6dp</dimen> + <dimen name="suggestion_text_size">18dp</dimen> + <dimen name="more_suggestions_hint_text_size">27dp</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/drawable/background_voice.xml b/java/res/values/donottranslate-config.xml index 3b6137df3..ba1cecb6c 100644 --- a/java/res/drawable/background_voice.xml +++ b/java/res/values/donottranslate-config.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. @@ -17,9 +17,8 @@ ** limitations under the License. */ --> -<shape xmlns:android="http://schemas.android.com/apk/res/android"> - <gradient - android:startColor="#ff000000" - android:endColor="#ff000e29" - android:angle="90" /> -</shape>
\ No newline at end of file + +<resources> + <bool name="config_require_umlaut_processing">false</bool> + <bool name="config_require_ligatures_processing">false</bool> +</resources> diff --git a/java/res/values/donottranslate-more-keys.xml b/java/res/values/donottranslate-more-keys.xml index 6c7753999..9b2780571 100644 --- a/java/res/values/donottranslate-more-keys.xml +++ b/java/res/values/donottranslate-more-keys.xml @@ -19,43 +19,61 @@ --> <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_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_h"></string> + <string name="more_keys_for_j"></string> + <string name="more_keys_for_w"></string> + <string name="keylabel_for_nordic_row1_11"></string> + <string name="keylabel_for_nordic_row2_10"></string> + <string name="keylabel_for_nordic_row2_11"></string> + <string name="more_keys_for_nordic_row2_10"></string> + <string name="more_keys_for_nordic_row2_11"></string> + <string name="keylabel_for_east_slavic_row1_9"></string> + <string name="keylabel_for_east_slavic_row2_1"></string> + <string name="keylabel_for_east_slavic_row3_5"></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> <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> + <string name="more_keys_for_east_slavic_row2_1"></string> + <string name="more_keys_for_cyrillic_o"></string> + <string name="more_keys_for_cyrillic_soft_sign"></string> + <string name="keylabel_for_south_slavic_row1_6"></string> + <string name="keylabel_for_south_slavic_row2_11"></string> + <string name="keylabel_for_south_slavic_row3_1"></string> + <string name="keylabel_for_south_slavic_row3_8"></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 +84,120 @@ <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_tablet_comma">,</string> + <string name="keyhintlabel_for_tablet_comma">!</string> + <string name="more_keys_for_tablet_comma">!</string> + <string name="keyhintlabel_for_tablet_period">\?</string> + <string name="more_keys_for_tablet_period">\?</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..68a8cabce 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> @@ -151,19 +156,26 @@ <string-array name="subtype_locale_exception_keys"> <item>en_US</item> <item>en_GB</item> - <item>de_ZZ</item> + <item>de_QY</item> + <item>zz_QY</item> </string-array> <string-array name="subtype_locale_exception_values"> <item>English (US)</item> <item>English (UK)</item> - <item>Deutsch (QWERTY)</item> + <item>@string/subtype_generic_qwerty</item> + <item>@string/subtype_qwerty</item> </string-array> <!-- Generic subtype label --> <string name="subtype_generic">%s</string> + <!-- Description for generic QWERTY keyboard subtype --> + <string name="subtype_generic_qwerty">%s (QWERTY)</string> + <!-- Description for language agnostic QWERTY keyboard subtype --> + <string name="subtype_qwerty">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-heights.xml b/java/res/values/keyboard-heights.xml new file mode 100644 index 000000000..7d5b58372 --- /dev/null +++ b/java/res/values/keyboard-heights.xml @@ -0,0 +1,34 @@ +<?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. +*/ +--> + +<!-- Preferable keyboard height in absolute scale: 1.285in --> +<resources> + <!-- Build.HARDWARE,keyboard_height_in_dp --> + <string-array name="keyboard_heights" translatable="false"> + <!-- Droid --> + <item>sholes,227.0167</item> + <!-- Nexus One --> + <item>mahimahi,217.5932</item> + <!-- Nexus S --> + <item>herring,200.8554</item> + <!-- Galaxy Nexus --> + <item>tuna,202.5869</item> + </string-array> +</resources> diff --git a/java/res/values/keyboard-icons-black.xml b/java/res/values/keyboard-icons-black.xml index f767cb349..1ff597a49 100644 --- a/java/res/values/keyboard-icons-black.xml +++ b/java/res/values/keyboard-icons-black.xml @@ -30,10 +30,14 @@ <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> + <!-- TODO: Needs dedicated black theme ZWNJ and ZWJ icons --> + <item name="iconZwnjKey">@drawable/sym_keyboard_zwnj_holo</item> + <item name="iconZwjKey">@drawable/sym_keyboard_zwj_holo</item> </style> </resources> diff --git a/java/res/values/keyboard-icons-ics.xml b/java/res/values/keyboard-icons-ics.xml index f1021433d..0774d57ac 100644 --- a/java/res/values/keyboard-icons-ics.xml +++ b/java/res/values/keyboard-icons-ics.xml @@ -23,16 +23,18 @@ <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> + <item name="iconZwnjKey">@drawable/sym_keyboard_zwnj_holo</item> + <item name="iconZwjKey">@drawable/sym_keyboard_zwj_holo</item> </style> </resources> diff --git a/java/res/values/keyboard-icons-white.xml b/java/res/values/keyboard-icons-white.xml index 07ece66b1..5798786f8 100644 --- a/java/res/values/keyboard-icons-white.xml +++ b/java/res/values/keyboard-icons-white.xml @@ -26,10 +26,14 @@ <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> + <!-- TODO: Needs dedicated black theme ZWNJ and ZWJ icons --> + <item name="iconZwnjKey">@drawable/sym_keyboard_zwnj_holo</item> + <item name="iconZwjKey">@drawable/sym_keyboard_zwj_holo</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..4f038e1a5 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,116 +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> - - <!-- Voice related labels --> - - <!-- Title of the warning dialog that shows when a user initiates voice input for - the first time. --> - <string name="voice_warning_title">Voice input</string> - - <!-- Message that gets put at the top of the warning dialog if the user is attempting to use - voice input in a currently unsupported locale. Voice input will work for such a user, - but it will only recognize them in English. --> - <string name="voice_warning_locale_not_supported">Voice input is not currently supported for your language, but does work in English.</string> - - <!-- Message of the warning dialog that shows when a user initiates voice input for - the first time, or turns it on in settings. [CHAR LIMIT=200] --> - <string name="voice_warning_may_not_understand">Voice input uses Google\'s speech recognition. <a href="http://m.google.com/privacy">The Mobile Privacy Policy</a> applies.</string> - - <!-- An additional part of the warning dialog for voice input that only shows when the user - actually initiates voice input, rather than just turning it on in settings. [CHAR LIMIT=200] --> - <string name="voice_warning_how_to_turn_off">To turn off voice input, go to input method settings.</string> - - <!-- Message to show when user enables the voice input settings (which says - "Press the microphone button"). [CHAR LIMIT=100] --> - <string name="voice_hint_dialog_message">To use voice input, press the microphone button.</string> - - <!-- Short message to tell the user the system is ready for them to speak. --> - <string name="voice_listening">Speak now</string> - - <!-- Short message shown after the user finishes speaking. --> - <string name="voice_working">Working</string> - - <!-- Short message shown before the user should speak. --> - <string name="voice_initializing"></string> - <!-- Short message shown when a generic error occurs. --> - <string name="voice_error">Error. Please try again.</string> - - <!-- Short message shown for a network error. --> - <string name="voice_network_error">Couldn\'t connect</string> - - <!-- Short message shown for a network error where the utterance was really long, - in which case we should suggest that the user speak less. --> - <string name="voice_too_much_speech">Error, too much speech.</string> - - <!-- Short message shown for an audio error. --> - <string name="voice_audio_error">Audio problem</string> - - <!-- Short message shown for an error with the voice server. --> - <string name="voice_server_error">Server error</string> - - <!-- Short message shown when no speech is heard. --> - <string name="voice_speech_timeout">No speech heard</string> - - <!-- Short message shown when the server couldn't parse any speech. --> - <string name="voice_no_match">No matches found</string> - - <!-- Short message shown when the user initiates voice and voice search is not installed. --> - <string name="voice_not_installed">Voice search not installed</string> - - <!-- Short hint shown in candidate view to explain voice input. --> - <string name="voice_swipe_hint"><b>Hint:</b> Swipe across keyboard to speak</string> - - <!-- Short hint shown in candidate view to explain that user can speak punctuation. --> - <string name="voice_punctuation_hint"><b>Hint:</b> Next time, try speaking punctuation like \"period\", \"comma\", or \"question mark\".</string> - - <!-- Label on button to stop recognition. Must be short to fit on button. --> - <string name="cancel">Cancel</string> - - <!-- Label on button when an error occurs --> - <string name="ok">OK</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> <!-- Preferences item for enabling speech input --> <string name="voice_input">Voice input key</string> @@ -307,9 +225,6 @@ <!-- On settings screen, voice input pop-up menu summary text to never show voice key [CHAR LIMIT=20] --> <string name="voice_input_modes_summary_off">Voice input is disabled</string> - <!-- Title of the dialog for selecting input methods. [CHAR LIMIT=20] --> - <string name="selectInputMethod">Select input method</string> - <!-- Title for configuring input method settings [CHAR LIMIT=35] --> <string name="configure_input_method">Configure input methods</string> @@ -320,7 +235,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 +248,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..b08ff3b90 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,31 +60,57 @@ <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="languageOnSpacebarFinalAlpha">@integer/config_language_on_spacebar_final_alpha</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> - <item name="keyboardBottomPadding">0dip</item> - <item name="horizontalGap">0dip</item> + <item name="keyboardTopPadding">0dp</item> + <item name="keyboardBottomPadding">0dp</item> + <item name="horizontalGap">0dp</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 +119,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 +132,7 @@ </style> <style name="MoreSuggestionsViewStyle" - parent="MiniKeyboardView" + parent="MoreKeysKeyboardView" > </style> <style name="SuggestionBackgroundStyle"> @@ -124,6 +146,7 @@ name="Keyboard.HighContrast" parent="Keyboard" > + <!-- This should be aligned with KeyboardSwitcher.KEYBOARD_THEMES[] --> <item name="themeId">1</item> </style> <style @@ -133,26 +156,29 @@ <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> <item name="keyboardBottomPadding">@fraction/keyboard_bottom_padding_stone</item> <item name="horizontalGap">@fraction/key_horizontal_gap_stone</item> <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,21 +187,31 @@ <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> - <item name="keyboardBottomPadding">0dip</item> - <item name="horizontalGap">0dip</item> + <item name="keyboardTopPadding">0dp</item> + <item name="keyboardBottomPadding">0dp</item> + <item name="horizontalGap">0dp</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,16 +261,26 @@ <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> - <item name="keyboardBottomPadding">0dip</item> - <item name="horizontalGap">0dip</item> + <item name="keyboardTopPadding">0dp</item> + <item name="keyboardBottomPadding">0dp</item> + <item name="horizontalGap">0dp</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,38 +307,48 @@ <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> <item name="keyPreviewBackgroundWidth">@dimen/keyboard_key_feedback_background_holo_width</item> <item name="keyPreviewBackgroundHeight">@dimen/keyboard_key_feedback_background_holo_height</item> <item name="keyPreviewTextColor">#FFFFFFFF</item> - <item name="keyPreviewHeight">@dimen/key_preview_height_ics</item> <item name="keyPreviewOffset">@dimen/key_preview_offset_ics</item> <item name="shadowColor">#00000000</item> <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> - <item name="keyboardBottomPadding">0dip</item> - <item name="horizontalGap">0dip</item> + <item name="keyboardTopPadding">0dp</item> + <item name="keyboardBottomPadding">0dp</item> + <item name="horizontalGap">0dp</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 +359,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 +374,7 @@ </style> <style name="MoreSuggestionsViewStyle.IceCreamSandwich" - parent="MiniKeyboardView.IceCreamSandwich" + parent="MoreKeysKeyboardView.IceCreamSandwich" > </style> <style name="SuggestionBackgroundStyle.IceCreamSandwich"> @@ -318,11 +382,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/sudden-jumping-touch-event-device-list.xml b/java/res/values/sudden-jumping-touch-event-device-list.xml index ba828a758..543992a81 100644 --- a/java/res/values/sudden-jumping-touch-event-device-list.xml +++ b/java/res/values/sudden-jumping-touch-event-device-list.xml @@ -19,9 +19,9 @@ --> <resources> <string-array name="sudden_jumping_touch_event_device_list" translatable="false"> - <!-- Nexus One --> - <item>mahimahi</item> - <!-- Droid --> - <item>sholes</item> + <!-- "Build.HARDWARE,true" that needs "sudden jump touch event" hack. + See {@link com.android.inputmethod.keyboard.SuddenJumpingTouchEventHandler}. --> + <item>mahimahi,true</item> <!-- Nexus One --> + <item>sholes,true</item> <!-- Droid --> </string-array> </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..88d320144 --- /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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_arabic" + latin:enableProximityCharsCorrection="true" /> + <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..959f644ea --- /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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_east_slavic" + latin:enableProximityCharsCorrection="true" /> + <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..593ad977c --- /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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_bulgarian" + latin:enableProximityCharsCorrection="true" /> + <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..f9f74516f --- /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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_qwertz" + latin:enableProximityCharsCorrection="true" /> + <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..0db9b1f59 --- /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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_nordic" + latin:enableProximityCharsCorrection="true" /> + <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-rQY/keyboard_set.xml b/java/res/xml-de-rQY/keyboard_set.xml new file mode 100644 index 000000000..8966ddbb0 --- /dev/null +++ b/java/res/xml-de-rQY/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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_qwerty" + latin:enableProximityCharsCorrection="true" /> + <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..f9f74516f --- /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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_qwertz" + latin:enableProximityCharsCorrection="true" /> + <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..af74e12c5 --- /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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_greek" + latin:enableProximityCharsCorrection="true" /> + <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..4ff5b54f2 --- /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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_spanish" + latin:enableProximityCharsCorrection="true" /> + <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..0db9b1f59 --- /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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_nordic" + latin:enableProximityCharsCorrection="true" /> + <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..f508f8f29 --- /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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_farsi" + latin:enableProximityCharsCorrection="true" /> + <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..0db9b1f59 --- /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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_nordic" + latin:enableProximityCharsCorrection="true" /> + <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..8966ddbb0 --- /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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_qwerty" + latin:enableProximityCharsCorrection="true" /> + <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..f9f74516f --- /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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_qwertz" + latin:enableProximityCharsCorrection="true" /> + <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..2ac25c91d --- /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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_azerty" + latin:enableProximityCharsCorrection="true" /> + <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-hi/keyboard_set.xml b/java/res/xml-hi/keyboard_set.xml new file mode 100644 index 000000000..c1fd0712d --- /dev/null +++ b/java/res/xml-hi/keyboard_set.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. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_hindi" + latin:enableProximityCharsCorrection="true" /> + <Element + latin:elementName="alphabetAutomaticShifted" + latin:elementKeyboard="@xml/kbd_hindi" + latin:enableProximityCharsCorrection="true" /> + <!-- On these shifted alphabet layouts the proximity characters correction should be disabled + because the letters on these layouts aren't the ones in different case of the above + unshifted layouts. --> + <Element + latin:elementName="alphabetManualShifted" + latin:elementKeyboard="@xml/kbd_hindi" /> + <Element + latin:elementName="alphabetShiftLocked" + latin:elementKeyboard="@xml/kbd_hindi" /> + <Element + latin:elementName="alphabetShiftLockShifted" + latin:elementKeyboard="@xml/kbd_hindi" /> + <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-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..f9f74516f --- /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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_qwertz" + latin:enableProximityCharsCorrection="true" /> + <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..f9f74516f --- /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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_qwertz" + latin:enableProximityCharsCorrection="true" /> + <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-is/keyboard_set.xml b/java/res/xml-is/keyboard_set.xml new file mode 100644 index 000000000..44edbba3e --- /dev/null +++ b/java/res/xml-is/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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_nordic" + latin:enableProximityCharsCorrection="true" /> + <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..6c51fb085 --- /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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_hebrew" + latin:enableProximityCharsCorrection="true" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_hebrew_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_hebrew_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..bc3df1ed0 --- /dev/null +++ b/java/res/xml-ka/keyboard_set.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. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_georgian" + latin:enableProximityCharsCorrection="true" /> + <Element + latin:elementName="alphabetAutomaticShifted" + latin:elementKeyboard="@xml/kbd_georgian" + latin:enableProximityCharsCorrection="true" /> + <!-- On these shifted alphabet layouts the proximity characters correction should be disabled + because the letters on these layouts aren't the ones in different case of the above + unshifted layouts. --> + <Element + latin:elementName="alphabetManualShifted" + latin:elementKeyboard="@xml/kbd_georgian" /> + <Element + latin:elementName="alphabetShiftLocked" + latin:elementKeyboard="@xml/kbd_georgian" /> + <Element + latin:elementName="alphabetShiftLockShifted" + 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..959f644ea --- /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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_east_slavic" + latin:enableProximityCharsCorrection="true" /> + <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..6b8b84434 --- /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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_south_slavic" + latin:enableProximityCharsCorrection="true" /> + <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..0db9b1f59 --- /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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_nordic" + latin:enableProximityCharsCorrection="true" /> + <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..8966ddbb0 --- /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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_qwerty" + latin:enableProximityCharsCorrection="true" /> + <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..8966ddbb0 --- /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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_qwerty" + latin:enableProximityCharsCorrection="true" /> + <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..8966ddbb0 --- /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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_qwerty" + latin:enableProximityCharsCorrection="true" /> + <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..959f644ea --- /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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_east_slavic" + latin:enableProximityCharsCorrection="true" /> + <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..8966ddbb0 --- /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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_qwerty" + latin:enableProximityCharsCorrection="true" /> + <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..8966ddbb0 --- /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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_qwerty" + latin:enableProximityCharsCorrection="true" /> + <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..5098134a7 --- /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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_south_slavic" + latin:enableProximityCharsCorrection="true" /> + <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..0db9b1f59 --- /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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_nordic" + latin:enableProximityCharsCorrection="true" /> + <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-sw600dp-land/kbd_thai.xml b/java/res/xml-sw600dp-land/kbd_thai.xml new file mode 100644 index 000000000..b75980f2f --- /dev/null +++ b/java/res/xml-sw600dp-land/kbd_thai.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. +*/ +--> + +<Keyboard + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:rowHeight="20%p" + latin:verticalGap="3.20%p" + latin:touchPositionCorrectionData="@null" +> + <include + latin:keyboardLayout="@xml/rows_thai" /> +</Keyboard> diff --git a/java/res/xml-de/kbd_qwerty.xml b/java/res/xml-sw600dp/kbd_azerty_symbols.xml index 89e10b26d..66254dea0 100644 --- a/java/res/xml-de/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="de" > <include - latin:keyboardLayout="@xml/kbd_rows_qwertz" /> + latin:keyboardLayout="@xml/rows_10_10_7_symbols" /> </Keyboard> diff --git a/java/res/xml-fr/kbd_qwerty.xml b/java/res/xml-sw600dp/kbd_azerty_symbols_shift.xml index 8c730a24f..3c5ed5e09 100644 --- a/java/res/xml-fr/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="fr" > <include - latin:keyboardLayout="@xml/kbd_rows_azerty" /> + latin:keyboardLayout="@xml/rows_10_10_7_symbols_shift" /> </Keyboard> diff --git a/java/res/xml-sw600dp/kbd_hebrew_symbols.xml b/java/res/xml-sw600dp/kbd_hebrew_symbols.xml new file mode 100644 index 000000000..66254dea0 --- /dev/null +++ b/java/res/xml-sw600dp/kbd_hebrew_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_hebrew_symbols_shift.xml b/java/res/xml-sw600dp/kbd_hebrew_symbols_shift.xml new file mode 100644 index 000000000..3c5ed5e09 --- /dev/null +++ b/java/res/xml-sw600dp/kbd_hebrew_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/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/kbd_thai.xml b/java/res/xml-sw600dp/kbd_thai.xml new file mode 100644 index 000000000..b75980f2f --- /dev/null +++ b/java/res/xml-sw600dp/kbd_thai.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. +*/ +--> + +<Keyboard + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:rowHeight="20%p" + latin:verticalGap="3.20%p" + latin:touchPositionCorrectionData="@null" +> + <include + latin:keyboardLayout="@xml/rows_thai" /> +</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..d4c45ad22 --- /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|preserveCase" + 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..77c0efd22 --- /dev/null +++ b/java/res/xml-sw600dp/key_styles_common.xml @@ -0,0 +1,165 @@ +<?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" /> + <!-- U+200C: ZERO WIDTH NON-JOINER + U+200D: ZERO WIDTH JOINER --> + <key-style + latin:styleName="zwnjKeyStyle" + latin:code="0x200C" + latin:keyIcon="iconZwnjKey" + latin:moreKeys="\@icon/zwjKey|‍" + latin:keyLabelFlags="hasPopupHint" + latin:keyActionFlags="noKeyPreview" /> + <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-sw768dp/kbd_row4_apostrophe_dash.xml b/java/res/xml-sw600dp/keys_apostrophe_dash.xml index 9536e81da..a53c1e4ab 100644 --- a/java/res/xml-sw768dp/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_row3_comma_period.xml b/java/res/xml-sw600dp/keys_comma_period.xml index b84443078..f5f307be6 100644 --- a/java/res/xml-sw600dp/kbd_row3_comma_period.xml +++ b/java/res/xml-sw600dp/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. @@ -32,15 +32,15 @@ </case> <default> <Key - latin:keyLabel="," - latin:keyLabelOption="hasUppercaseLetter" - latin:keyHintLabel="!" - latin:moreKeys="!" /> + latin:keyLabel="@string/keylabel_for_tablet_comma" + latin:keyHintLabel="@string/keyhintlabel_for_tablet_comma" + latin:moreKeys="@string/more_keys_for_tablet_comma" + latin:keyStyle="hasShiftedLetterHintStyle" /> <Key latin:keyLabel="." - latin:keyLabelOption="hasUppercaseLetter" - latin:keyHintLabel="\?" - latin:moreKeys="\?" /> + latin:keyHintLabel="@string/keyhintlabel_for_tablet_period" + latin:moreKeys="@string/more_keys_for_tablet_period" + 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_farsi1.xml b/java/res/xml-sw600dp/rowkeys_farsi1.xml new file mode 100644 index 000000000..ab260a460 --- /dev/null +++ b/java/res/xml-sw600dp/rowkeys_farsi1.xml @@ -0,0 +1,66 @@ +<?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 --> + <Key + latin:keyLabel="ق" /> + <!-- U+0641: "ف" ARABIC LETTER FEH --> + <Key + latin:keyLabel="ف" /> + <!-- 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 + U+06C0: "ۀ" ARABIC LETTER HEH WITH YEH ABOVE + U+0629: "ة" ARABIC LETTER TEH MARBUTA --> + <!-- TODO: DroidSansArabic lacks the glyph of U+06C0 ARABIC LETTER HEH WITH YEH ABOVE --> + <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 --> + <Key + latin:keyLabel="ج" /> + <!-- U+0686: "چ" ARABIC LETTER TCHEH --> + <Key + latin:keyLabel="چ" /> +</merge> diff --git a/java/res/xml-sw600dp/rowkeys_farsi2.xml b/java/res/xml-sw600dp/rowkeys_farsi2.xml new file mode 100644 index 000000000..98e0f2186 --- /dev/null +++ b/java/res/xml-sw600dp/rowkeys_farsi2.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" +> + <!-- U+0634: "ش" ARABIC LETTER SHEEN --> + <Key + latin:keyLabel="ش" /> + <!-- U+0633: "س" ARABIC LETTER SEEN --> + <Key + latin:keyLabel="س" /> + <!-- U+06CC: "ی" ARABIC LETTER FARSI YEH + U+0626: "ئ" ARABIC LETTER YEH WITH HAMZA ABOVE + U+064A: "ي" ARABIC LETTER YEH --> + <Key + latin:keyLabel="ی" + latin:moreKeys="ئ,ي" /> + <!-- U+0628: "ب" ARABIC LETTER BEH --> + <Key + latin:keyLabel="ب" /> + <!-- U+0644: "ل" ARABIC LETTER LAM --> + <Key + latin:keyLabel="ل" /> + <!-- U+0627: "ا" ARABIC LETTER ALEF + U+0621: "ء" ARABIC LETTER HAMZA + U+0622: "آ" ARABIC LETTER ALEF WITH MADDA ABOVE + U+0672: "ٲ" ARABIC LETTER ALEF WITH WAVY HAMZA ABOVE + U+0671: "ٱ" ARABIC LETTER ALEF WASLA + U+0673: "ٳ" ARABIC LETTER ALEF WITH WAVY HAMZA BELOW--> + <!-- TODO: DroidSansArabic lacks the glyph of U+0672 ARABIC LETTER ALEF WITH WAVY HAMZA ABOVE --> + <!-- TODO: DroidSansArabic lacks the glyph of U+0673 ARABIC LETTER ALEF WITH WAVY HAMZA BELOW --> + <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+06A9: "ک" ARABIC LETTER KEHEH + U+0643: "ك" ARABIC LETTER KAF --> + <Key + latin:keyLabel="ک" + latin:moreKeys="ك" /> + <!-- U+06AF: "گ" ARABIC LETTER GAF --> + <Key + latin:keyLabel="گ" /> +</merge> diff --git a/java/res/xml-sw600dp/rowkeys_farsi3.xml b/java/res/xml-sw600dp/rowkeys_farsi3.xml new file mode 100644 index 000000000..c80c14a55 --- /dev/null +++ b/java/res/xml-sw600dp/rowkeys_farsi3.xml @@ -0,0 +1,53 @@ +<?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+0632: "ز" ARABIC LETTER ZAIN + U+0698: "ژ" ARABIC LETTER JEH --> + <Key + latin:keyLabel="ز" + latin:moreKeys="ژ" /> + <!-- U+0631: "ر" ARABIC LETTER REH --> + <Key + latin:keyLabel="ر" /> + <!-- U+0630: "ذ" ARABIC LETTER THAL --> + <Key + latin:keyLabel="ذ" /> + <!-- U+062F: "د" ARABIC LETTER DAL --> + <Key + latin:keyLabel="د" /> + <!-- U+067E: "پ" ARABIC LETTER PEH --> + <Key + latin:keyLabel="پ" /> + <!-- U+0648: "و" ARABIC LETTER WAW + U+0676: "ٶ" ARABIC LETTER HIGH HAMZA WAW --> + <!-- TODO: DroidSansArabic lacks the glyph of U+0676 ARABIC LETTER HIGH HAMZA WAW --> + <Key + latin:keyLabel="و" + latin:moreKeys="ٶ" /> +</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/rowkeys_thai1.xml b/java/res/xml-sw600dp/rowkeys_thai1.xml new file mode 100644 index 000000000..e49cb2b47 --- /dev/null +++ b/java/res/xml-sw600dp/rowkeys_thai1.xml @@ -0,0 +1,97 @@ +<?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|alphabetShiftLocked|alphabetShiftLockShifted" + > + <!-- U+0E51: "๑" THAI DIGIT ONE --> + <Key + latin:keyLabel="๑" /> + <!-- U+0E52: "๒" THAI DIGIT TWO --> + <Key + latin:keyLabel="๒" /> + <!-- U+0E53: "๓" THAI DIGIT THREE --> + <Key + latin:keyLabel="๓" /> + <!-- U+0E54: "๔" THAI DIGIT FOUR --> + <Key + latin:keyLabel="๔" /> + <!-- U+0E39: " ู" THAI CHARACTER SARA UU --> + <Key + latin:keyLabel="ู" /> + <!-- U+0E3F: "฿" THAI CURRENCY SYMBOL BAHT --> + <Key + latin:keyLabel="฿" /> + <!-- U+0E55: "๕" THAI DIGIT FIVE --> + <Key + latin:keyLabel="๕" /> + <!-- U+0E56: "๖" THAI DIGIT SIX --> + <Key + latin:keyLabel="๖" /> + <!-- U+0E57: "๗" THAI DIGIT SEVEN --> + <Key + latin:keyLabel="๗" /> + <!-- U+0E58: "๘" THAI DIGIT EIGHT --> + <Key + latin:keyLabel="๘" /> + <!-- U+0E59: "๙" THAI DIGIT NINE --> + <Key + latin:keyLabel="๙" /> + </case> + <default> + <!-- U+0E45: "ๅ" THAI CHARACTER LAKKHANGYAO --> + <Key + latin:keyLabel="ๅ" /> + <Key + latin:keyLabel="/" /> + <!-- U+0E20: "ภ" THAI CHARACTER PHO SAMPHAO --> + <Key + latin:keyLabel="ภ" /> + <!-- U+0E16: "ถ" THAI CHARACTER THO THUNG --> + <Key + latin:keyLabel="ถ" /> + <!-- U+0E38: " ุ" THAI CHARACTER SARA U --> + <Key + latin:keyLabel="ุ" /> + <!-- U+0E36: " ึ" THAI CHARACTER SARA UE --> + <Key + latin:keyLabel="ึ" /> + <!-- U+0E04: "ค" THAI CHARACTER KHO KHWAI --> + <Key + latin:keyLabel="ค" /> + <!-- U+0E15: "ต" THAI CHARACTER TO TAO --> + <Key + latin:keyLabel="ต" /> + <!-- U+0E08: "จ" THAI CHARACTER CHO CHAN --> + <Key + latin:keyLabel="จ" /> + <!-- U+0E02: "ข" THAI CHARACTER KHO KHAI --> + <Key + latin:keyLabel="ข" /> + <!-- U+0E0A: "ช" THAI CHARACTER CHO CHANG --> + <Key + latin:keyLabel="ช" /> + </default> + </switch> +</merge> diff --git a/java/res/xml-sw600dp/rowkeys_thai2.xml b/java/res/xml-sw600dp/rowkeys_thai2.xml new file mode 100644 index 000000000..0edae1c73 --- /dev/null +++ b/java/res/xml-sw600dp/rowkeys_thai2.xml @@ -0,0 +1,108 @@ +<?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|alphabetShiftLocked|alphabetShiftLockShifted" + > + <!-- U+0E50: "๐" THAI DIGIT ZERO --> + <Key + latin:keyLabel="๐" /> + <Key + latin:keyLabel=""" /> + <!-- U+0E0E: "ฎ" THAI CHARACTER DO CHADA --> + <Key + latin:keyLabel="ฎ" /> + <!-- U+0E11: "ฑ" THAI CHARACTER THO NANGMONTHO --> + <Key + latin:keyLabel="ฑ" /> + <!-- U+0E18: "ธ" THAI CHARACTER THO THONG --> + <Key + latin:keyLabel="ธ" /> + <!-- U+0E4D: "กํ" THAI CHARACTER THANTHAKHAT --> + <Key + latin:keyLabel="ํ" /> + <!-- U+0E4A: "ก๊" THAI CHARACTER MAI TRI --> + <Key + latin:keyLabel="๊" /> + <!-- U+0E13: "ณ" THAI CHARACTER NO NEN --> + <Key + latin:keyLabel="ณ" /> + <!-- U+0E2F: "ฯ" THAI CHARACTER PAIYANNOI --> + <Key + latin:keyLabel="ฯ" /> + <!-- U+0E0D: "ญ" THAI CHARACTER YO YING --> + <Key + latin:keyLabel="ญ" /> + <!-- U+0E10: "ฐ" THAI CHARACTER THO THAN --> + <Key + latin:keyLabel="ฐ" /> + <Key + latin:keyLabel="," /> + <!-- U+0E05: "ฅ" THAI CHARACTER KHO KHON --> + <Key + latin:keyLabel="ฅ" /> + </case> + <default> + <!-- U+0E46: "ๆ" THAI CHARACTER MAIYAMOK --> + <Key + latin:keyLabel="ๆ" /> + <!-- U+0E44: "ไ" THAI CHARACTER SARA AI MAIMALAI --> + <Key + latin:keyLabel="ไ" /> + <!-- U+0E33: "ำ" THAI CHARACTER SARA AM --> + <Key + latin:keyLabel="ำ" /> + <!-- U+0E1E: "พ" THAI CHARACTER PHO PHAN --> + <Key + latin:keyLabel="พ" /> + <!-- U+0E30: "ะ" THAI CHARACTER SARA A --> + <Key + latin:keyLabel="ะ" /> + <!-- U+0E31: "กั" THAI CHARACTER MAI HAN-AKAT --> + <Key + latin:keyLabel="ั" /> + <!-- U+0E35: "กี" HAI CHARACTER SARA II --> + <Key + latin:keyLabel="ี" /> + <!-- U+0E23: "ร" THAI CHARACTER RO RUA --> + <Key + latin:keyLabel="ร" /> + <!-- U+0E19: "น" THAI CHARACTER NO NU --> + <Key + latin:keyLabel="น" /> + <!-- U+0E22: "ย" THAI CHARACTER YO YAK --> + <Key + latin:keyLabel="ย" /> + <!-- U+0E1A: "บ" THAI CHARACTER BO BAIMAI --> + <Key + latin:keyLabel="บ" /> + <!-- U+0E25: "ล" THAI CHARACTER LO LING --> + <Key + latin:keyLabel="ล" /> + <!-- U+0E03: "ฃ" THAI CHARACTER KHO KHUAT --> + <Key + latin:keyLabel="ฃ" /> + </default> + </switch> +</merge> diff --git a/java/res/xml-sw600dp/rowkeys_thai3.xml b/java/res/xml-sw600dp/rowkeys_thai3.xml new file mode 100644 index 000000000..abd67631c --- /dev/null +++ b/java/res/xml-sw600dp/rowkeys_thai3.xml @@ -0,0 +1,97 @@ +<?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|alphabetShiftLocked|alphabetShiftLockShifted" + > + <!-- U+0E24: "ฤ" THAI CHARACTER RU --> + <Key + latin:keyLabel="ฤ" /> + <!-- U+0E06: "ฆ" THAI CHARACTER KHO RAKHANG --> + <Key + latin:keyLabel="ฆ" /> + <!-- U+0E0F: "ฏ" THAI CHARACTER TO PATAK --> + <Key + latin:keyLabel="ฏ" /> + <!-- U+0E42: "โ" THAI CHARACTER SARA O --> + <Key + latin:keyLabel="โ" /> + <!-- U+0E0C: "ฌ" THAI CHARACTER CHO CHOE --> + <Key + latin:keyLabel="ฌ" /> + <!-- U+0E47: " ็" THAI CHARACTER MAITAIKHU --> + <Key + latin:keyLabel="็" /> + <!-- U+0E4B: " ๋" THAI CHARACTER MAI CHATTAWA --> + <Key + latin:keyLabel="๋" /> + <!-- U+0E29: "ษ" THAI CHARACTER SO RUSI --> + <Key + latin:keyLabel="ษ" /> + <!-- U+0E28: "ศ" THAI CHARACTER SO SALA --> + <Key + latin:keyLabel="ศ" /> + <!-- U+0E0B: "ซ" THAI CHARACTER SO SO --> + <Key + latin:keyLabel="ซ" /> + <Key + latin:keyLabel="." /> + </case> + <default> + <!-- U+0E1F: "ฟ" THAI CHARACTER FO FAN --> + <Key + latin:keyLabel="ฟ" /> + <!-- U+0E2B: "ห" THAI CHARACTER HO HIP --> + <Key + latin:keyLabel="ห" /> + <!-- U+0E01: "ก" THAI CHARACTER KO KAI --> + <Key + latin:keyLabel="ก" /> + <!-- U+0E14: "ด" THAI CHARACTER DO DEK --> + <Key + latin:keyLabel="ด" /> + <!-- U+0E40: "เ" THAI CHARACTER SARA E --> + <Key + latin:keyLabel="เ" /> + <!-- U+0E49: " ้" THAI CHARACTER MAI THO --> + <Key + latin:keyLabel="้" /> + <!-- U+0E48: " ฺ" THAI CHARACTER MAI EK --> + <Key + latin:keyLabel="่" /> + <!-- U+0E32: "า" THAI CHARACTER SARA AA --> + <Key + latin:keyLabel="า" /> + <!-- U+0E2A: "ส" THAI CHARACTER SO SUA --> + <Key + latin:keyLabel="ส" /> + <!-- U+0E27: "ว" THAI CHARACTER WO WAEN --> + <Key + latin:keyLabel="ว" /> + <!-- U+0E07: "ง" THAI CHARACTER NGO NGU --> + <Key + latin:keyLabel="ง" /> + </default> + </switch> +</merge> diff --git a/java/res/xml-sw600dp/rowkeys_thai4.xml b/java/res/xml-sw600dp/rowkeys_thai4.xml new file mode 100644 index 000000000..cec34a63b --- /dev/null +++ b/java/res/xml-sw600dp/rowkeys_thai4.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|alphabetShiftLocked|alphabetShiftLockShifted" + > + <Key + latin:keyLabel="(" /> + <Key + latin:keyLabel=")" /> + <!-- U+0E09: "ฉ" THAI CHARACTER CHO CHING --> + <Key + latin:keyLabel="ฉ" /> + <!-- U+0E2E: "ฮ" THAI CHARACTER HO NOKHUK --> + <Key + latin:keyLabel="ฮ" /> + <!-- U+0E3A: " ฺ" THAI CHARACTER PHINTHU --> + <Key + latin:keyLabel="ฺ" /> + <!-- U+0E4C: " ์" THAI CHARACTER THANTHAKHAT --> + <Key + latin:keyLabel="์" /> + <Key + latin:keyLabel="\?" /> + <!-- U+0E12: "ฒ" THAI CHARACTER THO PHUTHAO --> + <Key + latin:keyLabel="ฒ" /> + <!-- U+0E2C: "ฬ" THAI CHARACTER LO CHULA --> + <Key + latin:keyLabel="ฬ" /> + <!-- U+0E26: "ฦ" THAI CHARACTER LU --> + <Key + latin:keyLabel="ฦ" /> + </case> + <default> + <!-- U+0E1C: "ผ" THAI CHARACTER PHO PHUNG --> + <Key + latin:keyLabel="ผ" /> + <!-- U+0E1B: "ป" THAI CHARACTER PO PLA --> + <Key + latin:keyLabel="ป" /> + <!-- U+0E41: "แ" THAI CHARACTER SARA AE --> + <Key + latin:keyLabel="แ" /> + <!-- U+0E2D: "อ" THAI CHARACTER O ANG --> + <Key + latin:keyLabel="อ" /> + <!-- U+0E34: " ิ" THAI CHARACTER SARA I --> + <Key + latin:keyLabel="ิ" /> + <!-- U+0E37: " ื" THAI CHARACTER SARA UEE --> + <Key + latin:keyLabel="ื" /> + <!-- U+0E17: "ท" THAI CHARACTER THO THAHAN --> + <Key + latin:keyLabel="ท" /> + <!-- U+0E21: "ม" THAI CHARACTER MO MA --> + <Key + latin:keyLabel="ม" /> + <!-- U+0E43: "ใ" THAI CHARACTER SARA AI MAIMUAN --> + <Key + latin:keyLabel="ใ" /> + <!-- U+0E1D: "ฝ" THAI CHARACTER FO FA --> + <Key + latin:keyLabel="ฝ" /> + </default> + </switch> +</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_farsi.xml b/java/res/xml-sw600dp/rows_farsi.xml new file mode 100644 index 000000000..75800420a --- /dev/null +++ b/java/res/xml-sw600dp/rows_farsi.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" /> + <Row + latin:keyWidth="7.6%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_farsi1" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.6%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_farsi2" + 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_farsi3" /> + <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_hindi.xml b/java/res/xml-sw600dp/rows_hindi.xml new file mode 100644 index 000000000..6c98e080e --- /dev/null +++ b/java/res/xml-sw600dp/rows_hindi.xml @@ -0,0 +1,61 @@ +<?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_hindi1" + latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.6%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_hindi2" + latin:keyXPos="4.500%p" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.5%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="10.0%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_hindi3" /> + <include + latin:keyboardLayout="@xml/keys_comma_period" /> + <include + latin:keyboardLayout="@xml/key_smiley" /> + </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-sw600dp/rows_thai.xml b/java/res/xml-sw600dp/rows_thai.xml new file mode 100644 index 000000000..d4eaa10bb --- /dev/null +++ b/java/res/xml-sw600dp/rows_thai.xml @@ -0,0 +1,67 @@ +<?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.800%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_thai1" + latin:keyXPos="4.0%p" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillRight" /> + </Row> + <Row + latin:keyWidth="7.692%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_thai2" /> + </Row> + <Row + latin:keyWidth="7.692%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_thai3" + latin:keyXPos="4.5%p" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.692%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="10.0%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_thai4" /> + <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-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-land/kbd_thai.xml b/java/res/xml-sw768dp-land/kbd_thai.xml new file mode 100644 index 000000000..b2cdbc373 --- /dev/null +++ b/java/res/xml-sw768dp-land/kbd_thai.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. +*/ +--> + +<Keyboard + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:rowHeight="20%p" + latin:verticalGap="2.65%p" + latin:touchPositionCorrectionData="@null" +> + <include + latin:keyboardLayout="@xml/rows_thai" /> +</Keyboard> diff --git a/java/res/xml-sw768dp-land/kbd_thai_symbols.xml b/java/res/xml-sw768dp-land/kbd_thai_symbols.xml new file mode 100644 index 000000000..1531458ea --- /dev/null +++ b/java/res/xml-sw768dp-land/kbd_thai_symbols.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. +*/ +--> + +<Keyboard + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:rowHeight="20%p" + latin:verticalGap="2.65%p" + latin:touchPositionCorrectionData="@null" +> + <include + latin:keyboardLayout="@xml/rows_thai_symbols" /> +</Keyboard> diff --git a/java/res/xml-sw768dp-land/kbd_thai_symbols_shift.xml b/java/res/xml-sw768dp-land/kbd_thai_symbols_shift.xml new file mode 100644 index 000000000..fa30f24c0 --- /dev/null +++ b/java/res/xml-sw768dp-land/kbd_thai_symbols_shift.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. +*/ +--> + +<Keyboard + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:rowHeight="20%p" + latin:verticalGap="2.65%p" + latin:touchPositionCorrectionData="@null" +> + <include + latin:keyboardLayout="@xml/rows_thai_symbols_shift" /> +</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/kbd_thai.xml b/java/res/xml-sw768dp/kbd_thai.xml new file mode 100644 index 000000000..593ccbd48 --- /dev/null +++ b/java/res/xml-sw768dp/kbd_thai.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. +*/ +--> + +<Keyboard + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:rowHeight="20%p" + latin:verticalGap="2.95%p" + latin:touchPositionCorrectionData="@null" +> + <include + latin:keyboardLayout="@xml/rows_thai" /> +</Keyboard> diff --git a/java/res/xml-sw768dp/kbd_thai_symbols.xml b/java/res/xml-sw768dp/kbd_thai_symbols.xml new file mode 100644 index 000000000..e2e5f5d56 --- /dev/null +++ b/java/res/xml-sw768dp/kbd_thai_symbols.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. +*/ +--> + +<Keyboard + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:rowHeight="20%p" + latin:verticalGap="2.95%p" + latin:touchPositionCorrectionData="@null" +> + <include + latin:keyboardLayout="@xml/rows_thai_symbols" /> +</Keyboard> diff --git a/java/res/xml-sw768dp/kbd_thai_symbols_shift.xml b/java/res/xml-sw768dp/kbd_thai_symbols_shift.xml new file mode 100644 index 000000000..a1358d4a2 --- /dev/null +++ b/java/res/xml-sw768dp/kbd_thai_symbols_shift.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. +*/ +--> + +<Keyboard + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" + latin:rowHeight="20%p" + latin:verticalGap="2.95%p" + latin:touchPositionCorrectionData="@null" +> + <include + latin:keyboardLayout="@xml/rows_thai_symbols_shift" /> +</Keyboard> 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..f4a1a4ea5 --- /dev/null +++ b/java/res/xml-sw768dp/key_styles_common.xml @@ -0,0 +1,164 @@ +<?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" /> + <!-- U+200C: ZERO WIDTH NON-JOINER + U+200D: ZERO WIDTH JOINER --> + <key-style + latin:styleName="zwnjKeyStyle" + latin:code="0x200C" + latin:keyIcon="iconZwnjKey" + latin:moreKeys="\@icon/zwjKey|‍" + latin:keyLabelFlags="hasPopupHint" + latin:keyActionFlags="noKeyPreview" /> + <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-sw600dp/kbd_row4_apostrophe_dash.xml b/java/res/xml-sw768dp/keys_apostrophe_dash.xml index 9536e81da..a53c1e4ab 100644 --- a/java/res/xml-sw600dp/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..90da21ba3 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,43 @@ <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:keyStyle="zwnjKeyStyle" /> + </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/rowkeys_thai_digits.xml b/java/res/xml-sw768dp/rowkeys_thai_digits.xml new file mode 100644 index 000000000..512283096 --- /dev/null +++ b/java/res/xml-sw768dp/rowkeys_thai_digits.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" +> + <!-- U+0E51: "๑" THAI DIGIT ONE --> + <Key + latin:keyLabel="๑" /> + <!-- U+0E52: "๒" THAI DIGIT TWO --> + <Key + latin:keyLabel="๒" /> + <!-- U+0E53: "๓" THAI DIGIT THREE --> + <Key + latin:keyLabel="๓" /> + <!-- U+0E54: "๔" THAI DIGIT FOUR --> + <Key + latin:keyLabel="๔" /> + <!-- U+0E55: "๕" THAI DIGIT FIVE --> + <Key + latin:keyLabel="๕" /> + <!-- U+0E56: "๖" THAI DIGIT SIX --> + <Key + latin:keyLabel="๖" /> + <!-- U+0E57: "๗" THAI DIGIT SEVEN --> + <Key + latin:keyLabel="๗" /> + <!-- U+0E58: "๘" THAI DIGIT EIGHT --> + <Key + latin:keyLabel="๘" /> + <!-- U+0E59: "๙" THAI DIGIT NINE --> + <Key + latin:keyLabel="๙" /> + <!-- U+0E50: "๐" THAI DIGIT ZERO --> + <Key + latin:keyLabel="๐" /> +</merge> 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..1d61d999b --- /dev/null +++ b/java/res/xml-sw768dp/rows_10_10_7_symbols.xml @@ -0,0 +1,69 @@ +<?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: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: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..d22f8331d --- /dev/null +++ b/java/res/xml-sw768dp/rows_10_10_7_symbols_shift.xml @@ -0,0 +1,69 @@ +<?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: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: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..eaa64e5af --- /dev/null +++ b/java/res/xml-sw768dp/rows_arabic.xml @@ -0,0 +1,61 @@ +<?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.969%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_arabic1" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.375%p" + > + <Key + latin:keyStyle="toSymbolKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="11.172%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_arabic2" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.375%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_arabic3" + latin:keyXPos="13.829%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..1fc1a0630 --- /dev/null +++ b/java/res/xml-sw768dp/rows_azerty.xml @@ -0,0 +1,69 @@ +<?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: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: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: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..cb05fd5aa --- /dev/null +++ b/java/res/xml-sw768dp/rows_bulgarian.xml @@ -0,0 +1,69 @@ +<?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.186%p" + > + <Key + latin:keyStyle="tabKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="7.969%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_bulgarian1" + latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.186%p" + > + <Key + latin:keyStyle="toSymbolKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="11.172%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="13.829%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..480881bb6 --- /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.000%p" + > + <Key + latin:keyStyle="tabKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="7.969%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.000%p" + > + <Key + latin:keyStyle="toSymbolKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="11.172%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_east_slavic2" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.000%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="13.829%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_farsi.xml b/java/res/xml-sw768dp/rows_farsi.xml new file mode 100644 index 000000000..28ea6fff5 --- /dev/null +++ b/java/res/xml-sw768dp/rows_farsi.xml @@ -0,0 +1,69 @@ +<?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.000%p" + > + <Key + latin:keyStyle="tabKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="7.969%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_farsi1" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.125%p" + > + <Key + latin:keyStyle="toSymbolKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="11.172%p"/> + <include + latin:keyboardLayout="@xml/rowkeys_farsi2" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.375%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="13.829%p"/> + <include + latin:keyboardLayout="@xml/rowkeys_farsi3" /> + <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_georgian.xml b/java/res/xml-sw768dp/rows_georgian.xml new file mode 100644 index 000000000..3805b5d88 --- /dev/null +++ b/java/res/xml-sw768dp/rows_georgian.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/rowkeys_georgian1" + latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" /> + <Key + latin:keyStyle="deleteKeyStyle" + 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: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..c0b38dc15 --- /dev/null +++ b/java/res/xml-sw768dp/rows_greek.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="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: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: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..476071a5e --- /dev/null +++ b/java/res/xml-sw768dp/rows_hebrew.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.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: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_hebrew2" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="8.047%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_hebrew3" + latin:keyXPos="13.829%p" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml-sw768dp/rows_hindi.xml b/java/res/xml-sw768dp/rows_hindi.xml new file mode 100644 index 000000000..86e925fb1 --- /dev/null +++ b/java/res/xml-sw768dp/rows_hindi.xml @@ -0,0 +1,69 @@ +<?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" + latin:keyWidth="7.969%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_hindi1" + latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.186%p" + > + <Key + latin:keyStyle="toSymbolKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="11.172%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_hindi2" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.040%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="13.829%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_hindi3" /> + <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_nordic.xml b/java/res/xml-sw768dp/rows_nordic.xml new file mode 100644 index 000000000..fbee1c3f0 --- /dev/null +++ b/java/res/xml-sw768dp/rows_nordic.xml @@ -0,0 +1,70 @@ +<?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.969%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_nordic1" + latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.227%p" + > + <Key + latin:keyStyle="toSymbolKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="11.172%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_nordic2" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.227%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="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..edfb4011d --- /dev/null +++ b/java/res/xml-sw768dp/rows_qwerty.xml @@ -0,0 +1,70 @@ +<?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: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: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..7e755067d --- /dev/null +++ b/java/res/xml-sw768dp/rows_qwertz.xml @@ -0,0 +1,70 @@ +<?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: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: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..7ea0ff465 --- /dev/null +++ b/java/res/xml-sw768dp/rows_south_slavic.xml @@ -0,0 +1,69 @@ +<?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.000%p" + > + <Key + latin:keyStyle="tabKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="7.969%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_south_slavic1" + latin:keyLabelFlags="disableAdditionalMoreKeys|disableKeyHintLabel" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.000%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:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.000%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="13.829%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_south_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_spanish.xml b/java/res/xml-sw768dp/rows_spanish.xml new file mode 100644 index 000000000..fc3388d53 --- /dev/null +++ b/java/res/xml-sw768dp/rows_spanish.xml @@ -0,0 +1,70 @@ +<?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: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: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..ed2df18d7 --- /dev/null +++ b/java/res/xml-sw768dp/rows_symbols.xml @@ -0,0 +1,69 @@ +<?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: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: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..30e1df0bf --- /dev/null +++ b/java/res/xml-sw768dp/rows_symbols_shift.xml @@ -0,0 +1,69 @@ +<?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: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: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-sw768dp/rows_thai.xml b/java/res/xml-sw768dp/rows_thai.xml new file mode 100644 index 000000000..cc77f8bc5 --- /dev/null +++ b/java/res/xml-sw768dp/rows_thai.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="7.079%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_thai1" + latin:keyXPos="11.508%p"/> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillBoth"/> + </Row> + <Row + latin:keyWidth="7.079%p" + > + <Key + latin:keyStyle="tabKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="7.969%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_thai2" /> + </Row> + <Row + latin:keyWidth="7.125%p" + > + <Key + latin:keyStyle="toSymbolKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="11.172%p"/> + <include + latin:keyboardLayout="@xml/rowkeys_thai3" /> + <Key + latin:keyStyle="enterKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <Row + latin:keyWidth="7.181%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="13.829%p"/> + <include + latin:keyboardLayout="@xml/rowkeys_thai4" /> + <include + latin:keyboardLayout="@xml/keys_comma_period" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml-sw768dp/rows_thai_symbols.xml b/java/res/xml-sw768dp/rows_thai_symbols.xml new file mode 100644 index 000000000..20f22bc5b --- /dev/null +++ b/java/res/xml-sw768dp/rows_thai_symbols.xml @@ -0,0 +1,76 @@ +<?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" + > + <include + latin:keyboardLayout="@xml/rowkeys_thai_digits" + latin:keyXPos="7.969%p" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillRight" /> + </Row> + <Row + latin:keyWidth="8.282%p" + > + <Key + latin:keyStyle="tabKeyStyle" + latin:keyLabelFlags="alignLeft" + latin:keyWidth="7.969%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_symbols1" /> + </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: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_thai_symbols_shift.xml b/java/res/xml-sw768dp/rows_thai_symbols_shift.xml new file mode 100644 index 000000000..467dd19ad --- /dev/null +++ b/java/res/xml-sw768dp/rows_thai_symbols_shift.xml @@ -0,0 +1,76 @@ +<?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" + > + <include + latin:keyboardLayout="@xml/rowkeys_thai_digits" + latin:keyXPos="7.969%p" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillBoth" /> + </Row> + <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" /> + </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: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-th/keyboard_set.xml b/java/res/xml-th/keyboard_set.xml new file mode 100644 index 000000000..99e81b85e --- /dev/null +++ b/java/res/xml-th/keyboard_set.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. +*/ +--> + +<KeyboardSet + xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_thai" + latin:enableProximityCharsCorrection="true" /> + <Element + latin:elementName="alphabetAutomaticShifted" + latin:elementKeyboard="@xml/kbd_thai" + latin:enableProximityCharsCorrection="true" /> + <!-- On these shifted alphabet layouts the proximity characters correction should be disabled + because the letters on these layouts aren't the ones in different case of the above + unshifted layouts. --> + <Element + latin:elementName="alphabetManualShifted" + latin:elementKeyboard="@xml/kbd_thai" /> + <Element + latin:elementName="alphabetShiftLocked" + latin:elementKeyboard="@xml/kbd_thai" /> + <Element + latin:elementName="alphabetShiftLockShifted" + latin:elementKeyboard="@xml/kbd_thai" /> + <Element + latin:elementName="symbols" + latin:elementKeyboard="@xml/kbd_thai_symbols" /> + <Element + latin:elementName="symbolsShifted" + latin:elementKeyboard="@xml/kbd_thai_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-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..8966ddbb0 --- /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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_qwerty" + latin:enableProximityCharsCorrection="true" /> + <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..959f644ea --- /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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_east_slavic" + latin:enableProximityCharsCorrection="true" /> + <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..8966ddbb0 --- /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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_qwerty" + latin:enableProximityCharsCorrection="true" /> + <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-zz-rQY/keyboard_set.xml b/java/res/xml-zz-rQY/keyboard_set.xml new file mode 100644 index 000000000..6fa97017c --- /dev/null +++ b/java/res/xml-zz-rQY/keyboard_set.xml @@ -0,0 +1,43 @@ +<?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:disableShortcutKey="true" > + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_qwerty" + latin:enableProximityCharsCorrection="true" /> + <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_farsi.xml b/java/res/xml/kbd_farsi.xml new file mode 100644 index 000000000..1af4e61ca --- /dev/null +++ b/java/res/xml/kbd_farsi.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_farsi" /> +</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-cs/kbd_qwerty.xml b/java/res/xml/kbd_hebrew.xml index 9991ea2d2..74836f342 100644 --- a/java/res/xml-cs/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="cs" > <include - latin:keyboardLayout="@xml/kbd_rows_qwertz" /> + latin:keyboardLayout="@xml/rows_hebrew" /> </Keyboard> diff --git a/java/res/xml/kbd_hebrew_symbols.xml b/java/res/xml/kbd_hebrew_symbols.xml new file mode 100644 index 000000000..7e075df48 --- /dev/null +++ b/java/res/xml/kbd_hebrew_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_hebrew_symbols_shift.xml b/java/res/xml/kbd_hebrew_symbols_shift.xml new file mode 100644 index 000000000..25db3c84d --- /dev/null +++ b/java/res/xml/kbd_hebrew_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_hindi.xml b/java/res/xml/kbd_hindi.xml new file mode 100644 index 000000000..0e69e3ae2 --- /dev/null +++ b/java/res/xml/kbd_hindi.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_hindi" /> +</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-hu/kbd_qwerty.xml b/java/res/xml/kbd_nordic.xml index 3195d5b1f..a2196c926 100644 --- a/java/res/xml-hu/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="hu" > <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_thai.xml b/java/res/xml/kbd_thai.xml new file mode 100644 index 000000000..058ca16a3 --- /dev/null +++ b/java/res/xml/kbd_thai.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_thai" /> +</Keyboard> diff --git a/java/res/xml/kbd_thai_symbols.xml b/java/res/xml/kbd_thai_symbols.xml new file mode 100644 index 000000000..7e075df48 --- /dev/null +++ b/java/res/xml/kbd_thai_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_thai_symbols_shift.xml b/java/res/xml/kbd_thai_symbols_shift.xml new file mode 100644 index 000000000..25db3c84d --- /dev/null +++ b/java/res/xml/kbd_thai_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_settings_or_tab.xml b/java/res/xml/key_azerty_quote.xml index 4a8bcc7a6..8c44f7862 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..d5a9a2629 100644 --- a/java/res/xml/kbd_key_styles.xml +++ b/java/res/xml/key_styles_common.xml @@ -27,138 +27,111 @@ 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|preserveCase" + 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" /> + <!-- U+200C: ZERO WIDTH NON-JOINER + U+200D: ZERO WIDTH JOINER --> + <key-style + latin:styleName="zwnjKeyStyle" + latin:code="0x200C" + latin:keyIcon="iconZwnjKey" + latin:moreKeys="\@icon/zwjKey|‍" + latin:keyLabelFlags="hasPopupHint" + latin:keyActionFlags="noKeyPreview" 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" /> <key-style latin:styleName="tabKeyStyle" @@ -186,7 +159,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 +168,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 +177,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..bd1d959e4 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,26 +62,56 @@ 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" > + <!-- U+20AA: "₪" NEW SHEQEL SIGN + U+00A3: "£" POUND SIGN + U+20AC: "€" EURO SIGN + U+00A2: "¢" CENT SIGN --> <key-style latin:styleName="currencyKeyStyle" - latin:keyLabel="₪" + latin:keyLabel="₪" + latin:moreKeys="@string/more_keys_for_currency_general" /> + <key-style + latin:styleName="moreCurrency1KeyStyle" + latin:keyLabel="£" /> + <key-style + latin:styleName="moreCurrency2KeyStyle" + latin:keyLabel="€" /> + <key-style + latin:styleName="moreCurrency3KeyStyle" + latin:keyLabel="$" + latin:moreKeys="¢" /> + <key-style + latin:styleName="moreCurrency4KeyStyle" + latin:keyLabel="¢" /> + </case> + <case + latin:languageCode="fa" + > + <!-- U+FDFC: "﷼" RIAL SIGN + U+00A3: "£" POUND SIGN + U+20AC: "€" EURO SIGN + U+00A2: "¢" CENT SIGN --> + <!-- TODO: DroidSansArabic lacks the glyph of U+FCDC: RIAL SIGN --> + <key-style + latin:styleName="currencyKeyStyle" + latin:keyLabel="﷼" latin:moreKeys="@string/more_keys_for_currency_general" /> <key-style latin:styleName="moreCurrency1KeyStyle" @@ -101,27 +131,31 @@ <case latin:countryCode="GB" > + <!-- U+00A3: "£" POUND SIGN + U+20AC: "€" EURO SIGN + U+00A5: "¥" YEN SIGN + U+00A2: "¢" CENT SIGN --> <key-style latin:styleName="currencyKeyStyle" - latin:keyLabel="£" + latin:keyLabel="£" latin:moreKeys="@string/more_keys_for_currency_pound" /> <key-style latin:styleName="moreCurrency1KeyStyle" - latin:keyLabel="€" /> + latin:keyLabel="€" /> <key-style latin:styleName="moreCurrency2KeyStyle" - latin:keyLabel="¥" /> + latin:keyLabel="¥" /> <key-style latin:styleName="moreCurrency3KeyStyle" latin:keyLabel="$" - latin:moreKeys="¢" /> + latin:moreKeys="¢" /> <key-style latin:styleName="moreCurrency4KeyStyle" - latin:keyLabel="¢" /> + latin:keyLabel="¢" /> </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..8dd849879 100644 --- a/java/res/xml/kbd_currency_dollar_key_styles.xml +++ b/java/res/xml/key_styles_currency_dollar.xml @@ -19,20 +19,24 @@ --> <merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"> + <!-- U+00A3: "£" POUND SIGN + U+00A2: "¢" CENT SIGN + U+20AC: "€" EURO SIGN + U+00A5: "¥" YEN SIGN --> <key-style latin:styleName="currencyKeyStyle" latin:keyLabel="$" latin:moreKeys="@string/more_keys_for_currency_dollar" /> <key-style latin:styleName="moreCurrency1KeyStyle" - latin:keyLabel="£" /> + latin:keyLabel="£" /> <key-style latin:styleName="moreCurrency2KeyStyle" - latin:keyLabel="¢" /> + latin:keyLabel="¢" /> <key-style latin:styleName="moreCurrency3KeyStyle" - latin:keyLabel="€" /> + latin:keyLabel="€" /> <key-style latin:styleName="moreCurrency4KeyStyle" - latin:keyLabel="¥" /> + latin:keyLabel="¥" /> </merge> diff --git a/java/res/xml/kbd_currency_euro_key_styles.xml b/java/res/xml/key_styles_currency_euro.xml index 6edddf074..0573e0991 100644 --- a/java/res/xml/kbd_currency_euro_key_styles.xml +++ b/java/res/xml/key_styles_currency_euro.xml @@ -19,21 +19,25 @@ --> <merge xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"> + <!-- U+20AC: "€" EURO SIGN + U+00A3: "£" POUND SIGN + U+00A5: "¥" YEN SIGN + U+00A2: "¢" CENT SIGN --> <key-style latin:styleName="currencyKeyStyle" - latin:keyLabel="€" + latin:keyLabel="€" latin:moreKeys="@string/more_keys_for_currency_euro" /> <key-style latin:styleName="moreCurrency1KeyStyle" - latin:keyLabel="£" /> + latin:keyLabel="£" /> <key-style latin:styleName="moreCurrency2KeyStyle" - latin:keyLabel="¥" /> + latin:keyLabel="¥" /> <key-style latin:styleName="moreCurrency3KeyStyle" latin:keyLabel="$" - latin:moreKeys="¢" /> + latin:moreKeys="¢" /> <key-style latin:styleName="moreCurrency4KeyStyle" - latin:keyLabel="¢" /> + latin:keyLabel="¢" /> </merge> 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..8966ddbb0 --- /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"> + <Element + latin:elementName="alphabet" + latin:elementKeyboard="@xml/kbd_qwerty" + latin:enableProximityCharsCorrection="true" /> + <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/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/language_prefs.xml b/java/res/xml/language_prefs.xml deleted file mode 100644 index b7a4c07db..000000000 --- a/java/res/xml/language_prefs.xml +++ /dev/null @@ -1,19 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2009 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> - -<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" - android:title="@string/language_selection_title"> -</PreferenceScreen> diff --git a/java/res/xml/method.xml b/java/res/xml/method.xml index 6184add4d..7a21a856b 100644 --- a/java/res/xml/method.xml +++ b/java/res/xml/method.xml @@ -20,7 +20,51 @@ <!-- 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_QY: 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 + hi: Hindi/hindi + hr: Croatian/qwertz + hu: Hungarian/qwertz + is: Icelandic/qwerty + 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 + th: Thai/thai + tr: Turkish/qwerty + uk: Ukrainian/east_slavic + vi: Vietnamese/qwerty + zz_QY: QWERTY/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,145 +75,246 @@ android:label="@string/subtype_en_US" android:imeSubtypeLocale="en_US" android:imeSubtypeMode="keyboard" - android:imeSubtypeExtraValue="TrySuppressingImeSwitcher,AsciiCapable,SupportTouchPositionCorrection" + android:imeSubtypeExtraValue="TrySuppressingImeSwitcher,AsciiCapable" /> <subtype android:icon="@drawable/ic_subtype_keyboard" android:label="@string/subtype_en_GB" android:imeSubtypeLocale="en_GB" android:imeSubtypeMode="keyboard" - android:imeSubtypeExtraValue="TrySuppressingImeSwitcher,AsciiCapable,SupportTouchPositionCorrection" + android:imeSubtypeExtraValue="TrySuppressingImeSwitcher,AsciiCapable" /> <subtype android:icon="@drawable/ic_subtype_keyboard" android:label="@string/subtype_generic" android:imeSubtypeLocale="ar" android:imeSubtypeMode="keyboard" - android:imeSubtypeExtraValue="SupportTouchPositionCorrection" + /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_generic" + android:imeSubtypeLocale="be" + android:imeSubtypeMode="keyboard" + /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_generic" + android:imeSubtypeLocale="bg" + android:imeSubtypeMode="keyboard" /> <subtype android:icon="@drawable/ic_subtype_keyboard" android:label="@string/subtype_generic" android:imeSubtypeLocale="cs" android:imeSubtypeMode="keyboard" - android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection" + android:imeSubtypeExtraValue="AsciiCapable" /> <subtype android:icon="@drawable/ic_subtype_keyboard" android:label="@string/subtype_generic" android:imeSubtypeLocale="da" android:imeSubtypeMode="keyboard" - android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection" + android:imeSubtypeExtraValue="AsciiCapable" /> <subtype android:icon="@drawable/ic_subtype_keyboard" android:label="@string/subtype_generic" android:imeSubtypeLocale="de" android:imeSubtypeMode="keyboard" - android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection" + android:imeSubtypeExtraValue="AsciiCapable" /> <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" + android:imeSubtypeExtraValue="AsciiCapable,KeyboardLocale=de_QY" + /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_generic" + android:imeSubtypeLocale="el" + android:imeSubtypeMode="keyboard" /> <subtype android:icon="@drawable/ic_subtype_keyboard" android:label="@string/subtype_generic" android:imeSubtypeLocale="es" android:imeSubtypeMode="keyboard" - android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection" + android:imeSubtypeExtraValue="AsciiCapable" + /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_generic" + android:imeSubtypeLocale="et" + android:imeSubtypeMode="keyboard" + android:imeSubtypeExtraValue="AsciiCapable" + /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_generic" + android:imeSubtypeLocale="fa" + android:imeSubtypeMode="keyboard" /> <subtype android:icon="@drawable/ic_subtype_keyboard" android:label="@string/subtype_generic" android:imeSubtypeLocale="fi" android:imeSubtypeMode="keyboard" - android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection" + android:imeSubtypeExtraValue="AsciiCapable" /> <subtype android:icon="@drawable/ic_subtype_keyboard" android:label="@string/subtype_generic" android:imeSubtypeLocale="fr" android:imeSubtypeMode="keyboard" - android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection" + android:imeSubtypeExtraValue="AsciiCapable" /> <subtype android:icon="@drawable/ic_subtype_keyboard" android:label="@string/subtype_generic" android:imeSubtypeLocale="fr_CA" android:imeSubtypeMode="keyboard" - android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection" + android:imeSubtypeExtraValue="AsciiCapable" /> <subtype android:icon="@drawable/ic_subtype_keyboard" android:label="@string/subtype_generic" android:imeSubtypeLocale="fr_CH" android:imeSubtypeMode="keyboard" - android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection" + android:imeSubtypeExtraValue="AsciiCapable" + /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_generic" + android:imeSubtypeLocale="hi" + android:imeSubtypeMode="keyboard" /> <subtype android:icon="@drawable/ic_subtype_keyboard" android:label="@string/subtype_generic" android:imeSubtypeLocale="hr" android:imeSubtypeMode="keyboard" - android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection" + android:imeSubtypeExtraValue="AsciiCapable" /> <subtype android:icon="@drawable/ic_subtype_keyboard" android:label="@string/subtype_generic" android:imeSubtypeLocale="hu" android:imeSubtypeMode="keyboard" - android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection" + android:imeSubtypeExtraValue="AsciiCapable" + /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_generic" + android:imeSubtypeLocale="is" + android:imeSubtypeMode="keyboard" + android:imeSubtypeExtraValue="AsciiCapable" /> <subtype android:icon="@drawable/ic_subtype_keyboard" android:label="@string/subtype_generic" android:imeSubtypeLocale="it" android:imeSubtypeMode="keyboard" - android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection" + android:imeSubtypeExtraValue="AsciiCapable" /> <!-- Java uses the deprecated "iw" code instead of the standard "he" code for Hebrew. --> <subtype android:icon="@drawable/ic_subtype_keyboard" android:label="@string/subtype_generic" android:imeSubtypeLocale="iw" android:imeSubtypeMode="keyboard" - android:imeSubtypeExtraValue="SupportTouchPositionCorrection" + /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_generic" + android:imeSubtypeLocale="ka" + android:imeSubtypeMode="keyboard" + /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_generic" + android:imeSubtypeLocale="ky" + android:imeSubtypeMode="keyboard" + /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_generic" + android:imeSubtypeLocale="lt" + android:imeSubtypeMode="keyboard" + android:imeSubtypeExtraValue="AsciiCapable" + /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_generic" + android:imeSubtypeLocale="lv" + android:imeSubtypeMode="keyboard" + android:imeSubtypeExtraValue="AsciiCapable" + /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_generic" + android:imeSubtypeLocale="mk" + android:imeSubtypeMode="keyboard" /> <subtype android:icon="@drawable/ic_subtype_keyboard" android:label="@string/subtype_generic" android:imeSubtypeLocale="nb" android:imeSubtypeMode="keyboard" - android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection" + android:imeSubtypeExtraValue="AsciiCapable" /> <subtype android:icon="@drawable/ic_subtype_keyboard" android:label="@string/subtype_generic" android:imeSubtypeLocale="nl" android:imeSubtypeMode="keyboard" - android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection" + android:imeSubtypeExtraValue="AsciiCapable" /> <subtype android:icon="@drawable/ic_subtype_keyboard" android:label="@string/subtype_generic" android:imeSubtypeLocale="pl" android:imeSubtypeMode="keyboard" - android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection" + android:imeSubtypeExtraValue="AsciiCapable" /> <subtype android:icon="@drawable/ic_subtype_keyboard" android:label="@string/subtype_generic" android:imeSubtypeLocale="pt" android:imeSubtypeMode="keyboard" - android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection" + android:imeSubtypeExtraValue="AsciiCapable" + /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_generic" + android:imeSubtypeLocale="ro" + android:imeSubtypeMode="keyboard" + android:imeSubtypeExtraValue="AsciiCapable" /> <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" + /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_generic" + android:imeSubtypeLocale="sl" + android:imeSubtypeMode="keyboard" + android:imeSubtypeExtraValue="AsciiCapable" /> <subtype android:icon="@drawable/ic_subtype_keyboard" android:label="@string/subtype_generic" android:imeSubtypeLocale="sr" android:imeSubtypeMode="keyboard" - android:imeSubtypeExtraValue="SupportTouchPositionCorrection" /> <subtype android:icon="@drawable/ic_subtype_keyboard" android:label="@string/subtype_generic" android:imeSubtypeLocale="sv" android:imeSubtypeMode="keyboard" - android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection" + android:imeSubtypeExtraValue="AsciiCapable" /> <subtype android:icon="@drawable/ic_subtype_keyboard" android:label="@string/subtype_generic" android:imeSubtypeLocale="tr" android:imeSubtypeMode="keyboard" - android:imeSubtypeExtraValue="AsciiCapable,SupportTouchPositionCorrection" + android:imeSubtypeExtraValue="AsciiCapable" + /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_generic" + android:imeSubtypeLocale="th" + android:imeSubtypeMode="keyboard" + android:imeSubtypeExtraValue="" + /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_generic" + android:imeSubtypeLocale="uk" + android:imeSubtypeMode="keyboard" + /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_generic" + android:imeSubtypeLocale="vi" + android:imeSubtypeMode="keyboard" + android:imeSubtypeExtraValue="AsciiCapable" + /> + <subtype android:icon="@drawable/ic_subtype_keyboard" + android:label="@string/subtype_qwerty" + android:imeSubtypeLocale="zz_QY" + android:imeSubtypeMode="keyboard" + android:imeSubtypeExtraValue="AsciiCapable,EnabledWhenDefaultIsNotAsciiCapable" /> </input-method> diff --git a/java/res/xml/prefs.xml b/java/res/xml/prefs.xml index dcaa2029c..c5c647aac 100644 --- a/java/res/xml/prefs.xml +++ b/java/res/xml/prefs.xml @@ -21,9 +21,6 @@ <PreferenceCategory android:title="@string/general_category" android:key="general_settings"> - <PreferenceScreen - android:key="subtype_settings" - android:title="@string/language_selection_title" /> <CheckBoxPreference android:key="auto_cap" android:title="@string/auto_cap" @@ -44,11 +41,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 +89,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 +117,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 +135,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..ff0b06240 --- /dev/null +++ b/java/res/xml/rowkeys_azerty2.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" +> + <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" + latin:moreKeys="@string/more_keys_for_h" /> + <Key + latin:keyLabel="j" + latin:moreKeys="@string/more_keys_for_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/rowkeys_azerty3.xml b/java/res/xml/rowkeys_azerty3.xml new file mode 100644 index 000000000..b81c3c5a1 --- /dev/null +++ b/java/res/xml/rowkeys_azerty3.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="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" /> + <include + 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..04c6ef6ab --- /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_east_slavic_row1_9" + 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..57b037367 --- /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_east_slavic_row2_1" + latin:moreKeys="@string/more_keys_for_east_slavic_row2_1" /> + <!-- 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..b0f7aed7b --- /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_east_slavic_row3_5" /> + <!-- 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_farsi1.xml b/java/res/xml/rowkeys_farsi1.xml new file mode 100644 index 000000000..15cb80182 --- /dev/null +++ b/java/res/xml/rowkeys_farsi1.xml @@ -0,0 +1,90 @@ +<?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+0635: "ص" ARABIC LETTER SAD + U+06F1: "۱" EXTENDED ARABIC-INDIC DIGIT ONE --> + <Key + latin:keyLabel="ص" + latin:keyHintLabel="1" + latin:additionalMoreKeys="1,۱" /> + <!-- U+0642: "ق" ARABIC LETTER QAF + U+06F2: "۲" EXTENDED ARABIC-INDIC DIGIT TWO --> + <Key + latin:keyLabel="ق" + latin:keyHintLabel="2" + latin:additionalMoreKeys="2,۲" /> + <!-- U+0641: "ف" ARABIC LETTER FEH + U+06F3: "۳" EXTENDED ARABIC-INDIC DIGIT THREE --> + <Key + latin:keyLabel="ف" + latin:keyHintLabel="3" + latin:additionalMoreKeys="3,۳" /> + <!-- U+063A: "غ" ARABIC LETTER GHAIN + U+06F4: "۴" EXTENDED ARABIC-INDIC DIGIT FOUR --> + <Key + latin:keyLabel="غ" + latin:keyHintLabel="4" + latin:additionalMoreKeys="4,۴" /> + <!-- U+0639: "ع" ARABIC LETTER AIN + U+06F5: "۵" EXTENDED ARABIC-INDIC DIGIT FIVE --> + <Key + latin:keyLabel="ع" + latin:keyHintLabel="5" + latin:additionalMoreKeys="5,۵" /> + <!-- U+0647: "ه" ARABIC LETTER HEH + U+FEEB: "ﻫ" ARABIC LETTER HEH INITIAL FORM + U+0647/U+200D: ARABIC LETTER HEH + ZERO WIDTH JOINER + U+06C0: "ۀ" ARABIC LETTER HEH WITH YEH ABOVE + U+0629: "ة" ARABIC LETTER TEH MARBUTA + U+06F6: "۶" EXTENDED ARABIC-INDIC DIGIT SIX --> + <!-- TODO: DroidSansArabic lacks the glyph of U+06C0 ARABIC LETTER HEH WITH YEH ABOVE --> + <Key + latin:keyLabel="ه" + latin:moreKeys="ﻫ|ه‍,ۀ,ة,%" + latin:keyHintLabel="6" + latin:additionalMoreKeys="6,۶" /> + <!-- U+062E: "خ" ARABIC LETTER KHAH + U+06F7: "۷" EXTENDED ARABIC-INDIC DIGIT SEVEN --> + <Key + latin:keyLabel="خ" + latin:keyHintLabel="7" + latin:additionalMoreKeys="7,۷" /> + <!-- U+062D: "ح" ARABIC LETTER HAH + U+06F8: "۸" EXTENDED ARABIC-INDIC DIGIT EIGHT --> + <Key + latin:keyLabel="ح" + latin:keyHintLabel="8" + latin:additionalMoreKeys="8,۸" /> + <!-- U+062C: "ج" ARABIC LETTER JEEM + U+06F9: "۹" EXTENDED ARABIC-INDIC DIGIT NINE --> + <Key + latin:keyLabel="ج" + latin:keyHintLabel="9" + latin:additionalMoreKeys="9,۹" /> + <!-- U+0686: "چ" ARABIC LETTER TCHEH + U+06F0: "۰" EXTENDED ARABIC-INDIC DIGIT ZERO --> + <Key + latin:keyLabel="چ" + latin:keyHintLabel="0" + latin:additionalMoreKeys="0,۰" /> +</merge> diff --git a/java/res/xml/rowkeys_farsi2.xml b/java/res/xml/rowkeys_farsi2.xml new file mode 100644 index 000000000..77279c60f --- /dev/null +++ b/java/res/xml/rowkeys_farsi2.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+0634: "ش" ARABIC LETTER SHEEN --> + <Key + latin:keyLabel="ش" /> + <!-- U+0633: "س" ARABIC LETTER SEEN + U+0636: "ض" ARABIC LETTER DAD --> + <Key + latin:keyLabel="س" + latin:moreKeys="ض" /> + <!-- U+06CC: "ی" ARABIC LETTER FARSI YEH + U+0626: "ئ" ARABIC LETTER YEH WITH HAMZA ABOVE + U+064A: "ي" ARABIC LETTER YEH --> + <Key + latin:keyLabel="ی" + latin:moreKeys="ئ,ي" /> + <!-- U+0628: "ب" ARABIC LETTER BEH --> + <Key + latin:keyLabel="ب" /> + <!-- U+0644: "ل" ARABIC LETTER LAM --> + <Key + latin:keyLabel="ل" /> + <!-- U+0627: "ا" ARABIC LETTER ALEF + U+0621: "ء" ARABIC LETTER HAMZA + U+0622: "آ" ARABIC LETTER ALEF WITH MADDA ABOVE + U+0672: "ٲ" ARABIC LETTER ALEF WITH WAVY HAMZA ABOVE + U+0671: "ٱ" ARABIC LETTER ALEF WASLA + U+0673: "ٳ" ARABIC LETTER ALEF WITH WAVY HAMZA BELOW--> + <!-- TODO: DroidSansArabic lacks the glyph of U+0672 ARABIC LETTER ALEF WITH WAVY HAMZA ABOVE --> + <!-- TODO: DroidSansArabic lacks the glyph of U+0673 ARABIC LETTER ALEF WITH WAVY HAMZA BELOW --> + <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+06A9: "ک" ARABIC LETTER KEHEH + U+0643: "ك" ARABIC LETTER KAF --> + <Key + latin:keyLabel="ک" + latin:moreKeys="ك" /> +</merge> diff --git a/java/res/xml/rowkeys_farsi3.xml b/java/res/xml/rowkeys_farsi3.xml new file mode 100644 index 000000000..8db56e340 --- /dev/null +++ b/java/res/xml/rowkeys_farsi3.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+0637: "ط" ARABIC LETTER TAH + U+0638: "ظ" ARABIC LETTER ZAH --> + <Key + latin:keyLabel="ط" + latin:moreKeys="ظ" /> + <!-- U+0698: "ژ" ARABIC LETTER JEH --> + <Key + latin:keyLabel="ژ" /> + <!-- U+0632: "ز" ARABIC LETTER ZAIN --> + <Key + latin:keyLabel="ز" /> + <!-- U+0631: "ر" ARABIC LETTER REH --> + <Key + latin:keyLabel="ر" /> + <!-- U+062F: "د" ARABIC LETTER DAL + U+0630: "ذ" ARABIC LETTER THAL --> + <Key + latin:keyLabel="د" + latin:moreKeys="ذ" /> + <!-- U+067E: "پ" ARABIC LETTER PEH --> + <Key + latin:keyLabel="پ" /> + <!-- U+0648: "و" ARABIC LETTER WAW + U+0676: "ٶ" ARABIC LETTER HIGH HAMZA WAW --> + <!-- TODO: DroidSansArabic lacks the glyph of U+0676 ARABIC LETTER HIGH HAMZA WAW --> + <Key + latin:keyLabel="و" + latin:moreKeys="ٶ" /> + <!-- U+06AF: "گ" ARABIC LETTER GAF --> + <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..6b24c29fe --- /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|alphabetShiftLocked|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..f50e3d64b --- /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|alphabetShiftLocked|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..f908673af --- /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|alphabetShiftLocked|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_hindi1.xml b/java/res/xml/rowkeys_hindi1.xml new file mode 100644 index 000000000..eb99de96d --- /dev/null +++ b/java/res/xml/rowkeys_hindi1.xml @@ -0,0 +1,167 @@ +<?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|alphabetShiftLocked|alphabetShiftLockShifted" + > + <!-- U+0914: "औ" DEVANAGARI LETTER AU + U+0912/U+0902: "ऒं" DEVANAGARI LETTER SHORT O//DEVANAGARI SIGN ANUSVARA --> + <Key + latin:keyLabel="औ" + latin:moreKeys="ऒं" /> + <!-- U+0910: "ऐ" DEVANAGARI LETTER AI + U+0910/U+0902: "ऐं" DEVANAGARI LETTER AI/DEVANAGARI SIGN ANUSVARA --> + <Key + latin:keyLabel="ऐ" + latin:moreKeys="ऐं" /> + <!-- U+0906: "आ" DEVANAGARI LETTER AA + U+0906/U+0902: "आं" DEVANAGARI LETTER AA/DEVANAGARI SIGN ANUSVARA + U+0906/U+0901: "आँ" DEVANAGARI LETTER AA/DEVANAGARI SIGN CANDRABINDU --> + <Key + latin:keyLabel="आ" + latin:moreKeys="आं,आँ" /> + <!-- U+0908: "ई" DEVANAGARI LETTER II + U+0908/U+0902: "ईं" DEVANAGARI LETTER II/DEVANAGARI SIGN ANUSVARA --> + <Key + latin:keyLabel="ई" + latin:moreKeys="ईं" /> + <!-- U+090A: "ऊ" DEVANAGARI LETTER UU + U+090A/U+0902: "ऊं" DEVANAGARI LETTER UU/DEVANAGARI SIGN ANUSVARA + U+090A/U+0901: "ऊँ" DEVANAGARI LETTER UU/DEVANAGARI SIGN CANDRABINDU --> + <Key + latin:keyLabel="ऊ" + latin:moreKeys="ऊं,ऊँ" /> + <!-- U+092D: "भ" DEVANAGARI LETTER BHA --> + <Key + latin:keyLabel="भ" /> + <!-- U+0903: "ः" DEVANAGARI SIGN VISARGA --> + <Key + latin:keyLabel="ः" /> + <!-- U+0918: "घ" DEVANAGARI LETTER GHA --> + <Key + latin:keyLabel="घ" /> + <!-- U+0927: "ध" DEVANAGARI LETTER DHA + U+0915/U+094D/U+0937: "क्ष" DEVANAGARI LETTER KA/DEVANAGARI SIGN VIRAMA/DEVANAGARI LETTER SSA + U+0936/U+094D/U+0930: "श्र" DEVANAGARI LETTER SHA/DEVANAGARI SIGN VIRAMA/DEVANAGARI LETTER RA --> + <Key + latin:keyLabel="ध" + latin:moreKeys="क्ष,श्र" /> + <!-- U+091D: "झ" DEVANAGARI LETTER JHA --> + <Key + latin:keyLabel="झ" /> + <!-- U+0922: "ढ" DEVANAGARI LETTER DDHA --> + <Key + latin:keyLabel="ढ" /> + </case> + <default> + <!-- U+094C: "ौ" DEVANAGARI VOWEL SIGN AU + U+094C/U+0902: "ौं" DEVANAGARI VOWEL SIGN AU/DEVANAGARI SIGN ANUSVARA + U+0967: "१" DEVANAGARI DIGIT ONE --> + <Key + latin:keyLabel="ौ" + latin:moreKeys="ौं,%" + latin:keyHintLabel="1" + latin:additionalMoreKeys="१,1" /> + <!-- U+0948: "ै" DEVANAGARI VOWEL SIGN AI + U+0948/U+0902: "ैं" DEVANAGARI VOWEL SIGN AI/DEVANAGARI SIGN ANUSVARA + U+0968: "२" DEVANAGARI DIGIT TWO --> + <Key + latin:keyLabel="ै" + latin:moreKeys="ैं,%" + latin:keyHintLabel="2" + latin:additionalMoreKeys="२,2" /> + <!-- U+093E: "ा" DEVANAGARI VOWEL SIGN AA + U+093E/U+0902: "ां" DEVANAGARI VOWEL SIGN AA/DEVANAGARI SIGN ANUSVARA + U+093E/U+0901: "ाँ" DEVANAGARI VOWEL SIGN AA/DEVANAGARI SIGN CANDRABINDU + U+0969: "३" DEVANAGARI DIGIT THREE --> + <Key + latin:keyLabel="ा" + latin:moreKeys="ां,ाँ,%" + latin:keyHintLabel="3" + latin:additionalMoreKeys="३,3" /> + <!-- U+0940: "ी" DEVANAGARI VOWEL SIGN II + U+0940/U+0902: "ीं" DEVANAGARI VOWEL SIGN II/DEVANAGARI SIGN ANUSVARA + U+096A: "४" DEVANAGARI DIGIT FOUR --> + <Key + latin:keyLabel="ी" + latin:moreKeys="ीं,%" + latin:keyHintLabel="4" + latin:additionalMoreKeys="४,4" /> + <!-- U+0942: "ू" DEVANAGARI VOWEL SIGN UU + U+0942/U+0902: "ूं" DEVANAGARI VOWEL SIGN UU/DEVANAGARI SIGN ANUSVARA + U+0942/U+0901: "ूँ" DEVANAGARI VOWEL SIGN UU/DEVANAGARI SIGN CANDRABINDU + U+096B: "५" DEVANAGARI DIGIT FIVE --> + <Key + latin:keyLabel="ू" + latin:moreKeys="ूं,ूँ,%" + latin:keyHintLabel="5" + latin:additionalMoreKeys="५,5" /> + <!-- U+092C: "ब" DEVANAGARI LETTER BA + U+092C/U+0952: "ब॒" DEVANAGARI LETTER BA/DEVANAGARI STRESS SIGN ANUDATTA --> + <Key + latin:keyLabel="ब" + latin:moreKeys="ब॒,%" + latin:keyHintLabel="6" + latin:additionalMoreKeys="६,6" /> + <!-- U+0939: "ह" DEVANAGARI LETTER HA + U+096D: "७" DEVANAGARI DIGIT SEVEN --> + <Key + latin:keyLabel="ह" + latin:keyHintLabel="7" + latin:additionalMoreKeys="७,7" /> + <!-- U+0917: "ग" DEVANAGARI LETTER GA + U+091C/U+094D/U+091E: "ज्ञ" DEVANAGARI LETTER JA/DEVANAGARI SIGN VIRAMA/DEVANAGARI LETTER NYA + U+0917/U+093C: "ग़" DEVANAGARI LETTER GA/DEVANAGARI SIGN NUKTA + U+0917/U+0952: "ग॒" DEVANAGARI LETTER GA/DEVANAGARI STRESS SIGN ANUDATTA + U+096E: "८" DEVANAGARI DIGIT EIGHT --> + <Key + latin:keyLabel="ग" + latin:moreKeys="ज्ञ,ग़,ग॒,%" + latin:keyHintLabel="8" + latin:additionalMoreKeys="८,8" /> + <!-- U+0926: "द" DEVANAGARI LETTER DA + U+096F: "९" DEVANAGARI DIGIT NINE --> + <Key + latin:keyLabel="द" + latin:keyHintLabel="9" + latin:additionalMoreKeys="9" /> + <!-- U+091C: "ज" DEVANAGARI LETTER JA + U+091C/U+0952: "ज॒" DEVANAGARI LETTER JA/DEVANAGARI STRESS SIGN ANUDATTA + U+091C/U+094D/U+091E: "ज्ञ" DEVANAGARI LETTER JA/DEVANAGARI SIGN VIRAMA/DEVANAGARI LETTER NYA + U+091C/U+093C: "ज़" DEVANAGARI LETTER JA/DEVANAGARI SIGN NUKTA + U+0966: "०" DEVANAGARI DIGIT ZERO --> + <Key + latin:keyLabel="ज" + latin:moreKeys="ज॒,ज्ञ,ज़,%" + latin:keyHintLabel="0" + latin:additionalMoreKeys="०,0" /> + <!-- U+0921: "ड" DEVANAGARI LETTER DDA + U+0921/U+0952: "ड॒" DEVANAGARI LETTER DDA/DEVANAGARI STRESS SIGN ANUDATTA + U+0921/U+093C: "ड़" DEVANAGARI LETTER DDA/DEVANAGARI SIGN NUKTA --> + <Key + latin:keyLabel="ड" + latin:moreKeys="ड॒,ड़" /> + </default> + </switch> +</merge> diff --git a/java/res/xml/rowkeys_hindi2.xml b/java/res/xml/rowkeys_hindi2.xml new file mode 100644 index 000000000..95f488102 --- /dev/null +++ b/java/res/xml/rowkeys_hindi2.xml @@ -0,0 +1,142 @@ +<?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|alphabetShiftLocked|alphabetShiftLockShifted" + > + <!-- U+0913: "ओ" DEVANAGARI LETTER O + U+0913/U+0902: "ओं" DEVANAGARI LETTER O/DEVANAGARI SIGN ANUSVARA + U+0911: "ऑ" DEVANAGARI LETTER CANDRA O + U+0912: "ऒ" DEVANAGARI LETTER SHORT O --> + <Key + latin:keyLabel="ओ" + latin:moreKeys="ओं,ऑ,ऒ" /> + <!-- U+090F: "ए" DEVANAGARI LETTER E + U+090F/U+0902: "एं" DEVANAGARI LETTER E/DEVANAGARI SIGN ANUSVARA + U+090F/U+0901: "एँ" DEVANAGARI LETTER E/DEVANAGARI SIGN CANDRABINDU + U+090D: "ऍ" DEVANAGARI LETTER CANDRA E + U+090E: "ऎ" DEVANAGARI LETTER SHORT E --> + <Key + latin:keyLabel="ए" + latin:moreKeys="एं,एँ,ऍ,ऎ" /> + <!-- U+0905: "अ" DEVANAGARI LETTER A + U+0905/U+0902: "अं" DEVANAGARI LETTER A/DEVANAGARI SIGN ANUSVARA + U+0905/U+0901: "अँ" DEVANAGARI LETTER A/DEVANAGARI SIGN CANDRABINDU --> + <Key + latin:keyLabel="अ" + latin:moreKeys="अं,अँ" /> + <!-- U+0907: "इ" DEVANAGARI LETTER I + U+0907/U+0902: "इं" DEVANAGARI LETTER I/DEVANAGARI SIGN ANUSVARA + U+0907/U+0901: "इं" DEVANAGARI LETTER I/DEVANAGARI SIGN CANDRABINDU --> + <Key + latin:keyLabel="इ" + latin:moreKeys="इं,इँ" /> + <!-- U+0909: "उ" DEVANAGARI LETTER U + U+0909/U+0902: "उं" DEVANAGARI LETTER U/DEVANAGARI SIGN ANUSVARA + U+0909/U+0901: "उँ" DEVANAGARI LETTER U/DEVANAGARI SIGN CANDRABINDU --> + <Key + latin:keyLabel="उ" + latin:moreKeys="उं,उँ" /> + <!-- U+092B: "फ" DEVANAGARI LETTER PHA + U+092B/U+093C: "फ़" DEVANAGARI LETTER PHA/DEVANAGARI SIGN NUKTA --> + <Key + latin:keyLabel="फ" + latin:moreKeys="फ़" /> + <!-- U+0931: "ऱ" DEVANAGARI LETTER RRA + U+094D/U+0930: "्र" DEVANAGARI SIGN VIRAMA/DEVANAGARI LETTER RA + U+0930/U+094D: "र्" DEVANAGARI LETTER RA/DEVANAGARI SIGN VIRAMA --> + <Key + latin:keyLabel="ऱ" + latin:moreKeys="्र,र्" /> + <!-- U+0916: "ख" DEVANAGARI LETTER KHA + U+0916/U+093C: "ख़" DEVANAGARI LETTER KHA/DEVANAGARI SIGN NUKTA --> + <Key + latin:keyLabel="ख" + latin:moreKeys="ख़" /> + <!-- U+0925: "थ" DEVANAGARI LETTER THA --> + <Key + latin:keyLabel="थ" /> + <!-- U+091B: "छ" DEVANAGARI LETTER CHA --> + <Key + latin:keyLabel="छ" /> + <!-- U+0920: "ठ" DEVANAGARI LETTER TTHA --> + <Key + latin:keyLabel="ठ" /> + </case> + <default> + <!-- U+094B: "ो" DEVANAGARI VOWEL SIGN O + U+094B/U+0902: "қं" DEVANAGARI VOWEL SIGN O/DEVANAGARI SIGN ANUSVARA + U+0949: "ॉ" DEVANAGARI VOWEL SIGN CANDRA O + U+094A: "ॊ" DEVANAGARI VOWEL SIGN SHORT O --> + <Key + latin:keyLabel="ो" + latin:moreKeys="ों,ॉ,ॊ" /> + <!-- U+0947: "े" DEVANAGARI VOWEL SIGN E + U+0947/U+0902: "ें" DEVANAGARI VOWEL SIGN E/DEVANAGARI SIGN ANUSVARA --> + <Key + latin:keyLabel="े" + latin:moreKeys="ें" /> + <!-- U+094D: "्" DEVANAGARI SIGN VIRAMA --> + <Key + latin:keyLabel="्" /> + <!-- U+093F: "ि" DEVANAGARI VOWEL SIGN I + U+093F/U+0902: "िं" DEVANAGARI VOWEL SIGN I/DEVANAGARI SIGN ANUSVARA --> + <Key + latin:keyLabel="ि" + latin:moreKeys="िं" /> + <!-- U+0941: "ु" DEVANAGARI VOWEL SIGN U + U+0941/U+0902: "ुं" DEVANAGARI VOWEL SIGN U/DEVANAGARI SIGN ANUSVARA + U+0941/U+0901: "ुँ" DEVANAGARI VOWEL SIGN U/DEVANAGARI SIGN CANDRABINDU --> + <Key + latin:keyLabel="ु" + latin:moreKeys="ुं,ुँ" /> + <!-- U+092A: "प" DEVANAGARI LETTER PA --> + <Key + latin:keyLabel="प" /> + <!-- U+0930: "र" DEVANAGARI LETTER RA + U+090B: "ऋ" DEVANAGARI LETTER VOCALIC R + U+0930/U+093C: "ऱ" DEVANAGARI LETTER RA/DEVANAGARI SIGN NUKTA + U+0960: "ॠ" DEVANAGARI LETTER VOCALIC RR --> + <Key + latin:keyLabel="र" + latin:moreKeys="ऋ,ऱ,ॠ" /> + <!-- U+0915: "क" DEVANAGARI LETTER KA + U+0915/U+093C: "क़" DEVANAGARI LETTER KA/DEVANAGARI SIGN NUKTA --> + <Key + latin:keyLabel="क" + latin:moreKeys="क़" /> + <!-- U+0924: "त" DEVANAGARI LETTER TA + U+0924/U+094D/U+0930: "त्र" DEVANAGARI LETTER TA/DEVANAGARI SIGN VIRAMA/DEVANAGARI LETTER RA --> + <Key + latin:keyLabel="त" + latin:moreKeys="त्र" /> + <!-- U+091A: "च" DEVANAGARI LETTER CA --> + <Key + latin:keyLabel="च" /> + <!-- U+091F: "ट" DEVANAGARI LETTER TTA --> + <Key + latin:keyLabel="ट" /> + </default> + </switch> +</merge> diff --git a/java/res/xml/rowkeys_hindi3.xml b/java/res/xml/rowkeys_hindi3.xml new file mode 100644 index 000000000..c023115ee --- /dev/null +++ b/java/res/xml/rowkeys_hindi3.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|alphabetShiftLocked|alphabetShiftLockShifted" + > + <!-- U+0911: "ऑ" DEVANAGARI LETTER CANDRA O --> + <Key + latin:keyLabel="ऑ" /> + <!-- U+0901: "ँ" DEVANAGARI SIGN CANDRABINDU + U+0945: "ॅ" DEVANAGARI VOWEL SIGN CANDRA E--> + <Key + latin:keyLabel="ँ" + latin:moreKeys="ॅ" /> + <!-- U+0923: "ण" DEVANAGARI LETTER NNA --> + <Key + latin:keyLabel="ण" /> + <!-- U+0929: "ऩ" DEVANAGARI LETTER NNNA --> + <Key + latin:keyLabel="ऩ" /> + <!-- U+0933: "ळ" DEVANAGARI LETTER LLA + U+0934: "ऴ" DEVANAGARI LETTER LLLA --> + <Key + latin:keyLabel="ळ" + latin:moreKeys="ऴ" /> + <!-- U+0936: "श" DEVANAGARI LETTER SHA --> + <Key + latin:keyLabel="श" /> + <!-- U+0937: "ष" DEVANAGARI LETTER SSA --> + <Key + latin:keyLabel="ष" /> + <!-- U+0943: "ृ" DEVANAGARI VOWEL SIGN VOCALIC R + U+0944: "ॄ" DEVANAGARI VOWEL SIGN VOCALIC RR --> + <Key + latin:keyLabel="ृ" + latin:moreKeys="ॄ" /> + <!-- U+091E: "ञ" DEVANAGARI LETTER NYA --> + <Key + latin:keyLabel="ञ" /> + </case> + <default> + <!-- U+0949: "ॉ" DEVANAGARI VOWEL SIGN CANDRA O --> + <Key + latin:keyLabel="ॉ" /> + <!-- U+0902: "ं" DEVANAGARI SIGN ANUSVARA --> + <Key + latin:keyLabel="ं" /> + <!-- U+092E: "म" DEVANAGARI LETTER MA + U+0950: "ॐ" DEVANAGARI OM --> + <Key + latin:keyLabel="म" + latin:moreKeys="ॐ" /> + <!-- U+0928: "न" DEVANAGARI LETTER NA + U+091E: "ञ" DEVANAGARI LETTER NYA + U+0919: "ङ" DEVANAGARI LETTER NGA + U+0928/U+093C: "ऩ" DEVANAGARI LETTER NA/DEVANAGARI SIGN NUKTA --> + <Key + latin:keyLabel="न" + latin:moreKeys="ञ,ङ,ऩ" /> + <!-- U+0935: "व" DEVANAGARI LETTER VA --> + <Key + latin:keyLabel="व" /> + <!-- U+0932: "ल" DEVANAGARI LETTER LA + U+090C: "ऌ" DEVANAGARI LETTER VOCALIC L + U+0961: "ॡ" DEVANAGARI LETTER VOCALIC LL --> + <Key + latin:keyLabel="ल" + latin:moreKeys="ऌ,ॡ" /> + <!-- U+0938: "स" DEVANAGARI LETTER SA --> + <Key + latin:keyLabel="स" /> + <!-- U+092F: "य" DEVANAGARI LETTER YA + U+095F: "य़" DEVANAGARI LETTER YYA --> + <Key + latin:keyLabel="य" + latin:moreKeys="य़" /> + <!-- U+093C: "़" DEVANAGARI SIGN NUKTA + U+097D: "ॽ" DEVANAGARI LETTER GLOTTAL STOP + U+0970: "॰" DEVANAGARI ABBREVIATION SIGN + U+093D: "ऽ" DEVANAGARI SIGN AVAGRAHA --> + <Key + latin:keyLabel="़" + latin:moreKeys="ॽ,॰,ऽ" /> + </default> + </switch> +</merge> diff --git a/java/res/xml/rowkeys_nordic1.xml b/java/res/xml/rowkeys_nordic1.xml new file mode 100644 index 000000000..056895f1f --- /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_nordic_row1_11" /> +</merge> diff --git a/java/res/xml-sw600dp/kbd_rows_qwerty.xml b/java/res/xml/rowkeys_nordic2.xml index a2d26b3de..0033ea1bb 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_nordic_row2_10" + latin:moreKeys="@string/more_keys_for_nordic_row2_10" /> + <Key + latin:keyLabel="@string/keylabel_for_nordic_row2_11" + latin:moreKeys="@string/more_keys_for_nordic_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..19067a70c --- /dev/null +++ b/java/res/xml/rowkeys_qwerty1.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" +> + <Key + latin:keyLabel="q" + latin:keyHintLabel="1" + latin:additionalMoreKeys="1" /> + <Key + latin:keyLabel="w" + latin:keyHintLabel="2" + latin:additionalMoreKeys="2" + latin:moreKeys="@string/more_keys_for_w" /> + <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..2fa8214a8 --- /dev/null +++ b/java/res/xml/rowkeys_qwerty2.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: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" + latin:moreKeys="@string/more_keys_for_h" /> + <Key + latin:keyLabel="j" + latin:moreKeys="@string/more_keys_for_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/kbd_rows_qwerty.xml b/java/res/xml/rowkeys_qwerty3.xml index 6237712f6..932ea6f65 100644 --- a/java/res/xml/kbd_rows_qwerty.xml +++ b/java/res/xml/rowkeys_qwerty3.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,22 @@ <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="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..3e11a7ab4 --- /dev/null +++ b/java/res/xml/rowkeys_qwertz1.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" +> + <Key + latin:keyLabel="q" + latin:keyHintLabel="1" + latin:additionalMoreKeys="1" /> + <Key + latin:keyLabel="w" + latin:keyHintLabel="2" + latin:additionalMoreKeys="2" + latin:moreKeys="@string/more_keys_for_w" /> + <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..e3cb89c67 --- /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_south_slavic_row1_6" + 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..5a7ecd46e --- /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_south_slavic_row2_11" /> +</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..97ff51ee1 --- /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_south_slavic_row3_1" /> + <!-- 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_south_slavic_row3_8" /> + <!-- 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/rowkeys_thai1.xml b/java/res/xml/rowkeys_thai1.xml new file mode 100644 index 000000000..943112a1a --- /dev/null +++ b/java/res/xml/rowkeys_thai1.xml @@ -0,0 +1,124 @@ +<?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|alphabetShiftLocked|alphabetShiftLockShifted" + > + <!-- U+0E0E: "ฎ" THAI CHARACTER DO CHADA --> + <Key + latin:keyLabel="ฎ" /> + <!-- U+0E11: "ฑ" THAI CHARACTER THO NANGMONTHO --> + <Key + latin:keyLabel="ฑ" /> + <!-- U+0E18: "ธ" THAI CHARACTER THO THONG --> + <Key + latin:keyLabel="ธ" /> + <!-- U+0E13: "ณ" THAI CHARACTER NO NEN --> + <Key + latin:keyLabel="ณ" /> + <!-- U+0E0D: "ญ" THAI CHARACTER YO YING --> + <Key + latin:keyLabel="ญ" /> + <!-- U+0E10: "ฐ" THAI CHARACTER THO THAN --> + <Key + latin:keyLabel="ฐ" /> + <!-- U+0E03: "ฃ" THAI CHARACTER KHO KHUAT --> + <Key + latin:keyLabel="ฃ" /> + <!-- U+0E05: "ฅ" THAI CHARACTER KHO KHON --> + <Key + latin:keyLabel="ฅ" /> + <!-- U+0E51: "๑" THAI DIGIT ONE + U+0E52: "๒" THAI DIGIT TWO + U+0E53: "๓" THAI DIGIT THREE + U+0E54: "๔" THAI DIGIT FOUR + U+0E55: "๕" THAI DIGIT FIVE --> + <Key + latin:keyLabel="๑" + latin:moreKeys="!fixedColumnOrder!4,๒,๓,๔,๕" /> + <!-- U+0E56: "๖" THAI DIGIT SIX + U+0E57: "๗" THAI DIGIT SEVEN + U+0E58: "๘" THAI DIGIT EIGHT + U+0E59: "๙" THAI DIGIT NINE + U+0E50: "๐" THAI DIGIT ZERO --> + <Key + latin:keyLabel="๖" + latin:moreKeys="!fixedColumnOrder!4,๗,๘,๙,๐" /> + </case> + <default> + <!-- U+0E20: "ภ" THAI CHARACTER PHO SAMPHAO --> + <Key + latin:keyLabel="ภ" + latin:keyHintLabel="1" + latin:additionalMoreKeys="1,๑" /> + <!-- U+0E16: "ถ" THAI CHARACTER THO THUNG --> + <Key + latin:keyLabel="ถ" + latin:keyHintLabel="2" + latin:additionalMoreKeys="2,๒" /> + <!-- U+0E04: "ค" THAI CHARACTER KHO KHWAI --> + <Key + latin:keyLabel="ค" + latin:keyHintLabel="3" + latin:additionalMoreKeys="3,๓" /> + <!-- U+0E15: "ต" THAI CHARACTER TO TAO --> + <Key + latin:keyLabel="ต" + latin:keyHintLabel="4" + latin:additionalMoreKeys="4,๔" /> + <!-- U+0E08: "จ" THAI CHARACTER CHO CHAN --> + <Key + latin:keyLabel="จ" + latin:keyHintLabel="5" + latin:additionalMoreKeys="5,๕" /> + <!-- U+0E02: "ข" THAI CHARACTER KHO KHAI --> + <Key + latin:keyLabel="ข" + latin:keyHintLabel="6" + latin:additionalMoreKeys="6,๖" /> + <!-- U+0E0A: "ช" THAI CHARACTER CHO CHANG --> + <Key + latin:keyLabel="ช" + latin:keyHintLabel="7" + latin:additionalMoreKeys="7,๗" /> + <!-- U+0E23: "ร" THAI CHARACTER RO RUA + U+0E25: "ล" THAI CHARACTER LO LING --> + <Key + latin:keyLabel="ร" + latin:moreKeys="ล" + latin:keyHintLabel="8" + latin:additionalMoreKeys="8,๘" /> + <!-- U+0E19: "น" THAI CHARACTER NO NU --> + <Key + latin:keyLabel="น" + latin:keyHintLabel="9" + latin:additionalMoreKeys="9,๙" /> + <!-- U+0E22: "ย" THAI CHARACTER YO YAK --> + <Key + latin:keyLabel="ย" + latin:keyHintLabel="0" + latin:additionalMoreKeys="0,๐" /> + </default> + </switch> +</merge> diff --git a/java/res/xml/rowkeys_thai2.xml b/java/res/xml/rowkeys_thai2.xml new file mode 100644 index 000000000..02ea6c5f8 --- /dev/null +++ b/java/res/xml/rowkeys_thai2.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|alphabetShiftLocked|alphabetShiftLockShifted" + > + <!-- U+0E24: "ฤ" THAI CHARACTER RU --> + <Key + latin:keyLabel="ฤ" /> + <!-- U+0E06: "ฆ" THAI CHARACTER KHO RAKHANG --> + <Key + latin:keyLabel="ฆ" /> + <!-- U+0E0F: "ฏ" THAI CHARACTER TO PATAK --> + <Key + latin:keyLabel="ฏ" /> + <!-- U+0E0C: "ฌ" THAI CHARACTER CHO CHOE --> + <Key + latin:keyLabel="ฌ" /> + <!-- U+0E29: "ษ" THAI CHARACTER SO RUSI --> + <Key + latin:keyLabel="ษ" /> + <!-- U+0E28: "ศ" THAI CHARACTER SO SALA --> + <Key + latin:keyLabel="ศ" /> + <!-- U+0E0B: "ซ" THAI CHARACTER SO SO --> + <Key + latin:keyLabel="ซ" /> + <!-- U+0E3F: "฿" THAI CURRENCY SYMBOL BAHT + U+0E45: "ๅ" THAI CHARACTER LAKKHANGYAO --> + <Key + latin:keyLabel="฿" + latin:moreKeys="ๅ" /> + <!-- U+0E46: "ๆ" THAI CHARACTER MAIYAMOK + U+0E2F: "ฯ" THAI CHARACTER PAIYANNOI --> + <Key + latin:keyLabel="ๆ" + latin:moreKeys="ฯ" /> + </case> + <default> + <!-- U+0E1F: "ฟ" THAI CHARACTER FO FAN + U+0E1E: "พ" THAI CHARACTER PHO PHAN --> + <Key + latin:keyLabel="ฟ" + latin:moreKeys="พ" /> + <!-- U+0E2B: "ห" THAI CHARACTER HO HIP --> + <Key + latin:keyLabel="ห" /> + <!-- U+0E01: "ก" THAI CHARACTER KO KAI --> + <Key + latin:keyLabel="ก" /> + <!-- U+0E14: "ด" THAI CHARACTER DO DEK --> + <Key + latin:keyLabel="ด" /> + <!-- U+0E2A: "ส" THAI CHARACTER SO SUA --> + <Key + latin:keyLabel="ส" /> + <!-- U+0E27: "ว" THAI CHARACTER WO WAEN --> + <Key + latin:keyLabel="ว" /> + <!-- U+0E07: "ง" THAI CHARACTER NGO NGU --> + <Key + latin:keyLabel="ง" /> + <!-- U+0E30: "ะ" THAI CHARACTER SARA A + U+0E32: "า" THAI CHARACTER SARA AA + U+0E33: " ำ" THAI CHARACTER SARA AM + U+0E40: "เ" THAI CHARACTER SARA E + U+0E41: "แ" THAI CHARACTER SARA AE + U+0E43: "ใ" THAI CHARACTER SARA AI MAIMUAN + U+0E44: "ไ" THAI CHARACTER SARA AI MAIMALAI + U+0E42: "โ" THAI CHARACTER SARA O --> + <Key + latin:keyLabel="ะ" + latin:moreKeys="า,ำ,เ,แ,ใ,ไ,โ" /> + <!-- U+0E31: " ั" THAI CHARACTER MAI HAN-AKAT + U+0E34: " ิ" THAI CHARACTER SARA I + U+0E35: " ี" THAI CHARACTER SARA II + U+0E36: " ึ" THAI CHARACTER SARA UE + U+0E37: " ื" THAI CHARACTER SARA UEE + U+0E38: " ุ" THAI CHARACTER SARA U + U+0E39: " ู" THAI CHARACTER SARA UU --> + <Key + latin:keyLabel="ั" + latin:moreKeys="ิ,ี,ึ,ื,ุ,ู" /> + </default> + </switch> +</merge> diff --git a/java/res/xml/rowkeys_thai3.xml b/java/res/xml/rowkeys_thai3.xml new file mode 100644 index 000000000..72c0deffe --- /dev/null +++ b/java/res/xml/rowkeys_thai3.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" +> + <switch> + <case + latin:keyboardSetElement="alphabetManualShifted|alphabetShiftLocked|alphabetShiftLockShifted" + > + <!-- U+0E09: "ฉ" THAI CHARACTER CHO CHING --> + <Key + latin:keyLabel="ฉ" /> + <!-- U+0E2E: "ฮ" THAI CHARACTER HO NOKHUK --> + <Key + latin:keyLabel="ฮ" /> + <!-- U+0E12: "ฒ" THAI CHARACTER THO PHUTHAO --> + <Key + latin:keyLabel="ฒ" /> + <!-- U+0E2C: "ฬ" THAI CHARACTER LO CHULA --> + <Key + latin:keyLabel="ฬ" /> + <!-- U+0E26: "ฦ" THAI CHARACTER LU --> + <Key + latin:keyLabel="ฦ" /> + <!-- U+0E4C: " ์" THAI CHARACTER THANTHAKHAT + U+0E4D: " ํ" THAI CHARACTER NIKHAHIT + U+0E3A: " ฺ" THAI CHARACTER PHINTHU --> + <Key + latin:keyLabel="์" + latin:moreKeys="ํ,ฺ" /> + <!-- U+0E47: " ็" THAI CHARACTER MAITAIKHU --> + <Key + latin:keyLabel="็" /> + </case> + <default> + <!-- U+0E1C: "ผ" THAI CHARACTER PHO PHUNG --> + <Key + latin:keyLabel="ผ" /> + <!-- U+0E1B: "ป" THAI CHARACTER PO PLA + U+0E1A: "บ" THAI CHARACTER BO BAIMAI --> + <Key + latin:keyLabel="ป" + latin:moreKeys="บ" /> + <!-- U+0E2D: "อ" THAI CHARACTER O ANG --> + <Key + latin:keyLabel="อ" /> + <!-- U+0E17: "ท" THAI CHARACTER THO THAHAN --> + <Key + latin:keyLabel="ท" /> + <!-- U+0E21: "ม" THAI CHARACTER MO MA --> + <Key + latin:keyLabel="ม" /> + <!-- U+0E1D: "ฝ" THAI CHARACTER FO FA --> + <Key + latin:keyLabel="ฝ" /> + <!-- U+0E48: " ่" THAI CHARACTER MAI EK + U+0E49: " ้" THAI CHARACTER MAI THO + U+0E4A: " ๊" THAI CHARACTER MAI TRI + U+0E4B: " ๋" THAI CHARACTER MAI CHATTAWA --> + <Key + latin:keyLabel="่" + latin:moreKeys="้,๊,๋" /> + </default> + </switch> +</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..5d3d768f3 --- /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.711%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="10.8%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_farsi.xml b/java/res/xml/rows_farsi.xml new file mode 100644 index 000000000..cc0c526b3 --- /dev/null +++ b/java/res/xml/rows_farsi.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" +> + <include + latin:keyboardLayout="@xml/key_styles_common" /> + <Row + latin:keyWidth="10%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_farsi1" /> + </Row> + <Row + latin:keyWidth="10%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_farsi2" /> + </Row> + <Row + latin:keyWidth="10%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_farsi3" + 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/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/rows_hindi.xml b/java/res/xml/rows_hindi.xml new file mode 100644 index 000000000..5c631ebff --- /dev/null +++ b/java/res/xml/rows_hindi.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_hindi1" /> + </Row> + <Row + latin:keyWidth="9.091%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_hindi2" /> + </Row> + <Row + latin:keyWidth="8.711%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="10.8%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_hindi3" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyWidth="fillRight" /> + </Row> + <include + latin:keyboardLayout="@xml/row_qwerty4" /> +</merge> diff --git a/java/res/xml/rows_nordic.xml b/java/res/xml/rows_nordic.xml new file mode 100644 index 000000000..3068917f5 --- /dev/null +++ b/java/res/xml/rows_nordic.xml @@ -0,0 +1,57 @@ +<?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="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="9.2%p" + > + <Key + latin:keyStyle="shiftKeyStyle" + latin:keyWidth="15%p" + latin:visualInsetsRight="1%p" /> + <Spacer + latin:keyWidth="2.8%p" /> + <include + latin:keyboardLayout="@xml/rowkeys_qwerty3" /> + <Key + latin:keyStyle="deleteKeyStyle" + latin:keyXPos="-15%p" + latin:keyWidth="fillRight" + 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_row3.xml b/java/res/xml/rows_qwerty.xml index c2b45e752..716d10642 100644 --- a/java/res/xml/kbd_qwerty_row3.xml +++ b/java/res/xml/rows_qwerty.xml @@ -21,6 +21,21 @@ <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_qwerty2" + latin:keyXPos="5%p" /> + </Row> <Row latin:keyWidth="10%p" > @@ -28,27 +43,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/kbd_qwerty_row2.xml b/java/res/xml/rows_qwertz.xml index 8986780b7..31a147c12 100644 --- a/java/res/xml/kbd_qwerty_row2.xml +++ b/java/res/xml/rows_qwertz.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_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: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_qwertz3" /> <Key - latin:keyLabel="l" - latin:moreKeys="@string/more_keys_for_l" /> - <!-- Here is 5%p space --> + 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..05442848d 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.711%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="10.8%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/rows_thai.xml b/java/res/xml/rows_thai.xml new file mode 100644 index 000000000..6b80df640 --- /dev/null +++ b/java/res/xml/rows_thai.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_thai1" /> + </Row> + <Row + latin:keyWidth="10%p" + > + <include + latin:keyboardLayout="@xml/rowkeys_thai2" + 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_thai3" /> + <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/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..667b109cb 100644 --- a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java +++ b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java @@ -17,7 +17,6 @@ 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; @@ -28,11 +27,9 @@ 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.AudioManagerCompatWrapper; -import com.android.inputmethod.compat.InputTypeCompatUtils; -import com.android.inputmethod.compat.MotionEventCompatUtils; import com.android.inputmethod.compat.SettingsSecureCompatUtils; +import com.android.inputmethod.latin.InputTypeUtils; import com.android.inputmethod.latin.R; public class AccessibilityUtils { @@ -45,7 +42,6 @@ public class AccessibilityUtils { private Context mContext; private AccessibilityManager mAccessibilityManager; - private AccessibilityManagerCompatWrapper mCompatManager; private AudioManagerCompatWrapper mAudioManager; /* @@ -55,15 +51,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 +70,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 +90,7 @@ public class AccessibilityUtils { public boolean isTouchExplorationEnabled() { return ENABLE_ACCESSIBILITY && mAccessibilityManager.isEnabled() - && mCompatManager.isTouchExplorationEnabled(); + && mAccessibilityManager.isTouchExplorationEnabled(); } /** @@ -109,19 +104,19 @@ public class AccessibilityUtils { public boolean isTouchExplorationEvent(MotionEvent event) { final int action = event.getAction(); - return action == MotionEventCompatUtils.ACTION_HOVER_ENTER - || action == MotionEventCompatUtils.ACTION_HOVER_EXIT - || action == MotionEventCompatUtils.ACTION_HOVER_MOVE; + return action == MotionEvent.ACTION_HOVER_ENTER + || action == MotionEvent.ACTION_HOVER_EXIT + || action == MotionEvent.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 +132,7 @@ public class AccessibilityUtils { return false; // Don't speak if the IME is connected to a password field. - return InputTypeCompatUtils.isPasswordInputType(attribute.inputType); + return InputTypeUtils.isPasswordInputType(editorInfo.inputType); } /** @@ -171,11 +166,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..c85a5514e 100644 --- a/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java +++ b/java/src/com/android/inputmethod/accessibility/AccessibleKeyboardViewProxy.java @@ -17,35 +17,36 @@ 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.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.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 +54,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 +69,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 +124,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 MotionEvent.ACTION_HOVER_ENTER: + case MotionEvent.ACTION_HOVER_EXIT: + return onHoverKey(key, event); + case MotionEvent.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(MotionEvent.ACTION_HOVER_EXIT); + onHoverKey(previousKey, event); - if (keyIndex == KeyDetector.NOT_A_KEY) - return; + event.setAction(MotionEvent.ACTION_HOVER_ENTER); + onHoverKey(currentKey, event); - final Key key = tracker.getKey(keyIndex); + event.setAction(MotionEvent.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 MotionEvent.ACTION_HOVER_ENTER: + sendAccessibilityEventForKey(key, AccessibilityEventCompat.TYPE_VIEW_HOVER_ENTER); + break; + case MotionEvent.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. + mView.getParent().requestSendAccessibilityEvent(mView, event); } private class KeyboardFlickGestureDetector extends FlickGestureDetector { @@ -185,4 +227,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..e8ec37600 100644 --- a/java/src/com/android/inputmethod/accessibility/FlickGestureDetector.java +++ b/java/src/com/android/inputmethod/accessibility/FlickGestureDetector.java @@ -21,7 +21,6 @@ import android.os.Message; import android.view.MotionEvent; import android.view.ViewConfiguration; -import com.android.inputmethod.compat.MotionEventCompatUtils; import com.android.inputmethod.keyboard.PointerTracker; import com.android.inputmethod.latin.StaticInnerHandlerWrapper; @@ -31,10 +30,10 @@ import com.android.inputmethod.latin.StaticInnerHandlerWrapper; * A flick gesture is defined as a stream of hover events with the following * properties: * <ul> - * <li>Begins with a {@link MotionEventCompatUtils#ACTION_HOVER_ENTER} event - * <li>Contains any number of {@link MotionEventCompatUtils#ACTION_HOVER_MOVE} + * <li>Begins with a {@link MotionEvent#ACTION_HOVER_ENTER} event + * <li>Contains any number of {@link MotionEvent#ACTION_HOVER_MOVE} * events - * <li>Ends with a {@link MotionEventCompatUtils#ACTION_HOVER_EXIT} event + * <li>Ends with a {@link MotionEvent#ACTION_HOVER_EXIT} event * <li>Maximum duration of 250 milliseconds * <li>Minimum distance between enter and exit points must be at least equal to * scaled double tap slop (see @@ -112,7 +111,7 @@ public abstract class FlickGestureDetector { public boolean onHoverEvent(MotionEvent event, AccessibleKeyboardViewProxy view, PointerTracker tracker) { // Always cache and consume the first hover event. - if (event.getAction() == MotionEventCompatUtils.ACTION_HOVER_ENTER) { + if (event.getAction() == MotionEvent.ACTION_HOVER_ENTER) { mCachedView = view; mCachedTracker = tracker; mCachedHoverEnter = MotionEvent.obtain(event); @@ -126,13 +125,12 @@ 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 MotionEvent.ACTION_HOVER_MOVE: // Consume all valid move events before timeout. return true; - case MotionEventCompatUtils.ACTION_HOVER_EXIT: + case MotionEvent.ACTION_HOVER_EXIT: // Ignore exit events outside the flick radius. if (distanceSquare < mFlickRadiusSquare) { clearFlick(true); @@ -171,10 +169,8 @@ public abstract class FlickGestureDetector { * Computes the direction of a flick gesture and forwards it to * {@link #onFlick(MotionEvent, MotionEvent, int)} for handling. * - * @param e1 The {@link MotionEventCompatUtils#ACTION_HOVER_ENTER} event - * where the flick started. - * @param e2 The {@link MotionEventCompatUtils#ACTION_HOVER_EXIT} event - * where the flick ended. + * @param e1 The {@link MotionEvent#ACTION_HOVER_ENTER} event where the flick started. + * @param e2 The {@link MotionEvent#ACTION_HOVER_EXIT} event where the flick ended. * @return {@code true} if the flick event was handled. */ private boolean dispatchFlick(MotionEvent e1, MotionEvent e2) { 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 deleted file mode 100644 index 65949357f..000000000 --- a/java/src/com/android/inputmethod/compat/AbstractCompatWrapper.java +++ /dev/null @@ -1,39 +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; - -import android.util.Log; - -public abstract class AbstractCompatWrapper { - private static final String TAG = AbstractCompatWrapper.class.getSimpleName(); - protected final Object mObj; - - public AbstractCompatWrapper(Object obj) { - if (obj == null) { - Log.e(TAG, "Invalid input to AbstructCompatWrapper"); - } - mObj = obj; - } - - public Object getOriginalObject() { - return mObj; - } - - public boolean hasOriginalObject() { - return mObj != null; - } -} 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/AccessibilityManagerCompatWrapper.java deleted file mode 100644 index a30af0faf..000000000 --- a/java/src/com/android/inputmethod/compat/AccessibilityManagerCompatWrapper.java +++ /dev/null @@ -1,36 +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; - -import android.view.accessibility.AccessibilityManager; - -import java.lang.reflect.Method; - -public class AccessibilityManagerCompatWrapper { - private static final Method METHOD_isTouchExplorationEnabled = CompatUtils.getMethod( - AccessibilityManager.class, "isTouchExplorationEnabled"); - - private final AccessibilityManager mManager; - - public AccessibilityManagerCompatWrapper(AccessibilityManager manager) { - mManager = manager; - } - - public boolean isTouchExplorationEnabled() { - return (Boolean) CompatUtils.invoke(mManager, false, METHOD_isTouchExplorationEnabled); - } -} diff --git a/java/src/com/android/inputmethod/compat/ArraysCompatUtils.java b/java/src/com/android/inputmethod/compat/ArraysCompatUtils.java deleted file mode 100644 index f6afbcfe2..000000000 --- a/java/src/com/android/inputmethod/compat/ArraysCompatUtils.java +++ /dev/null @@ -1,50 +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; - -import java.lang.reflect.Method; -import java.util.Arrays; - -public class ArraysCompatUtils { - private static final Method METHOD_Arrays_binarySearch = CompatUtils - .getMethod(Arrays.class, "binarySearch", int[].class, int.class, int.class, int.class); - - public static int binarySearch(int[] array, int startIndex, int endIndex, int value) { - if (METHOD_Arrays_binarySearch != null) { - final Object index = CompatUtils.invoke(null, 0, METHOD_Arrays_binarySearch, - array, startIndex, endIndex, value); - return (Integer)index; - } else { - return compatBinarySearch(array, startIndex, endIndex, value); - } - } - - /* package */ static int compatBinarySearch(int[] array, int startIndex, int endIndex, - int value) { - if (startIndex > endIndex) throw new IllegalArgumentException(); - if (startIndex < 0 || endIndex > array.length) throw new ArrayIndexOutOfBoundsException(); - - final int work[] = new int[endIndex - startIndex]; - System.arraycopy(array, startIndex, work, 0, work.length); - final int index = Arrays.binarySearch(work, value); - if (index >= 0) { - return index + startIndex; - } else { - return ~(~index + startIndex); - } - } -} diff --git a/java/src/com/android/inputmethod/compat/CompatUtils.java b/java/src/com/android/inputmethod/compat/CompatUtils.java index b42633cd9..ce427e9c9 100644 --- a/java/src/com/android/inputmethod/compat/CompatUtils.java +++ b/java/src/com/android/inputmethod/compat/CompatUtils.java @@ -23,8 +23,6 @@ import android.util.Log; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; public class CompatUtils { private static final String TAG = CompatUtils.class.getSimpleName(); @@ -32,28 +30,17 @@ public class CompatUtils { // TODO: Can these be constants instead of literal String constants? private static final String INPUT_METHOD_SUBTYPE_SETTINGS = "android.settings.INPUT_METHOD_SUBTYPE_SETTINGS"; - private static final String INPUT_LANGUAGE_SELECTION = - "com.android.inputmethod.latin.INPUT_LANGUAGE_SELECTION"; public static Intent getInputLanguageSelectionIntent(String inputMethodId, int flagsForSubtypeSettings) { - final String action; - Intent intent; - if (InputMethodServiceCompatWrapper.CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED - /* android.os.Build.VERSION_CODES.HONEYCOMB */ - && android.os.Build.VERSION.SDK_INT >= 11) { - // Refer to android.provider.Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS - action = INPUT_METHOD_SUBTYPE_SETTINGS; - intent = new Intent(action); - if (!TextUtils.isEmpty(inputMethodId)) { - intent.putExtra(EXTRA_INPUT_METHOD_ID, inputMethodId); - } - if (flagsForSubtypeSettings > 0) { - intent.setFlags(flagsForSubtypeSettings); - } - } else { - action = INPUT_LANGUAGE_SELECTION; - intent = new Intent(action); + // Refer to android.provider.Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS + final String action = INPUT_METHOD_SUBTYPE_SETTINGS; + final Intent intent = new Intent(action); + if (!TextUtils.isEmpty(inputMethodId)) { + intent.putExtra(EXTRA_INPUT_METHOD_ID, inputMethodId); + } + if (flagsForSubtypeSettings > 0) { + intent.setFlags(flagsForSubtypeSettings); } return intent; } @@ -142,15 +129,4 @@ public class CompatUtils { Log.e(TAG, "Exception in setFieldValue: " + e.getClass().getSimpleName()); } } - - public static List<InputMethodSubtypeCompatWrapper> copyInputMethodSubtypeListToWrapper( - Object listObject) { - if (!(listObject instanceof List<?>)) return null; - final List<InputMethodSubtypeCompatWrapper> subtypes = - new ArrayList<InputMethodSubtypeCompatWrapper>(); - for (Object o: (List<?>)listObject) { - subtypes.add(new InputMethodSubtypeCompatWrapper(o)); - } - return subtypes; - } } diff --git a/java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java b/java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java index bcdcef7dc..08c246f8b 100644 --- a/java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java +++ b/java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java @@ -17,86 +17,65 @@ package com.android.inputmethod.compat; import android.view.inputmethod.EditorInfo; -import android.view.inputmethod.InputConnection; import java.lang.reflect.Field; public class EditorInfoCompatUtils { - private static final Field FIELD_IME_FLAG_NAVIGATE_NEXT = CompatUtils.getField( - 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_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_ACTION_PREVIOUS = (Integer) CompatUtils - .getFieldValue(null, null, FIELD_IME_ACTION_PREVIOUS); + // EditorInfo.IME_FLAG_FORCE_ASCII has been introduced since API#16 (JellyBean). + private static final Field FIELD_IME_FLAG_FORCE_ASCII = CompatUtils.getField( + EditorInfo.class, "IME_FLAG_FORCE_ASCII"); + private static final Integer OBJ_IME_FLAG_FORCE_ASCII = (Integer) CompatUtils + .getFieldValue(null, null, FIELD_IME_FLAG_FORCE_ASCII); - public static boolean hasFlagNavigateNext(int imeOptions) { - if (OBJ_IME_FLAG_NAVIGATE_NEXT == null) - return false; - return (imeOptions & OBJ_IME_FLAG_NAVIGATE_NEXT) != 0; + private EditorInfoCompatUtils() { + // This utility class is not publicly instantiable. } - public static boolean hasFlagNavigatePrevious(int imeOptions) { - if (OBJ_IME_FLAG_NAVIGATE_PREVIOUS == null) + public static boolean hasFlagForceAscii(int imeOptions) { + if (OBJ_IME_FLAG_FORCE_ASCII == null) return false; - return (imeOptions & OBJ_IME_FLAG_NAVIGATE_PREVIOUS) != 0; - } - - public static void performEditorActionNext(InputConnection ic) { - ic.performEditorAction(EditorInfo.IME_ACTION_NEXT); + return (imeOptions & OBJ_IME_FLAG_FORCE_ASCII) != 0; } - public static void performEditorActionPrevious(InputConnection ic) { - if (OBJ_IME_ACTION_PREVIOUS == 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"; + case EditorInfo.IME_ACTION_PREVIOUS: + return "actionPrevious"; + default: + 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 ((imeOptions & EditorInfo.IME_FLAG_NAVIGATE_NEXT) != 0) { + flags.append("flagNavigateNext|"); + } + if ((imeOptions & EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS) != 0) { + 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/InputConnectionCompatUtils.java b/java/src/com/android/inputmethod/compat/InputConnectionCompatUtils.java deleted file mode 100644 index 7d00b6007..000000000 --- a/java/src/com/android/inputmethod/compat/InputConnectionCompatUtils.java +++ /dev/null @@ -1,80 +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; - -import com.android.inputmethod.latin.EditingUtils.SelectedWord; - -import android.view.inputmethod.InputConnection; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; - -public class InputConnectionCompatUtils { - private static final Class<?> CLASS_CorrectionInfo = CompatUtils - .getClass("android.view.inputmethod.CorrectionInfo"); - private static final Class<?>[] INPUT_TYPE_CorrectionInfo = new Class<?>[] { int.class, - CharSequence.class, CharSequence.class }; - private static final Constructor<?> CONSTRUCTOR_CorrectionInfo = CompatUtils - .getConstructor(CLASS_CorrectionInfo, INPUT_TYPE_CorrectionInfo); - private static final Method METHOD_InputConnection_commitCorrection = CompatUtils - .getMethod(InputConnection.class, "commitCorrection", CLASS_CorrectionInfo); - private static final Method METHOD_getSelectedText = CompatUtils - .getMethod(InputConnection.class, "getSelectedText", int.class); - private static final Method METHOD_setComposingRegion = CompatUtils - .getMethod(InputConnection.class, "setComposingRegion", int.class, int.class); - public static final boolean RECORRECTION_SUPPORTED; - - static { - RECORRECTION_SUPPORTED = METHOD_getSelectedText != null - && METHOD_setComposingRegion != null; - } - - public static void commitCorrection(InputConnection ic, int offset, CharSequence oldText, - CharSequence newText) { - if (ic == null || CONSTRUCTOR_CorrectionInfo == null - || METHOD_InputConnection_commitCorrection == null) { - return; - } - Object[] args = { offset, oldText, newText }; - Object correctionInfo = CompatUtils.newInstance(CONSTRUCTOR_CorrectionInfo, args); - if (correctionInfo != null) { - CompatUtils.invoke(ic, null, METHOD_InputConnection_commitCorrection, - correctionInfo); - } - } - - - /** - * Returns the selected text between the selStart and selEnd positions. - */ - public static CharSequence getSelectedText(InputConnection ic, int selStart, int selEnd) { - // Use reflection, for backward compatibility - return (CharSequence) CompatUtils.invoke( - ic, null, METHOD_getSelectedText, 0); - } - - /** - * Tries to set the text into composition mode if there is support for it in the framework. - */ - public static void underlineWord(InputConnection ic, SelectedWord word) { - // Use reflection, for backward compatibility - // If method not found, there's nothing we can do. It still works but just wont underline - // the word. - CompatUtils.invoke( - ic, null, METHOD_setComposingRegion, word.mStart, word.mEnd); - } -} diff --git a/java/src/com/android/inputmethod/compat/InputMethodInfoCompatWrapper.java b/java/src/com/android/inputmethod/compat/InputMethodInfoCompatWrapper.java deleted file mode 100644 index 831559809..000000000 --- a/java/src/com/android/inputmethod/compat/InputMethodInfoCompatWrapper.java +++ /dev/null @@ -1,77 +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; - -import android.content.pm.PackageManager; -import android.content.pm.ServiceInfo; -import android.view.inputmethod.InputMethodInfo; - -import java.lang.reflect.Method; - -public class InputMethodInfoCompatWrapper { - private final InputMethodInfo mImi; - private static final Method METHOD_getSubtypeAt = CompatUtils.getMethod( - InputMethodInfo.class, "getSubtypeAt", int.class); - private static final Method METHOD_getSubtypeCount = CompatUtils.getMethod( - InputMethodInfo.class, "getSubtypeCount"); - - public InputMethodInfoCompatWrapper(InputMethodInfo imi) { - mImi = imi; - } - - public InputMethodInfo getInputMethodInfo() { - return mImi; - } - - public String getId() { - return mImi.getId(); - } - - public String getPackageName() { - return mImi.getPackageName(); - } - - public ServiceInfo getServiceInfo() { - return mImi.getServiceInfo(); - } - - public int getSubtypeCount() { - return (Integer) CompatUtils.invoke(mImi, 0, METHOD_getSubtypeCount); - } - - public InputMethodSubtypeCompatWrapper getSubtypeAt(int index) { - return new InputMethodSubtypeCompatWrapper(CompatUtils.invoke(mImi, null, - METHOD_getSubtypeAt, index)); - } - - public CharSequence loadLabel(PackageManager pm) { - return mImi.loadLabel(pm); - } - - @Override - public boolean equals(Object o) { - if (o instanceof InputMethodInfoCompatWrapper) { - return mImi.equals(((InputMethodInfoCompatWrapper)o).mImi); - } - return false; - } - - @Override - public int hashCode() { - return mImi.hashCode(); - } -} diff --git a/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java b/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java index 51dc4cd37..ffed8202d 100644 --- a/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java +++ b/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java @@ -16,304 +16,83 @@ package com.android.inputmethod.compat; -import android.app.AlertDialog; import android.content.Context; -import android.content.DialogInterface; -import android.content.DialogInterface.OnClickListener; -import android.content.Intent; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; +import android.inputmethodservice.InputMethodService; import android.os.IBinder; -import android.text.TextUtils; import android.util.Log; import android.view.inputmethod.InputMethodInfo; 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 android.view.inputmethod.InputMethodSubtype; import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; import java.util.List; -import java.util.Locale; import java.util.Map; // TODO: Override this class with the concrete implementation if we need to take care of the // performance. 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_getEnabledInputMethodSubtypeList = - CompatUtils.getMethod(InputMethodManager.class, "getEnabledInputMethodSubtypeList", - InputMethodInfo.class, boolean.class); - private static final Method METHOD_getShortcutInputMethodsAndSubtypes = - CompatUtils.getMethod(InputMethodManager.class, "getShortcutInputMethodsAndSubtypes"); - private static final Method METHOD_setInputMethodAndSubtype = - CompatUtils.getMethod( - InputMethodManager.class, "setInputMethodAndSubtype", IBinder.class, - 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(); - public static final boolean SUBTYPE_SUPPORTED; + private InputMethodManager mImm; - static { - // This static initializer guarantees that METHOD_getShortcutInputMethodsAndSubtypes is - // already instantiated. - SUBTYPE_SUPPORTED = METHOD_getShortcutInputMethodsAndSubtypes != null; + private InputMethodManagerCompatWrapper() { + // This wrapper class is not publicly instantiable. } - // For the compatibility, IMM will create dummy subtypes if subtypes are not found. - // This is required to be false if the current behavior is broken. For now, it's ok to be true. - public static final boolean FORCE_ENABLE_VOICE_EVEN_WITH_NO_VOICE_SUBTYPES = - !InputMethodServiceCompatWrapper.CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED; - private static final String VOICE_MODE = "voice"; - private static final String KEYBOARD_MODE = "keyboard"; - - private InputMethodServiceCompatWrapper mService; - private InputMethodManager mImm; - private PackageManager mPackageManager; - private ApplicationInfo mApplicationInfo; - private LanguageSwitcherProxy mLanguageSwitcherProxy; - private String mLatinImePackageName; - public static InputMethodManagerCompatWrapper getInstance() { if (sInstance.mImm == null) Log.w(TAG, "getInstance() is called before initialization"); return sInstance; } - public static void init(InputMethodServiceCompatWrapper service) { - sInstance.mService = service; + public static void init(InputMethodService service) { sInstance.mImm = (InputMethodManager) service.getSystemService( Context.INPUT_METHOD_SERVICE); - sInstance.mLatinImePackageName = service.getPackageName(); - sInstance.mPackageManager = service.getPackageManager(); - sInstance.mApplicationInfo = service.getApplicationInfo(); - sInstance.mLanguageSwitcherProxy = LanguageSwitcherProxy.getInstance(); - } - - public InputMethodSubtypeCompatWrapper getCurrentInputMethodSubtype() { - if (!SUBTYPE_SUPPORTED) { - return new InputMethodSubtypeCompatWrapper( - 0, 0, mLanguageSwitcherProxy.getInputLocale().toString(), KEYBOARD_MODE, ""); - } - Object o = CompatUtils.invoke(mImm, null, METHOD_getCurrentInputMethodSubtype); - return new InputMethodSubtypeCompatWrapper(o); } - public List<InputMethodSubtypeCompatWrapper> getEnabledInputMethodSubtypeList( - InputMethodInfoCompatWrapper imi, boolean allowsImplicitlySelectedSubtypes) { - if (!SUBTYPE_SUPPORTED) { - String[] languages = mLanguageSwitcherProxy.getEnabledLanguages( - allowsImplicitlySelectedSubtypes); - List<InputMethodSubtypeCompatWrapper> subtypeList = - new ArrayList<InputMethodSubtypeCompatWrapper>(); - for (String lang: languages) { - subtypeList.add(new InputMethodSubtypeCompatWrapper(0, 0, lang, KEYBOARD_MODE, "")); - } - return subtypeList; - } - Object retval = CompatUtils.invoke(mImm, null, METHOD_getEnabledInputMethodSubtypeList, - (imi != null ? imi.getInputMethodInfo() : null), allowsImplicitlySelectedSubtypes); - if (retval == null || !(retval instanceof List<?>) || ((List<?>)retval).isEmpty()) { - if (!FORCE_ENABLE_VOICE_EVEN_WITH_NO_VOICE_SUBTYPES) { - // Returns an empty list - return Collections.emptyList(); - } - // Creates dummy subtypes - @SuppressWarnings("unused") - List<InputMethodSubtypeCompatWrapper> subtypeList = - new ArrayList<InputMethodSubtypeCompatWrapper>(); - InputMethodSubtypeCompatWrapper keyboardSubtype = getLastResortSubtype(KEYBOARD_MODE); - InputMethodSubtypeCompatWrapper voiceSubtype = getLastResortSubtype(VOICE_MODE); - if (keyboardSubtype != null) { - subtypeList.add(keyboardSubtype); - } - if (voiceSubtype != null) { - subtypeList.add(voiceSubtype); - } - return subtypeList; - } - return CompatUtils.copyInputMethodSubtypeListToWrapper(retval); + public InputMethodSubtype getCurrentInputMethodSubtype() { + return mImm.getCurrentInputMethodSubtype(); } - private InputMethodInfoCompatWrapper getLatinImeInputMethodInfo() { - if (TextUtils.isEmpty(mLatinImePackageName)) - return null; - return Utils.getInputMethodInfo(this, mLatinImePackageName); + public InputMethodSubtype getLastInputMethodSubtype() { + return mImm.getLastInputMethodSubtype(); } - @SuppressWarnings("unused") - private InputMethodSubtypeCompatWrapper getLastResortSubtype(String mode) { - if (VOICE_MODE.equals(mode) && !FORCE_ENABLE_VOICE_EVEN_WITH_NO_VOICE_SUBTYPES) - return null; - Locale inputLocale = SubtypeSwitcher.getInstance().getInputLocale(); - if (inputLocale == null) - return null; - return new InputMethodSubtypeCompatWrapper(0, 0, inputLocale.toString(), mode, ""); + public List<InputMethodSubtype> getEnabledInputMethodSubtypeList( + InputMethodInfo imi, boolean allowsImplicitlySelectedSubtypes) { + return mImm.getEnabledInputMethodSubtypeList(imi, allowsImplicitlySelectedSubtypes); } - public Map<InputMethodInfoCompatWrapper, List<InputMethodSubtypeCompatWrapper>> - getShortcutInputMethodsAndSubtypes() { - Object retval = CompatUtils.invoke(mImm, null, METHOD_getShortcutInputMethodsAndSubtypes); - if (retval == null || !(retval instanceof Map<?, ?>) || ((Map<?, ?>)retval).isEmpty()) { - if (!FORCE_ENABLE_VOICE_EVEN_WITH_NO_VOICE_SUBTYPES) { - // Returns an empty map - return Collections.emptyMap(); - } - // Creates dummy subtypes - @SuppressWarnings("unused") - InputMethodInfoCompatWrapper imi = getLatinImeInputMethodInfo(); - InputMethodSubtypeCompatWrapper voiceSubtype = getLastResortSubtype(VOICE_MODE); - if (imi != null && voiceSubtype != null) { - Map<InputMethodInfoCompatWrapper, List<InputMethodSubtypeCompatWrapper>> - shortcutMap = - new HashMap<InputMethodInfoCompatWrapper, - List<InputMethodSubtypeCompatWrapper>>(); - List<InputMethodSubtypeCompatWrapper> subtypeList = - new ArrayList<InputMethodSubtypeCompatWrapper>(); - subtypeList.add(voiceSubtype); - shortcutMap.put(imi, subtypeList); - return shortcutMap; - } else { - return Collections.emptyMap(); - } - } - Map<InputMethodInfoCompatWrapper, List<InputMethodSubtypeCompatWrapper>> shortcutMap = - new HashMap<InputMethodInfoCompatWrapper, List<InputMethodSubtypeCompatWrapper>>(); - final Map<?, ?> retvalMap = (Map<?, ?>)retval; - for (Object key : retvalMap.keySet()) { - if (!(key instanceof InputMethodInfo)) { - Log.e(TAG, "Class type error."); - return null; - } - shortcutMap.put(new InputMethodInfoCompatWrapper((InputMethodInfo)key), - CompatUtils.copyInputMethodSubtypeListToWrapper(retvalMap.get(key))); - } - return shortcutMap; + public Map<InputMethodInfo, List<InputMethodSubtype>> getShortcutInputMethodsAndSubtypes() { + return mImm.getShortcutInputMethodsAndSubtypes(); } // We don't call this method when we switch between subtypes within this IME. - public void setInputMethodAndSubtype( - IBinder token, String id, InputMethodSubtypeCompatWrapper subtype) { - // TODO: Support subtype change on non-subtype-supported platform. - if (subtype != null && subtype.hasOriginalObject()) { - CompatUtils.invoke(mImm, null, METHOD_setInputMethodAndSubtype, - token, id, subtype.getOriginalObject()); - } else { - mImm.setInputMethod(token, id); - } + public void setInputMethodAndSubtype(IBinder token, String id, InputMethodSubtype subtype) { + mImm.setInputMethodAndSubtype(token, id, subtype); } public boolean switchToLastInputMethod(IBinder token) { - if (SubtypeSwitcher.getInstance().isDummyVoiceMode()) { - return true; - } - return (Boolean)CompatUtils.invoke(mImm, false, METHOD_switchToLastInputMethod, token); + return mImm.switchToLastInputMethod(token); + } + + public boolean switchToNextInputMethod(IBinder token, boolean onlyCurrentIme) { + return (Boolean)CompatUtils.invoke(mImm, false, METHOD_switchToNextInputMethod, token, + onlyCurrentIme); } - public List<InputMethodInfoCompatWrapper> getEnabledInputMethodList() { + public List<InputMethodInfo> getEnabledInputMethodList() { if (mImm == null) return null; - List<InputMethodInfoCompatWrapper> imis = new ArrayList<InputMethodInfoCompatWrapper>(); - for (InputMethodInfo imi : mImm.getEnabledInputMethodList()) { - imis.add(new InputMethodInfoCompatWrapper(imi)); - } - return imis; + return mImm.getEnabledInputMethodList(); } public void showInputMethodPicker() { if (mImm == null) return; - if (SUBTYPE_SUPPORTED) { - mImm.showInputMethodPicker(); - return; - } - - // The code below are based on {@link InputMethodManager#showInputMethodMenuInternal}. - - final InputMethodInfoCompatWrapper myImi = Utils.getInputMethodInfo( - this, mLatinImePackageName); - final List<InputMethodSubtypeCompatWrapper> myImsList = getEnabledInputMethodSubtypeList( - myImi, true); - final InputMethodSubtypeCompatWrapper currentIms = getCurrentInputMethodSubtype(); - final List<InputMethodInfoCompatWrapper> imiList = getEnabledInputMethodList(); - imiList.remove(myImi); - Collections.sort(imiList, new Comparator<InputMethodInfoCompatWrapper>() { - @Override - public int compare(InputMethodInfoCompatWrapper imi1, - InputMethodInfoCompatWrapper imi2) { - final CharSequence imiId1 = imi1.loadLabel(mPackageManager) + "/" + imi1.getId(); - final CharSequence imiId2 = imi2.loadLabel(mPackageManager) + "/" + imi2.getId(); - return imiId1.toString().compareTo(imiId2.toString()); - } - }); - - final int myImsCount = myImsList.size(); - final int imiCount = imiList.size(); - final CharSequence[] items = new CharSequence[myImsCount + imiCount]; - - int checkedItem = 0; - int index = 0; - final CharSequence myImiLabel = myImi.loadLabel(mPackageManager); - for (int i = 0; i < myImsCount; i++) { - InputMethodSubtypeCompatWrapper ims = myImsList.get(i); - if (currentIms.equals(ims)) - checkedItem = index; - final CharSequence title = TextUtils.concat( - ims.getDisplayName(mService, mLatinImePackageName, mApplicationInfo), - " (" + myImiLabel, ")"); - items[index] = title; - index++; - } - - for (int i = 0; i < imiCount; i++) { - final InputMethodInfoCompatWrapper imi = imiList.get(i); - final CharSequence title = imi.loadLabel(mPackageManager); - items[index] = title; - index++; - } - - final OnClickListener buttonListener = new OnClickListener() { - @Override - public void onClick(DialogInterface di, int whichButton) { - final Intent intent = new Intent("android.settings.INPUT_METHOD_SETTINGS"); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK - | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED - | Intent.FLAG_ACTIVITY_CLEAR_TOP); - mService.startActivity(intent); - } - }; - final InputMethodServiceCompatWrapper service = mService; - final IBinder token = service.getWindow().getWindow().getAttributes().token; - final OnClickListener selectionListener = new OnClickListener() { - @Override - public void onClick(DialogInterface di, int which) { - di.dismiss(); - if (which < myImsCount) { - final int imsIndex = which; - final InputMethodSubtypeCompatWrapper ims = myImsList.get(imsIndex); - service.notifyOnCurrentInputMethodSubtypeChanged(ims); - } else { - final int imiIndex = which - myImsCount; - final InputMethodInfoCompatWrapper imi = imiList.get(imiIndex); - setInputMethodAndSubtype(token, imi.getId(), null); - } - } - }; - - final AlertDialog.Builder builder = new AlertDialog.Builder(mService) - .setTitle(mService.getString(R.string.selectInputMethod)) - .setNeutralButton(R.string.configure_input_method, buttonListener) - .setSingleChoiceItems(items, checkedItem, selectionListener); - mService.showOptionDialogInternal(builder.create()); + mImm.showInputMethodPicker(); } } diff --git a/java/src/com/android/inputmethod/compat/InputMethodServiceCompatWrapper.java b/java/src/com/android/inputmethod/compat/InputMethodServiceCompatWrapper.java deleted file mode 100644 index 8e2ee0f7a..000000000 --- a/java/src/com/android/inputmethod/compat/InputMethodServiceCompatWrapper.java +++ /dev/null @@ -1,113 +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; - -import android.app.AlertDialog; -import android.inputmethodservice.InputMethodService; -import android.os.IBinder; -import android.view.Window; -import android.view.WindowManager; -import android.view.inputmethod.InputMethodSubtype; - -import com.android.inputmethod.deprecated.LanguageSwitcherProxy; -import com.android.inputmethod.keyboard.KeyboardSwitcher; -import com.android.inputmethod.latin.SubtypeSwitcher; - -public class InputMethodServiceCompatWrapper extends InputMethodService { - // CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED needs to be false if the API level is 10 - // or previous. Note that InputMethodSubtype was added in the API level 11. - // For the API level 11 or later, LatinIME should override onCurrentInputMethodSubtypeChanged(). - // For the API level 10 or previous, we handle the "subtype changed" events by ourselves - // without having support from framework -- onCurrentInputMethodSubtypeChanged(). - public static final boolean CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED = true; - - private InputMethodManagerCompatWrapper mImm; - - // For compatibility of {@link InputMethodManager#showInputMethodPicker}. - // TODO: Move this variable back to LatinIME when this compatibility wrapper is removed. - protected AlertDialog mOptionsDialog; - - public void showOptionDialogInternal(AlertDialog dialog) { - final IBinder windowToken = KeyboardSwitcher.getInstance().getKeyboardView() - .getWindowToken(); - if (windowToken == null) return; - - dialog.setCancelable(true); - dialog.setCanceledOnTouchOutside(true); - - final Window window = dialog.getWindow(); - final WindowManager.LayoutParams lp = window.getAttributes(); - lp.token = windowToken; - lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; - window.setAttributes(lp); - window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); - - mOptionsDialog = dialog; - dialog.show(); - } - - @Override - public void onCreate() { - super.onCreate(); - mImm = InputMethodManagerCompatWrapper.getInstance(); - } - - // When the API level is 10 or previous, notifyOnCurrentInputMethodSubtypeChanged should - // handle the event the current subtype was changed. LatinIME calls - // notifyOnCurrentInputMethodSubtypeChanged every time LatinIME - // changes the current subtype. - // This call is required to let LatinIME itself know a subtype changed - // event when the API level is 10 or previous. - @SuppressWarnings("unused") - public void notifyOnCurrentInputMethodSubtypeChanged( - InputMethodSubtypeCompatWrapper newSubtype) { - // Do nothing when the API level is 11 or later - // and FORCE_ENABLE_VOICE_EVEN_WITH_NO_VOICE_SUBTYPES is not true - if (CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED && !InputMethodManagerCompatWrapper. - FORCE_ENABLE_VOICE_EVEN_WITH_NO_VOICE_SUBTYPES) { - return; - } - final InputMethodSubtypeCompatWrapper subtype = (newSubtype == null) - ? mImm.getCurrentInputMethodSubtype() - : newSubtype; - if (subtype != null) { - if (!InputMethodManagerCompatWrapper.FORCE_ENABLE_VOICE_EVEN_WITH_NO_VOICE_SUBTYPES - && !subtype.isDummy()) return; - if (!InputMethodManagerCompatWrapper.SUBTYPE_SUPPORTED) { - LanguageSwitcherProxy.getInstance().setLocale(subtype.getLocale()); - } - SubtypeSwitcher.getInstance().updateSubtype(subtype); - } - } - - ////////////////////////////////////// - // Functions using API v11 or later // - ////////////////////////////////////// - @Override - public void onCurrentInputMethodSubtypeChanged(InputMethodSubtype subtype) { - // Do nothing when the API level is 10 or previous - if (!CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED) return; - SubtypeSwitcher.getInstance().updateSubtype( - new InputMethodSubtypeCompatWrapper(subtype)); - } - - protected static void setTouchableRegionCompat(InputMethodService.Insets outInsets, - int x, int y, int width, int height) { - outInsets.touchableInsets = InputMethodService.Insets.TOUCHABLE_INSETS_REGION; - outInsets.touchableRegion.set(x, y, width, height); - } -} diff --git a/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatWrapper.java b/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatWrapper.java deleted file mode 100644 index a6bb83adf..000000000 --- a/java/src/com/android/inputmethod/compat/InputMethodSubtypeCompatWrapper.java +++ /dev/null @@ -1,188 +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; - -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.text.TextUtils; -import android.util.Log; - -import com.android.inputmethod.latin.LatinImeLogger; - -import java.lang.reflect.Method; -import java.util.Arrays; -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 { - private static final boolean DBG = LatinImeLogger.sDBG; - private static final String TAG = InputMethodSubtypeCompatWrapper.class.getSimpleName(); - private static final String DEFAULT_LOCALE = "en_US"; - private static final String DEFAULT_MODE = "keyboard"; - - public static final Class<?> CLASS_InputMethodSubtype = - CompatUtils.getClass("android.view.inputmethod.InputMethodSubtype"); - private static final Method METHOD_getNameResId = - CompatUtils.getMethod(CLASS_InputMethodSubtype, "getNameResId"); - private static final Method METHOD_getIconResId = - CompatUtils.getMethod(CLASS_InputMethodSubtype, "getIconResId"); - private static final Method METHOD_getLocale = - CompatUtils.getMethod(CLASS_InputMethodSubtype, "getLocale"); - private static final Method METHOD_getMode = - CompatUtils.getMethod(CLASS_InputMethodSubtype, "getMode"); - private static final Method METHOD_getExtraValue = - CompatUtils.getMethod(CLASS_InputMethodSubtype, "getExtraValue"); - private static final Method METHOD_containsExtraValueKey = - CompatUtils.getMethod(CLASS_InputMethodSubtype, "containsExtraValueKey", String.class); - private static final Method METHOD_getExtraValueOf = - CompatUtils.getMethod(CLASS_InputMethodSubtype, "getExtraValueOf", String.class); - private static final Method METHOD_isAuxiliary = - CompatUtils.getMethod(CLASS_InputMethodSubtype, "isAuxiliary"); - private static final Method METHOD_getDisplayName = - CompatUtils.getMethod(CLASS_InputMethodSubtype, "getDisplayName", Context.class, - String.class, ApplicationInfo.class); - - private final int mDummyNameResId; - private final int mDummyIconResId; - private final String mDummyLocale; - private final String mDummyMode; - private final String mDummyExtraValues; - - public InputMethodSubtypeCompatWrapper(Object subtype) { - super((CLASS_InputMethodSubtype != null && CLASS_InputMethodSubtype.isInstance(subtype)) - ? subtype : null); - mDummyNameResId = 0; - mDummyIconResId = 0; - mDummyLocale = DEFAULT_LOCALE; - mDummyMode = DEFAULT_MODE; - mDummyExtraValues = ""; - } - - // Constructor for creating a dummy subtype. - public InputMethodSubtypeCompatWrapper(int nameResId, int iconResId, String locale, - String mode, String extraValues) { - super(null); - if (DBG) { - Log.d(TAG, "CreateInputMethodSubtypeCompatWrapper"); - } - mDummyNameResId = nameResId; - mDummyIconResId = iconResId; - mDummyLocale = locale != null ? locale : ""; - mDummyMode = mode != null ? mode : ""; - mDummyExtraValues = extraValues != null ? extraValues : ""; - } - - public int getNameResId() { - if (mObj == null) return mDummyNameResId; - return (Integer)CompatUtils.invoke(mObj, 0, METHOD_getNameResId); - } - - public int getIconResId() { - if (mObj == null) return mDummyIconResId; - return (Integer)CompatUtils.invoke(mObj, 0, METHOD_getIconResId); - } - - public String getLocale() { - if (mObj == null) return mDummyLocale; - final String s = (String)CompatUtils.invoke(mObj, null, METHOD_getLocale); - return s != null ? s : DEFAULT_LOCALE; - } - - public String getMode() { - if (mObj == null) return mDummyMode; - String s = (String)CompatUtils.invoke(mObj, null, METHOD_getMode); - if (TextUtils.isEmpty(s)) return DEFAULT_MODE; - return s; - } - - public String getExtraValue() { - if (mObj == null) return mDummyExtraValues; - return (String)CompatUtils.invoke(mObj, null, METHOD_getExtraValue); - } - - public boolean containsExtraValueKey(String key) { - return (Boolean)CompatUtils.invoke(mObj, false, METHOD_containsExtraValueKey, key); - } - - public String getExtraValueOf(String key) { - return (String)CompatUtils.invoke(mObj, null, METHOD_getExtraValueOf, key); - } - - public boolean isAuxiliary() { - return (Boolean)CompatUtils.invoke(mObj, false, METHOD_isAuxiliary); - } - - public CharSequence getDisplayName(Context context, String packageName, - ApplicationInfo appInfo) { - if (mObj != null) { - return (CharSequence)CompatUtils.invoke( - mObj, "", METHOD_getDisplayName, context, packageName, appInfo); - } - - // The code below are based on {@link InputMethodSubtype#getDisplayName}. - - final Locale locale = new Locale(getLocale()); - final String localeStr = locale.getDisplayName(); - if (getNameResId() == 0) { - return localeStr; - } - final CharSequence subtypeName = context.getText(getNameResId()); - if (!TextUtils.isEmpty(localeStr)) { - return String.format(subtypeName.toString(), localeStr); - } else { - return localeStr; - } - } - - public boolean isDummy() { - return !hasOriginalObject(); - } - - @Override - public boolean equals(Object o) { - if (o instanceof InputMethodSubtypeCompatWrapper) { - InputMethodSubtypeCompatWrapper subtype = (InputMethodSubtypeCompatWrapper)o; - if (mObj == null) { - // easy check of dummy subtypes - return (mDummyNameResId == subtype.mDummyNameResId - && mDummyIconResId == subtype.mDummyIconResId - && mDummyLocale.equals(subtype.mDummyLocale) - && mDummyMode.equals(subtype.mDummyMode) - && mDummyExtraValues.equals(subtype.mDummyExtraValues)); - } - return mObj.equals(subtype.getOriginalObject()); - } else { - return mObj.equals(o); - } - } - - @Override - public int hashCode() { - if (mObj == null) { - return hashCodeInternal(mDummyNameResId, mDummyIconResId, mDummyLocale, - mDummyMode, mDummyExtraValues); - } - return mObj.hashCode(); - } - - private static int hashCodeInternal(int nameResId, int iconResId, String locale, - String mode, String extraValue) { - return Arrays - .hashCode(new Object[] { nameResId, iconResId, locale, mode, extraValue }); - } -} diff --git a/java/src/com/android/inputmethod/compat/InputTypeCompatUtils.java b/java/src/com/android/inputmethod/compat/InputTypeCompatUtils.java deleted file mode 100644 index 6c2f0f799..000000000 --- a/java/src/com/android/inputmethod/compat/InputTypeCompatUtils.java +++ /dev/null @@ -1,118 +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; - -import android.text.InputType; - -import java.lang.reflect.Field; - -public class InputTypeCompatUtils { - private static final Field FIELD_InputType_TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS = - CompatUtils.getField(InputType.class, "TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS"); - private static final Field FIELD_InputType_TYPE_TEXT_VARIATION_WEB_PASSWORD = CompatUtils - .getField(InputType.class, "TYPE_TEXT_VARIATION_WEB_PASSWORD"); - private static final Field FIELD_InputType_TYPE_NUMBER_VARIATION_PASSWORD = CompatUtils - .getField(InputType.class, "TYPE_NUMBER_VARIATION_PASSWORD"); - private static final Integer OBJ_InputType_TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS = - (Integer) CompatUtils.getFieldValue(null, null, - FIELD_InputType_TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS); - private static final Integer OBJ_InputType_TYPE_TEXT_VARIATION_WEB_PASSWORD = - (Integer) CompatUtils.getFieldValue(null, null, - FIELD_InputType_TYPE_TEXT_VARIATION_WEB_PASSWORD); - private static final Integer OBJ_InputType_TYPE_NUMBER_VARIATION_PASSWORD = - (Integer) CompatUtils.getFieldValue(null, null, - FIELD_InputType_TYPE_NUMBER_VARIATION_PASSWORD); - private static final int WEB_TEXT_PASSWORD_INPUT_TYPE; - private static final int WEB_TEXT_EMAIL_ADDRESS_INPUT_TYPE; - private static final int NUMBER_PASSWORD_INPUT_TYPE; - private static final int TEXT_PASSWORD_INPUT_TYPE = - InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD; - private static final int TEXT_VISIBLE_PASSWORD_INPUT_TYPE = - InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD; - - static { - WEB_TEXT_PASSWORD_INPUT_TYPE = - OBJ_InputType_TYPE_TEXT_VARIATION_WEB_PASSWORD != null - ? InputType.TYPE_CLASS_TEXT | OBJ_InputType_TYPE_TEXT_VARIATION_WEB_PASSWORD - : 0; - WEB_TEXT_EMAIL_ADDRESS_INPUT_TYPE = - OBJ_InputType_TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS != null - ? InputType.TYPE_CLASS_TEXT - | OBJ_InputType_TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS - : 0; - NUMBER_PASSWORD_INPUT_TYPE = - OBJ_InputType_TYPE_NUMBER_VARIATION_PASSWORD != null - ? InputType.TYPE_CLASS_NUMBER | OBJ_InputType_TYPE_NUMBER_VARIATION_PASSWORD - : 0; - } - - private static boolean isWebEditTextInputType(int inputType) { - return inputType == (InputType.TYPE_CLASS_TEXT - | InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT); - } - - private static boolean isWebPasswordInputType(int inputType) { - return WEB_TEXT_PASSWORD_INPUT_TYPE != 0 - && inputType == WEB_TEXT_PASSWORD_INPUT_TYPE; - } - - private static boolean isWebEmailAddressInputType(int inputType) { - return WEB_TEXT_EMAIL_ADDRESS_INPUT_TYPE != 0 - && inputType == WEB_TEXT_EMAIL_ADDRESS_INPUT_TYPE; - } - - private static boolean isNumberPasswordInputType(int inputType) { - return NUMBER_PASSWORD_INPUT_TYPE != 0 - && inputType == NUMBER_PASSWORD_INPUT_TYPE; - } - - private static boolean isTextPasswordInputType(int inputType) { - return inputType == TEXT_PASSWORD_INPUT_TYPE; - } - - private static boolean isWebEmailAddressVariation(int variation) { - return OBJ_InputType_TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS != null - && variation == OBJ_InputType_TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS; - } - - public static boolean isEmailVariation(int variation) { - return variation == InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS - || isWebEmailAddressVariation(variation); - } - - public static boolean isWebInputType(int inputType) { - final int maskedInputType = - inputType & (InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION); - return isWebEditTextInputType(maskedInputType) || isWebPasswordInputType(maskedInputType) - || isWebEmailAddressInputType(maskedInputType); - } - - // Please refer to TextView.isPasswordInputType - public static boolean isPasswordInputType(int inputType) { - final int maskedInputType = - inputType & (InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION); - return isTextPasswordInputType(maskedInputType) || isWebPasswordInputType(maskedInputType) - || isNumberPasswordInputType(maskedInputType); - } - - // Please refer to TextView.isVisiblePasswordInputType - public static boolean isVisiblePasswordInputType(int inputType) { - final int maskedInputType = - inputType & (InputType.TYPE_MASK_CLASS | InputType.TYPE_MASK_VARIATION); - return maskedInputType == TEXT_VISIBLE_PASSWORD_INPUT_TYPE; - } -} diff --git a/java/src/com/android/inputmethod/compat/MotionEventCompatUtils.java b/java/src/com/android/inputmethod/compat/MotionEventCompatUtils.java deleted file mode 100644 index 8518a4a78..000000000 --- a/java/src/com/android/inputmethod/compat/MotionEventCompatUtils.java +++ /dev/null @@ -1,23 +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 MotionEventCompatUtils { - public static final int ACTION_HOVER_MOVE = 0x7; - 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/SharedPreferencesCompat.java b/java/src/com/android/inputmethod/compat/SharedPreferencesCompat.java deleted file mode 100644 index 38736f3a1..000000000 --- a/java/src/com/android/inputmethod/compat/SharedPreferencesCompat.java +++ /dev/null @@ -1,53 +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.compat; - -import android.content.SharedPreferences; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -/** - * Reflection utils to call SharedPreferences$Editor.apply when possible, - * falling back to commit when apply isn't available. - */ -public class SharedPreferencesCompat { - private static final Method sApplyMethod = findApplyMethod(); - - private static Method findApplyMethod() { - try { - return SharedPreferences.Editor.class.getMethod("apply"); - } catch (NoSuchMethodException unused) { - // fall through - } - return null; - } - - public static void apply(SharedPreferences.Editor editor) { - if (sApplyMethod != null) { - try { - sApplyMethod.invoke(editor); - return; - } catch (InvocationTargetException unused) { - // fall through - } catch (IllegalAccessException unused) { - // fall through - } - } - editor.commit(); - } -} diff --git a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java index 161ef09b8..5c351e41f 100644 --- a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java +++ b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java @@ -48,30 +48,44 @@ public class SuggestionSpanUtils { Context.class, Locale.class, String[].class, int.class, Class.class }; private static final Constructor<?> CONSTRUCTOR_SuggestionSpan = CompatUtils .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_FLAG_EASY_CORRECT = + CompatUtils.getField(CLASS_SuggestionSpan, "FLAG_EASY_CORRECT"); + public static final Field FIELD_FLAG_MISSPELLED = + CompatUtils.getField(CLASS_SuggestionSpan, "FLAG_MISSPELLED"); + public static final Field FIELD_FLAG_AUTO_CORRECTION = + CompatUtils.getField(CLASS_SuggestionSpan, "FLAG_AUTO_CORRECTION"); + public static final Field FIELD_SUGGESTIONS_MAX_SIZE = CompatUtils.getField(CLASS_SuggestionSpan, "SUGGESTIONS_MAX_SIZE"); + public static final Integer OBJ_FLAG_EASY_CORRECT = (Integer) CompatUtils + .getFieldValue(null, null, FIELD_FLAG_EASY_CORRECT); + public static final Integer OBJ_FLAG_MISSPELLED = (Integer) CompatUtils + .getFieldValue(null, null, FIELD_FLAG_MISSPELLED); 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);; + .getFieldValue(null, null, FIELD_FLAG_AUTO_CORRECTION); + 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 + || OBJ_FLAG_MISSPELLED == null || OBJ_FLAG_EASY_CORRECT == null)) { throw new RuntimeException("Field is accidentially null."); } } } + private SuggestionSpanUtils() { + // This utility class is not publicly instantiable. + } + 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 + || OBJ_FLAG_MISSPELLED == null || OBJ_FLAG_EASY_CORRECT == null) { return text; } final Spannable spannable = text instanceof Spannable @@ -93,8 +107,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; } @@ -105,18 +118,26 @@ public class SuggestionSpanUtils { spannable = new SpannableString(pickedWord); } final ArrayList<String> suggestionsList = new ArrayList<String>(); + boolean sameAsTyped = false; 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); if (!TextUtils.equals(pickedWord, word)) { suggestionsList.add(word.toString()); + } else if (i == 0) { + sameAsTyped = true; } } + // TODO: Share the implementation for checking typed word validity between the IME + // and the spell checker. + final int flag = (sameAsTyped && !suggestedWords.mTypedWordValid) + ? (OBJ_FLAG_EASY_CORRECT | OBJ_FLAG_MISSPELLED) + : 0; final Object[] args = - { context, null, suggestionsList.toArray(new String[suggestionsList.size()]), 0, + { context, null, suggestionsList.toArray(new String[suggestionsList.size()]), flag, (Class<?>) SuggestionSpanPickedNotificationReceiver.class }; final Object ss = CompatUtils.newInstance(CONSTRUCTOR_SuggestionSpan, args); if (ss == null) { 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..e5f9db27c --- /dev/null +++ b/java/src/com/android/inputmethod/compat/SuggestionsInfoCompatUtils.java @@ -0,0 +1,44 @@ +/* + * 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() { + // This utility class is not publicly instantiable. + } + + /** + * Returns the flag value of the attributes of the suggestions that can be obtained by + * {@link SuggestionsInfo#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/deprecated/LanguageSwitcherProxy.java b/java/src/com/android/inputmethod/deprecated/LanguageSwitcherProxy.java deleted file mode 100644 index 290e6b554..000000000 --- a/java/src/com/android/inputmethod/deprecated/LanguageSwitcherProxy.java +++ /dev/null @@ -1,90 +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.deprecated; - -import com.android.inputmethod.compat.InputMethodManagerCompatWrapper; -import com.android.inputmethod.deprecated.languageswitcher.LanguageSwitcher; -import com.android.inputmethod.latin.LatinIME; -import com.android.inputmethod.latin.Settings; - -import android.content.SharedPreferences; -import android.content.res.Configuration; - -import java.util.Locale; - -// This class is used only when the IME doesn't use method.xml for language switching. -public class LanguageSwitcherProxy implements SharedPreferences.OnSharedPreferenceChangeListener { - private static final LanguageSwitcherProxy sInstance = new LanguageSwitcherProxy(); - private LatinIME mService; - private LanguageSwitcher mLanguageSwitcher; - private SharedPreferences mPrefs; - - public static LanguageSwitcherProxy getInstance() { - if (InputMethodManagerCompatWrapper.SUBTYPE_SUPPORTED) return null; - return sInstance; - } - - public static void init(LatinIME service, SharedPreferences prefs) { - if (InputMethodManagerCompatWrapper.SUBTYPE_SUPPORTED) return; - final Configuration conf = service.getResources().getConfiguration(); - sInstance.mLanguageSwitcher = new LanguageSwitcher(service); - sInstance.mLanguageSwitcher.loadLocales(prefs, conf.locale); - sInstance.mPrefs = prefs; - sInstance.mService = service; - prefs.registerOnSharedPreferenceChangeListener(sInstance); - } - - public static void onConfigurationChanged(Configuration conf) { - if (InputMethodManagerCompatWrapper.SUBTYPE_SUPPORTED) return; - sInstance.mLanguageSwitcher.onConfigurationChanged(conf, sInstance.mPrefs); - } - - public static void loadSettings() { - if (InputMethodManagerCompatWrapper.SUBTYPE_SUPPORTED) return; - sInstance.mLanguageSwitcher.loadLocales(sInstance.mPrefs, null); - } - - public int getLocaleCount() { - return mLanguageSwitcher.getLocaleCount(); - } - - public String[] getEnabledLanguages(boolean allowImplicitlySelectedLanguages) { - return mLanguageSwitcher.getEnabledLanguages(allowImplicitlySelectedLanguages); - } - - public Locale getInputLocale() { - return mLanguageSwitcher.getInputLocale(); - } - - public void setLocale(String localeStr) { - mLanguageSwitcher.setLocale(localeStr); - mLanguageSwitcher.persist(mPrefs); - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { - // PREF_SELECTED_LANGUAGES: enabled input subtypes - // PREF_INPUT_LANGUAGE: current input subtype - if (key.equals(Settings.PREF_SELECTED_LANGUAGES) - || key.equals(Settings.PREF_INPUT_LANGUAGE)) { - mLanguageSwitcher.loadLocales(prefs, null); - if (mService != null) { - mService.onRefreshKeyboard(); - } - } - } -} diff --git a/java/src/com/android/inputmethod/deprecated/VoiceProxy.java b/java/src/com/android/inputmethod/deprecated/VoiceProxy.java deleted file mode 100644 index 3f8c2ef8f..000000000 --- a/java/src/com/android/inputmethod/deprecated/VoiceProxy.java +++ /dev/null @@ -1,880 +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.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; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.net.Uri; -import android.os.AsyncTask; -import android.os.IBinder; -import android.preference.PreferenceManager; -import android.provider.Browser; -import android.speech.SpeechRecognizer; -import android.text.SpannableStringBuilder; -import android.text.Spanned; -import android.text.TextUtils; -import android.text.method.LinkMovementMethod; -import android.text.style.URLSpan; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewParent; -import android.view.Window; -import android.view.WindowManager; -import android.view.inputmethod.EditorInfo; -import android.view.inputmethod.ExtractedTextRequest; -import android.view.inputmethod.InputConnection; -import android.widget.TextView; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class VoiceProxy implements VoiceInput.UiListener { - private static final VoiceProxy sInstance = new VoiceProxy(); - - public static final boolean VOICE_INSTALLED = - !InputMethodServiceCompatWrapper.CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED; - private static final boolean ENABLE_VOICE_BUTTON = true; - private static final String PREF_VOICE_MODE = "voice_mode"; - // Whether or not the user has used voice input before (and thus, whether to show the - // first-run warning dialog or not). - private static final String PREF_HAS_USED_VOICE_INPUT = "has_used_voice_input"; - // Whether or not the user has used voice input from an unsupported locale UI before. - // For example, the user has a Chinese UI but activates voice input. - private static final String PREF_HAS_USED_VOICE_INPUT_UNSUPPORTED_LOCALE = - "has_used_voice_input_unsupported_locale"; - private static final int RECOGNITIONVIEW_HEIGHT_THRESHOLD_RATIO = 6; - // TODO: Adjusted on phones for now - private static final int RECOGNITIONVIEW_MINIMUM_HEIGHT_DIP = 244; - - private static final String TAG = VoiceProxy.class.getSimpleName(); - private static final boolean DEBUG = LatinImeLogger.sDBG; - - private boolean mAfterVoiceInput; - private boolean mHasUsedVoiceInput; - private boolean mHasUsedVoiceInputUnsupportedLocale; - private boolean mImmediatelyAfterVoiceInput; - private boolean mIsShowingHint; - private boolean mLocaleSupportedForVoiceInput; - private boolean mPasswordText; - private boolean mRecognizing; - private boolean mShowingVoiceSuggestions; - private boolean mVoiceButtonEnabled; - private boolean mVoiceButtonOnPrimary; - private boolean mVoiceInputHighlighted; - - private int mMinimumVoiceRecognitionViewHeightPixel; - private InputMethodManagerCompatWrapper mImm; - private LatinIME mService; - private AlertDialog mVoiceWarningDialog; - private VoiceInput mVoiceInput; - private final VoiceResults mVoiceResults = new VoiceResults(); - private Hints mHints; - private UIHandler mHandler; - private SubtypeSwitcher mSubtypeSwitcher; - - // For each word, a list of potential replacements, usually from voice. - private final Map<String, List<CharSequence>> mWordToSuggestions = - new HashMap<String, List<CharSequence>>(); - - public static VoiceProxy init(LatinIME context, SharedPreferences prefs, UIHandler h) { - sInstance.initInternal(context, prefs, h); - return sInstance; - } - - public static VoiceProxy getInstance() { - return sInstance; - } - - private void initInternal(LatinIME service, SharedPreferences prefs, UIHandler h) { - if (!VOICE_INSTALLED) { - return; - } - mService = service; - mHandler = h; - mMinimumVoiceRecognitionViewHeightPixel = Utils.dipToPixel( - Utils.getDipScale(service), RECOGNITIONVIEW_MINIMUM_HEIGHT_DIP); - mImm = InputMethodManagerCompatWrapper.getInstance(); - mSubtypeSwitcher = SubtypeSwitcher.getInstance(); - mVoiceInput = new VoiceInput(service, this); - mHints = new Hints(service, prefs, new Hints.Display() { - @Override - public void showHint(int viewResource) { - View view = LayoutInflater.from(mService).inflate(viewResource, null); - mIsShowingHint = true; - } - }); - } - - private VoiceProxy() { - // Intentional empty constructor for singleton. - } - - public void resetVoiceStates(boolean isPasswordText) { - mAfterVoiceInput = false; - mImmediatelyAfterVoiceInput = false; - mShowingVoiceSuggestions = false; - mVoiceInputHighlighted = false; - mPasswordText = isPasswordText; - } - - public void flushVoiceInputLogs(boolean configurationChanged) { - if (!VOICE_INSTALLED) { - return; - } - if (!configurationChanged) { - if (mAfterVoiceInput) { - mVoiceInput.flushAllTextModificationCounters(); - mVoiceInput.logInputEnded(); - } - mVoiceInput.flushLogs(); - mVoiceInput.cancel(); - } - } - - public void flushAndLogAllTextModificationCounters(int index, CharSequence suggestion, - String wordSeparators) { - if (!VOICE_INSTALLED) { - return; - } - if (mAfterVoiceInput && mShowingVoiceSuggestions) { - mVoiceInput.flushAllTextModificationCounters(); - // send this intent AFTER logging any prior aggregated edits. - mVoiceInput.logTextModifiedByChooseSuggestion(suggestion.toString(), index, - wordSeparators, mService.getCurrentInputConnection()); - } - } - - private void showVoiceWarningDialog(final boolean swipe, IBinder token) { - if (mVoiceWarningDialog != null && mVoiceWarningDialog.isShowing()) { - return; - } - AlertDialog.Builder builder = new UrlLinkAlertDialogBuilder(mService); - builder.setCancelable(true); - builder.setIcon(R.drawable.ic_mic_dialog); - builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int whichButton) { - mVoiceInput.logKeyboardWarningDialogOk(); - reallyStartListening(swipe); - } - }); - builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int whichButton) { - mVoiceInput.logKeyboardWarningDialogCancel(); - switchToLastInputMethod(); - } - }); - // When the dialog is dismissed by user's cancellation, switch back to the last input method - builder.setOnCancelListener(new DialogInterface.OnCancelListener() { - @Override - public void onCancel(DialogInterface arg0) { - mVoiceInput.logKeyboardWarningDialogCancel(); - switchToLastInputMethod(); - } - }); - - final CharSequence message; - if (mLocaleSupportedForVoiceInput) { - message = TextUtils.concat( - mService.getText(R.string.voice_warning_may_not_understand), "\n\n", - mService.getText(R.string.voice_warning_how_to_turn_off)); - } else { - message = TextUtils.concat( - mService.getText(R.string.voice_warning_locale_not_supported), "\n\n", - mService.getText(R.string.voice_warning_may_not_understand), "\n\n", - mService.getText(R.string.voice_warning_how_to_turn_off)); - } - builder.setMessage(message); - builder.setTitle(R.string.voice_warning_title); - mVoiceWarningDialog = builder.create(); - final Window window = mVoiceWarningDialog.getWindow(); - final WindowManager.LayoutParams lp = window.getAttributes(); - lp.token = token; - lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; - window.setAttributes(lp); - window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); - mVoiceInput.logKeyboardWarningDialogShown(); - mVoiceWarningDialog.show(); - } - - private static class UrlLinkAlertDialogBuilder extends AlertDialog.Builder { - private AlertDialog mAlertDialog; - - public UrlLinkAlertDialogBuilder(Context context) { - super(context); - } - - @Override - public AlertDialog.Builder setMessage(CharSequence message) { - return super.setMessage(replaceURLSpan(message)); - } - - private Spanned replaceURLSpan(CharSequence message) { - // Replace all spans with the custom span - final SpannableStringBuilder ssb = new SpannableStringBuilder(message); - for (URLSpan span : ssb.getSpans(0, ssb.length(), URLSpan.class)) { - int spanStart = ssb.getSpanStart(span); - int spanEnd = ssb.getSpanEnd(span); - int spanFlags = ssb.getSpanFlags(span); - ssb.removeSpan(span); - ssb.setSpan(new ClickableSpan(span.getURL()), spanStart, spanEnd, spanFlags); - } - return ssb; - } - - @Override - public AlertDialog create() { - final AlertDialog dialog = super.create(); - - dialog.setOnShowListener(new DialogInterface.OnShowListener() { - @Override - public void onShow(DialogInterface dialogInterface) { - // Make URL in the dialog message click-able. - TextView textView = (TextView) mAlertDialog.findViewById(android.R.id.message); - if (textView != null) { - textView.setMovementMethod(LinkMovementMethod.getInstance()); - } - } - }); - mAlertDialog = dialog; - return dialog; - } - - class ClickableSpan extends URLSpan { - public ClickableSpan(String url) { - super(url); - } - - @Override - public void onClick(View widget) { - Uri uri = Uri.parse(getURL()); - Context context = widget.getContext(); - Intent intent = new Intent(Intent.ACTION_VIEW, uri); - // Add this flag to start an activity from service - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName()); - // Dismiss the warning dialog and go back to the previous IME. - // TODO: If we can find a way to bring the new activity to front while keeping - // the warning dialog, we don't need to dismiss it here. - mAlertDialog.cancel(); - context.startActivity(intent); - } - } - } - - public void showPunctuationHintIfNecessary() { - if (!VOICE_INSTALLED) { - return; - } - InputConnection ic = mService.getCurrentInputConnection(); - if (!mImmediatelyAfterVoiceInput && mAfterVoiceInput && ic != null) { - if (mHints.showPunctuationHintIfNecessary(ic)) { - mVoiceInput.logPunctuationHintDisplayed(); - } - } - mImmediatelyAfterVoiceInput = false; - } - - public void hideVoiceWindow(boolean configurationChanging) { - if (!VOICE_INSTALLED) { - return; - } - if (!configurationChanging) { - if (mAfterVoiceInput) - mVoiceInput.logInputEnded(); - if (mVoiceWarningDialog != null && mVoiceWarningDialog.isShowing()) { - mVoiceInput.logKeyboardWarningDialogDismissed(); - mVoiceWarningDialog.dismiss(); - mVoiceWarningDialog = null; - } - if (VOICE_INSTALLED & mRecognizing) { - mVoiceInput.cancel(); - } - } - mWordToSuggestions.clear(); - } - - public void setCursorAndSelection(int newSelEnd, int newSelStart) { - if (!VOICE_INSTALLED) { - return; - } - if (mAfterVoiceInput) { - mVoiceInput.setCursorPos(newSelEnd); - mVoiceInput.setSelectionSpan(newSelEnd - newSelStart); - } - } - - public void setVoiceInputHighlighted(boolean b) { - mVoiceInputHighlighted = b; - } - - public void setShowingVoiceSuggestions(boolean b) { - mShowingVoiceSuggestions = b; - } - - public boolean isVoiceButtonEnabled() { - return mVoiceButtonEnabled; - } - - public boolean isVoiceButtonOnPrimary() { - return mVoiceButtonOnPrimary; - } - - public boolean isVoiceInputHighlighted() { - return mVoiceInputHighlighted; - } - - public boolean isRecognizing() { - return mRecognizing; - } - - public boolean needsToShowWarningDialog() { - return !mHasUsedVoiceInput - || (!mLocaleSupportedForVoiceInput && !mHasUsedVoiceInputUnsupportedLocale); - } - - public boolean getAndResetIsShowingHint() { - boolean ret = mIsShowingHint; - mIsShowingHint = false; - return ret; - } - - private void revertVoiceInput() { - InputConnection ic = mService.getCurrentInputConnection(); - if (ic != null) ic.commitText("", 1); - mService.updateSuggestions(); - mVoiceInputHighlighted = false; - } - - public void commitVoiceInput() { - if (VOICE_INSTALLED && mVoiceInputHighlighted) { - InputConnection ic = mService.getCurrentInputConnection(); - if (ic != null) ic.finishComposingText(); - mService.updateSuggestions(); - mVoiceInputHighlighted = false; - } - } - - public boolean logAndRevertVoiceInput() { - if (!VOICE_INSTALLED) { - return false; - } - if (mVoiceInputHighlighted) { - mVoiceInput.incrementTextModificationDeleteCount( - mVoiceResults.candidates.get(0).toString().length()); - revertVoiceInput(); - return true; - } else { - return false; - } - } - - public void rememberReplacedWord(CharSequence suggestion,String wordSeparators) { - if (!VOICE_INSTALLED) { - return; - } - if (mShowingVoiceSuggestions) { - // Retain the replaced word in the alternatives array. - String wordToBeReplaced = EditingUtils.getWordAtCursor( - mService.getCurrentInputConnection(), wordSeparators); - if (!mWordToSuggestions.containsKey(wordToBeReplaced)) { - wordToBeReplaced = wordToBeReplaced.toLowerCase(); - } - if (mWordToSuggestions.containsKey(wordToBeReplaced)) { - List<CharSequence> suggestions = mWordToSuggestions.get(wordToBeReplaced); - if (suggestions.contains(suggestion)) { - suggestions.remove(suggestion); - } - suggestions.add(wordToBeReplaced); - mWordToSuggestions.remove(wordToBeReplaced); - mWordToSuggestions.put(suggestion.toString(), suggestions); - } - } - } - - /** - * 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; - } - if (mAfterVoiceInput) { - // Don't log delete if the user is pressing delete at - // the beginning of the text box (hence not deleting anything) - if (mVoiceInput.getCursorPos() > 0) { - // If anything was selected before the delete was pressed, increment the - // delete count by the length of the selection - int deleteLen = mVoiceInput.getSelectionSpan() > 0 ? - mVoiceInput.getSelectionSpan() : 1; - mVoiceInput.incrementTextModificationDeleteCount(deleteLen); - } - } - } - - public void handleCharacter() { - if (!VOICE_INSTALLED) { - return; - } - commitVoiceInput(); - if (mAfterVoiceInput) { - // Assume input length is 1. This assumption fails for smiley face insertions. - mVoiceInput.incrementTextModificationInsertCount(1); - } - } - - public void handleSeparator() { - if (!VOICE_INSTALLED) { - return; - } - commitVoiceInput(); - if (mAfterVoiceInput){ - // Assume input length is 1. This assumption fails for smiley face insertions. - mVoiceInput.incrementTextModificationInsertPunctuationCount(1); - } - } - - public void handleClose() { - if (!VOICE_INSTALLED) { - return; - } - if (mRecognizing) { - mVoiceInput.cancel(); - } - } - - - public void handleVoiceResults(boolean capitalizeFirstWord) { - if (!VOICE_INSTALLED) { - return; - } - mAfterVoiceInput = true; - mImmediatelyAfterVoiceInput = true; - - InputConnection ic = mService.getCurrentInputConnection(); - if (!mService.isFullscreenMode()) { - // Start listening for updates to the text from typing, etc. - if (ic != null) { - ExtractedTextRequest req = new ExtractedTextRequest(); - ic.getExtractedText(req, InputConnection.GET_EXTRACTED_TEXT_MONITOR); - } - } - mService.vibrate(); - - final List<CharSequence> nBest = new ArrayList<CharSequence>(); - for (String c : mVoiceResults.candidates) { - if (capitalizeFirstWord) { - c = Character.toUpperCase(c.charAt(0)) + c.substring(1, c.length()); - } - nBest.add(c); - } - if (nBest.size() == 0) { - return; - } - String bestResult = nBest.get(0).toString(); - mVoiceInput.logVoiceInputDelivered(bestResult.length()); - mHints.registerVoiceResult(bestResult); - - if (ic != null) ic.beginBatchEdit(); // To avoid extra updates on committing older text - mService.commitTyped(ic); - EditingUtils.appendText(ic, bestResult); - if (ic != null) ic.endBatchEdit(); - - mVoiceInputHighlighted = true; - mWordToSuggestions.putAll(mVoiceResults.alternatives); - onCancelVoice(); - } - - public void switchToRecognitionStatusView(final Configuration configuration) { - if (!VOICE_INSTALLED) { - return; - } - mHandler.post(new Runnable() { - @Override - public void run() { -// mService.setCandidatesViewShown(false); - mRecognizing = true; - mVoiceInput.newView(); - View v = mVoiceInput.getView(); - - ViewParent p = v.getParent(); - if (p != null && p instanceof ViewGroup) { - ((ViewGroup) p).removeView(v); - } - - View keyboardView = KeyboardSwitcher.getInstance().getKeyboardView(); - - // The full height of the keyboard is difficult to calculate - // as the dimension is expressed in "mm" and not in "pixel" - // As we add mm, we don't know how the rounding is going to work - // thus we may end up with few pixels extra (or less). - if (keyboardView != null) { - View popupLayout = v.findViewById(R.id.popup_layout); - final int displayHeight = - mService.getResources().getDisplayMetrics().heightPixels; - final int currentHeight = popupLayout.getLayoutParams().height; - final int keyboardHeight = keyboardView.getHeight(); - if (mMinimumVoiceRecognitionViewHeightPixel > keyboardHeight - || mMinimumVoiceRecognitionViewHeightPixel > currentHeight) { - popupLayout.getLayoutParams().height = - mMinimumVoiceRecognitionViewHeightPixel; - } else if (keyboardHeight > currentHeight || keyboardHeight - > (displayHeight / RECOGNITIONVIEW_HEIGHT_THRESHOLD_RATIO)) { - popupLayout.getLayoutParams().height = keyboardHeight; - } - } - mService.setInputView(v); - mService.updateInputViewShown(); - - if (configuration != null) { - mVoiceInput.onConfigurationChanged(configuration); - } - }}); - } - - private void switchToLastInputMethod() { - if (!VOICE_INSTALLED) { - return; - } - final IBinder token = mService.getWindow().getWindow().getAttributes().token; - new AsyncTask<Void, Void, Boolean>() { - @Override - protected Boolean doInBackground(Void... params) { - return mImm.switchToLastInputMethod(token); - } - - @Override - protected void onPostExecute(Boolean result) { - // Calls in this method need to be done in the same thread as the thread which - // called switchToLastInputMethod() - if (!result) { - if (DEBUG) { - Log.d(TAG, "Couldn't switch back to last IME."); - } - // Because the current IME and subtype failed to switch to any other IME and - // subtype by switchToLastInputMethod, the current IME and subtype should keep - // being LatinIME and voice subtype in the next time. And for re-showing voice - // mode, the state of voice input should be reset and the voice view should be - // hidden. - mVoiceInput.reset(); - mService.requestHideSelf(0); - } else { - // Notify an event that the current subtype was changed. This event will be - // handled if "onCurrentInputMethodSubtypeChanged" can't be implemented - // when the API level is 10 or previous. - mService.notifyOnCurrentInputMethodSubtypeChanged(null); - } - } - }.execute(); - } - - private void reallyStartListening(boolean swipe) { - if (!VOICE_INSTALLED) { - return; - } - if (!mHasUsedVoiceInput) { - // The user has started a voice input, so remember that in the - // future (so we don't show the warning dialog after the first run). - SharedPreferences.Editor editor = - PreferenceManager.getDefaultSharedPreferences(mService).edit(); - editor.putBoolean(PREF_HAS_USED_VOICE_INPUT, true); - SharedPreferencesCompat.apply(editor); - mHasUsedVoiceInput = true; - } - - if (!mLocaleSupportedForVoiceInput && !mHasUsedVoiceInputUnsupportedLocale) { - // The user has started a voice input from an unsupported locale, so remember that - // in the future (so we don't show the warning dialog the next time they do this). - SharedPreferences.Editor editor = - PreferenceManager.getDefaultSharedPreferences(mService).edit(); - editor.putBoolean(PREF_HAS_USED_VOICE_INPUT_UNSUPPORTED_LOCALE, true); - SharedPreferencesCompat.apply(editor); - mHasUsedVoiceInputUnsupportedLocale = true; - } - - // Clear N-best suggestions - mService.clearSuggestions(); - - FieldContext context = makeFieldContext(); - mVoiceInput.startListening(context, swipe); - switchToRecognitionStatusView(null); - } - - public void startListening(final boolean swipe, IBinder token) { - if (!VOICE_INSTALLED) { - return; - } - // TODO: remove swipe which is no longer used. - if (needsToShowWarningDialog()) { - // Calls reallyStartListening if user clicks OK, does nothing if user clicks Cancel. - showVoiceWarningDialog(swipe, token); - } else { - reallyStartListening(swipe); - } - } - - private boolean fieldCanDoVoice(FieldContext fieldContext) { - return !mPasswordText - && mVoiceInput != null - && !mVoiceInput.isBlacklistedField(fieldContext); - } - - private boolean shouldShowVoiceButton(FieldContext fieldContext, EditorInfo attribute) { - @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); - return ENABLE_VOICE_BUTTON && fieldCanDoVoice(fieldContext) && !noMic - && SpeechRecognizer.isRecognitionAvailable(mService); - } - - public static boolean isRecognitionAvailable(Context context) { - return SpeechRecognizer.isRecognitionAvailable(context); - } - - public void loadSettings(EditorInfo attribute, SharedPreferences sp) { - if (!VOICE_INSTALLED) { - return; - } - mHasUsedVoiceInput = sp.getBoolean(PREF_HAS_USED_VOICE_INPUT, false); - mHasUsedVoiceInputUnsupportedLocale = - sp.getBoolean(PREF_HAS_USED_VOICE_INPUT_UNSUPPORTED_LOCALE, false); - - mLocaleSupportedForVoiceInput = SubtypeSwitcher.isVoiceSupported( - mService, SubtypeSwitcher.getInstance().getInputLocaleStr()); - - 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); - mVoiceButtonOnPrimary = voiceMode.equals(mService.getString(R.string.voice_mode_main)); - } - - public void destroy() { - if (!VOICE_INSTALLED) { - return; - } - if (mVoiceInput != null) { - mVoiceInput.destroy(); - } - } - - public void onStartInputView(IBinder keyboardViewToken) { - if (!VOICE_INSTALLED) { - return; - } - // If keyboardViewToken is null, keyboardView is not attached but voiceView is attached. - IBinder windowToken = keyboardViewToken != null ? keyboardViewToken - : mVoiceInput.getView().getWindowToken(); - // If IME is in voice mode, but still needs to show the voice warning dialog, - // 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(); - startListening(false, windowToken); - } - // If we have no token, onAttachedToWindow will take care of showing dialog and start - // listening. - } - - public void onAttachedToWindow() { - if (!VOICE_INSTALLED) { - return; - } - // After onAttachedToWindow, we can show the voice warning dialog. See startListening() - // above. - VoiceInputWrapper.getInstance().setVoiceInput(mVoiceInput, mSubtypeSwitcher); - } - - public void onConfigurationChanged(Configuration configuration) { - if (!VOICE_INSTALLED) { - return; - } - if (mRecognizing) { - switchToRecognitionStatusView(configuration); - } - } - - @Override - public void onCancelVoice() { - if (!VOICE_INSTALLED) { - return; - } - if (mRecognizing) { - if (mSubtypeSwitcher.isVoiceMode()) { - // If voice mode is being canceled within LatinIME (i.e. time-out or user - // cancellation etc.), onCancelVoice() will be called first. LatinIME thinks it's - // still in voice mode. LatinIME needs to call switchToLastInputMethod(). - // Note that onCancelVoice() will be called again from SubtypeSwitcher. - switchToLastInputMethod(); - } else if (mSubtypeSwitcher.isKeyboardMode()) { - // If voice mode is being canceled out of LatinIME (i.e. by user's IME switching or - // as a result of switchToLastInputMethod() etc.), - // onCurrentInputMethodSubtypeChanged() will be called first. LatinIME will know - // that it's in keyboard mode and SubtypeSwitcher will call onCancelVoice(). - mRecognizing = false; - mService.switchToKeyboardView(); - } - } - } - - @Override - public void onVoiceResults(List<String> candidates, - Map<String, List<CharSequence>> alternatives) { - if (!VOICE_INSTALLED) { - return; - } - if (!mRecognizing) { - return; - } - mVoiceResults.candidates = candidates; - mVoiceResults.alternatives = alternatives; - mHandler.updateVoiceResults(); - } - - private FieldContext makeFieldContext() { - SubtypeSwitcher switcher = SubtypeSwitcher.getInstance(); - return new FieldContext(mService.getCurrentInputConnection(), - mService.getCurrentInputEditorInfo(), switcher.getInputLocaleStr(), - switcher.getEnabledLanguages()); - } - - // TODO: make this private (proguard issue) - public static class VoiceResults { - List<String> candidates; - Map<String, List<CharSequence>> alternatives; - } - - public static class VoiceInputWrapper { - private static final VoiceInputWrapper sInputWrapperInstance = new VoiceInputWrapper(); - private VoiceInput mVoiceInput; - public static VoiceInputWrapper getInstance() { - return sInputWrapperInstance; - } - private void setVoiceInput(VoiceInput voiceInput, SubtypeSwitcher switcher) { - if (!VOICE_INSTALLED) { - return; - } - if (mVoiceInput == null && voiceInput != null) { - mVoiceInput = voiceInput; - } - switcher.setVoiceInputWrapper(this); - } - - private VoiceInputWrapper() { - } - - public void cancel() { - if (!VOICE_INSTALLED) { - return; - } - if (mVoiceInput != null) mVoiceInput.cancel(); - } - - public void reset() { - if (!VOICE_INSTALLED) { - return; - } - if (mVoiceInput != null) mVoiceInput.reset(); - } - } - - // A list of locales which are supported by default for voice input, unless we get a - // different list from Gservices. - private static final String DEFAULT_VOICE_INPUT_SUPPORTED_LOCALES = - "en " + - "en_US " + - "en_GB " + - "en_AU " + - "en_CA " + - "en_IE " + - "en_IN " + - "en_NZ " + - "en_SG " + - "en_ZA "; - - public static String getSupportedLocalesString (ContentResolver resolver) { - return SettingsUtil.getSettingsString( - resolver, - SettingsUtil.LATIN_IME_VOICE_INPUT_SUPPORTED_LOCALES, - DEFAULT_VOICE_INPUT_SUPPORTED_LOCALES); - } -} diff --git a/java/src/com/android/inputmethod/deprecated/compat/VoiceInputLoggerCompatUtils.java b/java/src/com/android/inputmethod/deprecated/compat/VoiceInputLoggerCompatUtils.java deleted file mode 100644 index 488390fbc..000000000 --- a/java/src/com/android/inputmethod/deprecated/compat/VoiceInputLoggerCompatUtils.java +++ /dev/null @@ -1,36 +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.deprecated.compat; - -import com.android.common.userhappiness.UserHappinessSignals; -import com.android.inputmethod.compat.CompatUtils; - -import java.lang.reflect.Method; - -public class VoiceInputLoggerCompatUtils { - public static final String EXTRA_TEXT_REPLACED_LENGTH = "length"; - public static final String EXTRA_BEFORE_N_BEST_CHOOSE = "before"; - public static final String EXTRA_AFTER_N_BEST_CHOOSE = "after"; - private static final Method METHOD_UserHappinessSignals_setHasVoiceLoggingInfo = - CompatUtils.getMethod(UserHappinessSignals.class, "setHasVoiceLoggingInfo", - boolean.class); - - public static void setHasVoiceLoggingInfoCompat(boolean hasLoggingInfo) { - CompatUtils.invoke(null, null, METHOD_UserHappinessSignals_setHasVoiceLoggingInfo, - hasLoggingInfo); - } -} diff --git a/java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java b/java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java deleted file mode 100644 index dbe7aec6a..000000000 --- a/java/src/com/android/inputmethod/deprecated/languageswitcher/InputLanguageSelection.java +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Copyright (C) 2008-2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * 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.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; -import android.os.Bundle; -import android.preference.CheckBoxPreference; -import android.preference.PreferenceActivity; -import android.preference.PreferenceGroup; -import android.preference.PreferenceManager; -import android.text.TextUtils; -import android.util.Pair; - -import java.io.IOException; -import java.text.Collator; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map.Entry; -import java.util.TreeMap; - -public class InputLanguageSelection extends PreferenceActivity { - - private SharedPreferences mPrefs; - private String mSelectedLanguages; - private HashMap<CheckBoxPreference, Locale> mLocaleMap = - new HashMap<CheckBoxPreference, Locale>(); - - private static class LocaleEntry implements Comparable<Object> { - private static Collator sCollator = Collator.getInstance(); - - private String mLabel; - public final Locale mLocale; - - public LocaleEntry(String label, Locale locale) { - this.mLabel = label; - this.mLocale = locale; - } - - @Override - public String toString() { - return this.mLabel; - } - - @Override - public int compareTo(Object o) { - return sCollator.compare(this.mLabel, ((LocaleEntry) o).mLabel); - } - } - - @Override - protected void onCreate(Bundle icicle) { - super.onCreate(icicle); - addPreferencesFromResource(R.xml.language_prefs); - // Get the settings preferences - mPrefs = PreferenceManager.getDefaultSharedPreferences(this); - mSelectedLanguages = mPrefs.getString(Settings.PREF_SELECTED_LANGUAGES, ""); - String[] languageList = mSelectedLanguages.split(","); - ArrayList<LocaleEntry> availableLanguages = getUniqueLocales(); - PreferenceGroup parent = getPreferenceScreen(); - final HashMap<Long, LocaleEntry> dictionaryIdLocaleMap = new HashMap<Long, LocaleEntry>(); - final TreeMap<LocaleEntry, Boolean> localeHasDictionaryMap = - new TreeMap<LocaleEntry, Boolean>(); - for (int i = 0; i < availableLanguages.size(); i++) { - LocaleEntry loc = availableLanguages.get(i); - Locale locale = loc.mLocale; - final Pair<Long, Boolean> hasDictionaryOrLayout = hasDictionaryOrLayout(locale); - final Long dictionaryId = hasDictionaryOrLayout.first; - final boolean hasLayout = hasDictionaryOrLayout.second; - final boolean hasDictionary = dictionaryId != null; - // Add this locale to the supported list if: - // 1) this locale has a layout/ 2) this locale has a dictionary - // If some locales have no layout but have a same dictionary, the shortest locale - // will be added to the supported list. - if (!hasLayout && !hasDictionary) { - continue; - } - if (hasLayout) { - localeHasDictionaryMap.put(loc, hasDictionary); - } - if (!hasDictionary) { - continue; - } - if (dictionaryIdLocaleMap.containsKey(dictionaryId)) { - final String newLocale = locale.toString(); - final String oldLocale = - dictionaryIdLocaleMap.get(dictionaryId).mLocale.toString(); - // Check if this locale is more appropriate to be the candidate of the input locale. - if (oldLocale.length() <= newLocale.length() && !hasLayout) { - // Don't add this new locale to the map<dictionary id, locale> if: - // 1) the new locale's name is longer than the existing one, and - // 2) the new locale doesn't have its layout - continue; - } - } - dictionaryIdLocaleMap.put(dictionaryId, loc); - } - - for (LocaleEntry localeEntry : dictionaryIdLocaleMap.values()) { - if (!localeHasDictionaryMap.containsKey(localeEntry)) { - localeHasDictionaryMap.put(localeEntry, true); - } - } - - for (Entry<LocaleEntry, Boolean> entry : localeHasDictionaryMap.entrySet()) { - final LocaleEntry localeEntry = entry.getKey(); - final Locale locale = localeEntry.mLocale; - final Boolean hasDictionary = entry.getValue(); - CheckBoxPreference pref = new CheckBoxPreference(this); - pref.setTitle(localeEntry.mLabel); - boolean checked = isLocaleIn(locale, languageList); - pref.setChecked(checked); - if (hasDictionary) { - pref.setSummary(R.string.has_dictionary); - } - mLocaleMap.put(pref, locale); - parent.addPreference(pref); - } - } - - private boolean isLocaleIn(Locale locale, String[] list) { - String lang = get5Code(locale); - for (int i = 0; i < list.length; i++) { - if (lang.equalsIgnoreCase(list[i])) return true; - } - return false; - } - - private Pair<Long, Boolean> hasDictionaryOrLayout(Locale locale) { - if (locale == null) return new Pair<Long, Boolean>(null, false); - final Resources res = getResources(); - final Locale saveLocale = LocaleUtils.setSystemLocale(res, locale); - final Long dictionaryId = DictionaryFactory.getDictionaryId(this, locale); - boolean hasLayout = false; - - try { - final String localeStr = locale.toString(); - final String[] layoutCountryCodes = KeyboardBuilder.parseKeyboardLocale( - this, R.xml.kbd_qwerty).split(",", -1); - if (!TextUtils.isEmpty(localeStr) && layoutCountryCodes.length > 0) { - for (String s : layoutCountryCodes) { - if (s.equals(localeStr)) { - hasLayout = true; - break; - } - } - } - } catch (XmlPullParserException e) { - } catch (IOException e) { - } - LocaleUtils.setSystemLocale(res, saveLocale); - return new Pair<Long, Boolean>(dictionaryId, hasLayout); - } - - private String get5Code(Locale locale) { - String country = locale.getCountry(); - return locale.getLanguage() - + (TextUtils.isEmpty(country) ? "" : "_" + country); - } - - @Override - protected void onResume() { - super.onResume(); - } - - @Override - protected void onPause() { - super.onPause(); - // Save the selected languages - String checkedLanguages = ""; - PreferenceGroup parent = getPreferenceScreen(); - int count = parent.getPreferenceCount(); - for (int i = 0; i < count; i++) { - CheckBoxPreference pref = (CheckBoxPreference) parent.getPreference(i); - if (pref.isChecked()) { - checkedLanguages += get5Code(mLocaleMap.get(pref)) + ","; - } - } - if (checkedLanguages.length() < 1) checkedLanguages = null; // Save null - Editor editor = mPrefs.edit(); - editor.putString(Settings.PREF_SELECTED_LANGUAGES, checkedLanguages); - SharedPreferencesCompat.apply(editor); - } - - public ArrayList<LocaleEntry> getUniqueLocales() { - String[] locales = getAssets().getLocales(); - Arrays.sort(locales); - ArrayList<LocaleEntry> uniqueLocales = new ArrayList<LocaleEntry>(); - - final int origSize = locales.length; - LocaleEntry[] preprocess = new LocaleEntry[origSize]; - int finalSize = 0; - for (int i = 0 ; i < origSize; i++ ) { - String s = locales[i]; - int len = s.length(); - String language = ""; - String country = ""; - if (len == 5) { - language = s.substring(0, 2); - country = s.substring(3, 5); - } else if (len < 5) { - language = s; - } - Locale l = new Locale(language, country); - - // Exclude languages that are not relevant to LatinIME - if (TextUtils.isEmpty(language)) { - continue; - } - - if (finalSize == 0) { - preprocess[finalSize++] = - new LocaleEntry(Utils.getFullDisplayName(l, false), l); - } else { - if (s.equals("zz_ZZ")) { - // ignore this locale - } else { - final String displayName = Utils.getFullDisplayName(l, false); - preprocess[finalSize++] = new LocaleEntry(displayName, l); - } - } - } - for (int i = 0; i < finalSize ; i++) { - uniqueLocales.add(preprocess[i]); - } - return uniqueLocales; - } -} diff --git a/java/src/com/android/inputmethod/deprecated/languageswitcher/LanguageSwitcher.java b/java/src/com/android/inputmethod/deprecated/languageswitcher/LanguageSwitcher.java deleted file mode 100644 index 7e2627c81..000000000 --- a/java/src/com/android/inputmethod/deprecated/languageswitcher/LanguageSwitcher.java +++ /dev/null @@ -1,234 +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.deprecated.languageswitcher; - -import com.android.inputmethod.compat.SharedPreferencesCompat; -import com.android.inputmethod.latin.LatinIME; -import com.android.inputmethod.latin.LatinImeLogger; -import com.android.inputmethod.latin.LocaleUtils; -import com.android.inputmethod.latin.Settings; - -import android.content.SharedPreferences; -import android.content.SharedPreferences.Editor; -import android.content.res.Configuration; -import android.text.TextUtils; -import android.util.Log; - -import java.util.ArrayList; -import java.util.Locale; - -/** - * Keeps track of list of selected input languages and the current - * input language that the user has selected. - */ -public class LanguageSwitcher { - private static final String TAG = LanguageSwitcher.class.getSimpleName(); - - @SuppressWarnings("unused") - private static final String KEYBOARD_MODE = "keyboard"; - private static final String[] EMPTY_STIRNG_ARRAY = new String[0]; - - private final ArrayList<Locale> mLocales = new ArrayList<Locale>(); - private final LatinIME mIme; - private String[] mSelectedLanguageArray = EMPTY_STIRNG_ARRAY; - private String mSelectedLanguages; - private int mCurrentIndex = 0; - private String mDefaultInputLanguage; - private Locale mDefaultInputLocale; - private Locale mSystemLocale; - - public LanguageSwitcher(LatinIME ime) { - mIme = ime; - } - - public int getLocaleCount() { - return mLocales.size(); - } - - public void onConfigurationChanged(Configuration conf, SharedPreferences prefs) { - final Locale newLocale = conf.locale; - if (!getSystemLocale().toString().equals(newLocale.toString())) { - loadLocales(prefs, newLocale); - } - } - - /** - * Loads the currently selected input languages from shared preferences. - * @param sp shared preference for getting the current input language and enabled languages - * @param systemLocale the current system locale, stored for changing the current input language - * based on the system current system locale. - * @return whether there was any change - */ - public boolean loadLocales(SharedPreferences sp, Locale systemLocale) { - if (LatinImeLogger.sDBG) { - Log.d(TAG, "load locales"); - } - if (systemLocale != null) { - setSystemLocale(systemLocale); - } - String selectedLanguages = sp.getString(Settings.PREF_SELECTED_LANGUAGES, null); - String currentLanguage = sp.getString(Settings.PREF_INPUT_LANGUAGE, null); - if (TextUtils.isEmpty(selectedLanguages)) { - mSelectedLanguageArray = EMPTY_STIRNG_ARRAY; - mSelectedLanguages = null; - loadDefaults(); - if (mLocales.size() == 0) { - return false; - } - mLocales.clear(); - return true; - } - if (selectedLanguages.equals(mSelectedLanguages)) { - return false; - } - mSelectedLanguageArray = selectedLanguages.split(","); - mSelectedLanguages = selectedLanguages; // Cache it for comparison later - constructLocales(); - mCurrentIndex = 0; - if (currentLanguage != null) { - // Find the index - mCurrentIndex = 0; - for (int i = 0; i < mLocales.size(); i++) { - if (mSelectedLanguageArray[i].equals(currentLanguage)) { - mCurrentIndex = i; - break; - } - } - // If we didn't find the index, use the first one - } - return true; - } - - private void loadDefaults() { - if (LatinImeLogger.sDBG) { - Log.d(TAG, "load default locales:"); - } - mDefaultInputLocale = mIme.getResources().getConfiguration().locale; - String country = mDefaultInputLocale.getCountry(); - mDefaultInputLanguage = mDefaultInputLocale.getLanguage() + - (TextUtils.isEmpty(country) ? "" : "_" + country); - } - - private void constructLocales() { - mLocales.clear(); - for (final String lang : mSelectedLanguageArray) { - final Locale locale = LocaleUtils.constructLocaleFromString(lang); - mLocales.add(locale); - } - } - - /** - * Returns the currently selected input language code, or the display language code if - * no specific locale was selected for input. - */ - public String getInputLanguage() { - if (getLocaleCount() == 0) return mDefaultInputLanguage; - - return mSelectedLanguageArray[mCurrentIndex]; - } - - /** - * Returns the list of enabled language codes. - */ - public String[] getEnabledLanguages(boolean allowImplicitlySelectedLanguages) { - if (mSelectedLanguageArray.length == 0 && allowImplicitlySelectedLanguages) { - return new String[] { mDefaultInputLanguage }; - } - return mSelectedLanguageArray; - } - - /** - * Returns the currently selected input locale, or the display locale if no specific - * locale was selected for input. - */ - public Locale getInputLocale() { - if (getLocaleCount() == 0) return mDefaultInputLocale; - - return mLocales.get(mCurrentIndex); - } - - private int nextLocaleIndex() { - final int size = mLocales.size(); - return (mCurrentIndex + 1) % size; - } - - private int prevLocaleIndex() { - final int size = mLocales.size(); - return (mCurrentIndex - 1 + size) % size; - } - - /** - * Returns the next input locale in the list. Wraps around to the beginning of the - * list if we're at the end of the list. - */ - public Locale getNextInputLocale() { - if (getLocaleCount() == 0) return mDefaultInputLocale; - return mLocales.get(nextLocaleIndex()); - } - - /** - * Sets the system locale (display UI) used for comparing with the input language. - * @param locale the locale of the system - */ - private void setSystemLocale(Locale locale) { - mSystemLocale = locale; - } - - /** - * Returns the system locale. - * @return the system locale - */ - private Locale getSystemLocale() { - return mSystemLocale; - } - - /** - * Returns the previous input locale in the list. Wraps around to the end of the - * list if we're at the beginning of the list. - */ - public Locale getPrevInputLocale() { - if (getLocaleCount() == 0) return mDefaultInputLocale; - return mLocales.get(prevLocaleIndex()); - } - - public void reset() { - mCurrentIndex = 0; - } - - public void next() { - mCurrentIndex = nextLocaleIndex(); - } - - public void prev() { - mCurrentIndex = prevLocaleIndex(); - } - - public void setLocale(String localeStr) { - final int N = mLocales.size(); - for (int i = 0; i < N; ++i) { - if (mLocales.get(i).toString().equals(localeStr)) { - mCurrentIndex = i; - } - } - } - - public void persist(SharedPreferences prefs) { - Editor editor = prefs.edit(); - editor.putString(Settings.PREF_INPUT_LANGUAGE, getInputLanguage()); - SharedPreferencesCompat.apply(editor); - } -} diff --git a/java/src/com/android/inputmethod/deprecated/voice/FieldContext.java b/java/src/com/android/inputmethod/deprecated/voice/FieldContext.java deleted file mode 100644 index 3c79cc218..000000000 --- a/java/src/com/android/inputmethod/deprecated/voice/FieldContext.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * 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.deprecated.voice; - -import android.os.Bundle; -import android.util.Log; -import android.view.inputmethod.EditorInfo; -import android.view.inputmethod.ExtractedText; -import android.view.inputmethod.ExtractedTextRequest; -import android.view.inputmethod.InputConnection; - -/** - * Represents information about a given text field, which can be passed - * to the speech recognizer as context information. - */ -public class FieldContext { - private static final boolean DBG = false; - - static final String LABEL = "label"; - static final String HINT = "hint"; - static final String PACKAGE_NAME = "packageName"; - static final String FIELD_ID = "fieldId"; - static final String FIELD_NAME = "fieldName"; - static final String SINGLE_LINE = "singleLine"; - static final String INPUT_TYPE = "inputType"; - static final String IME_OPTIONS = "imeOptions"; - static final String SELECTED_LANGUAGE = "selectedLanguage"; - static final String ENABLED_LANGUAGES = "enabledLanguages"; - - Bundle mFieldInfo; - - public FieldContext(InputConnection conn, EditorInfo info, - String selectedLanguage, String[] enabledLanguages) { - mFieldInfo = new Bundle(); - addEditorInfoToBundle(info, mFieldInfo); - addInputConnectionToBundle(conn, mFieldInfo); - addLanguageInfoToBundle(selectedLanguage, enabledLanguages, mFieldInfo); - if (DBG) Log.i("FieldContext", "Bundle = " + mFieldInfo.toString()); - } - - private static String safeToString(Object o) { - if (o == null) { - return ""; - } - return o.toString(); - } - - private static void addEditorInfoToBundle(EditorInfo info, Bundle bundle) { - if (info == null) { - return; - } - - bundle.putString(LABEL, safeToString(info.label)); - bundle.putString(HINT, safeToString(info.hintText)); - bundle.putString(PACKAGE_NAME, safeToString(info.packageName)); - bundle.putInt(FIELD_ID, info.fieldId); - bundle.putString(FIELD_NAME, safeToString(info.fieldName)); - bundle.putInt(INPUT_TYPE, info.inputType); - bundle.putInt(IME_OPTIONS, info.imeOptions); - } - - @SuppressWarnings("static-access") - private static void addInputConnectionToBundle( - InputConnection conn, Bundle bundle) { - if (conn == null) { - return; - } - - ExtractedText et = conn.getExtractedText(new ExtractedTextRequest(), 0); - if (et == null) { - return; - } - bundle.putBoolean(SINGLE_LINE, (et.flags & et.FLAG_SINGLE_LINE) > 0); - } - - private static void addLanguageInfoToBundle( - String selectedLanguage, String[] enabledLanguages, Bundle bundle) { - bundle.putString(SELECTED_LANGUAGE, selectedLanguage); - bundle.putStringArray(ENABLED_LANGUAGES, enabledLanguages); - } - - public Bundle getBundle() { - return mFieldInfo; - } - - @Override - public String toString() { - return mFieldInfo.toString(); - } -} diff --git a/java/src/com/android/inputmethod/deprecated/voice/Hints.java b/java/src/com/android/inputmethod/deprecated/voice/Hints.java deleted file mode 100644 index 17a19bf23..000000000 --- a/java/src/com/android/inputmethod/deprecated/voice/Hints.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * 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.deprecated.voice; - -import com.android.inputmethod.compat.SharedPreferencesCompat; -import com.android.inputmethod.latin.R; - -import android.content.ContentResolver; -import android.content.Context; -import android.content.SharedPreferences; -import android.view.inputmethod.InputConnection; - -import java.util.Calendar; -import java.util.HashMap; -import java.util.Map; - -/** - * Logic to determine when to display hints on usage to the user. - */ -public class Hints { - public interface Display { - public void showHint(int viewResource); - } - - private static final String PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN = - "voice_hint_num_unique_days_shown"; - private static final String PREF_VOICE_HINT_LAST_TIME_SHOWN = - "voice_hint_last_time_shown"; - private static final String PREF_VOICE_INPUT_LAST_TIME_USED = - "voice_input_last_time_used"; - private static final String PREF_VOICE_PUNCTUATION_HINT_VIEW_COUNT = - "voice_punctuation_hint_view_count"; - private static final int DEFAULT_SWIPE_HINT_MAX_DAYS_TO_SHOW = 7; - private static final int DEFAULT_PUNCTUATION_HINT_MAX_DISPLAYS = 7; - - private final Context mContext; - private final SharedPreferences mPrefs; - private final Display mDisplay; - private boolean mVoiceResultContainedPunctuation; - private int mSwipeHintMaxDaysToShow; - private int mPunctuationHintMaxDisplays; - - // Only show punctuation hint if voice result did not contain punctuation. - static final Map<CharSequence, String> SPEAKABLE_PUNCTUATION - = new HashMap<CharSequence, String>(); - static { - SPEAKABLE_PUNCTUATION.put(",", "comma"); - SPEAKABLE_PUNCTUATION.put(".", "period"); - SPEAKABLE_PUNCTUATION.put("?", "question mark"); - } - - public Hints(Context context, SharedPreferences prefs, Display display) { - mContext = context; - mPrefs = prefs; - mDisplay = display; - - ContentResolver cr = mContext.getContentResolver(); - mSwipeHintMaxDaysToShow = SettingsUtil.getSettingsInt( - cr, - SettingsUtil.LATIN_IME_VOICE_INPUT_SWIPE_HINT_MAX_DAYS, - DEFAULT_SWIPE_HINT_MAX_DAYS_TO_SHOW); - mPunctuationHintMaxDisplays = SettingsUtil.getSettingsInt( - cr, - SettingsUtil.LATIN_IME_VOICE_INPUT_PUNCTUATION_HINT_MAX_DISPLAYS, - DEFAULT_PUNCTUATION_HINT_MAX_DISPLAYS); - } - - public boolean showSwipeHintIfNecessary(boolean fieldRecommended) { - if (fieldRecommended && shouldShowSwipeHint()) { - showHint(R.layout.voice_swipe_hint); - return true; - } - - return false; - } - - public boolean showPunctuationHintIfNecessary(InputConnection ic) { - if (!mVoiceResultContainedPunctuation - && ic != null - && getAndIncrementPref(PREF_VOICE_PUNCTUATION_HINT_VIEW_COUNT) - < mPunctuationHintMaxDisplays) { - CharSequence charBeforeCursor = ic.getTextBeforeCursor(1, 0); - if (SPEAKABLE_PUNCTUATION.containsKey(charBeforeCursor)) { - showHint(R.layout.voice_punctuation_hint); - return true; - } - } - - return false; - } - - public void registerVoiceResult(String text) { - // Update the current time as the last time voice input was used. - SharedPreferences.Editor editor = mPrefs.edit(); - editor.putLong(PREF_VOICE_INPUT_LAST_TIME_USED, System.currentTimeMillis()); - SharedPreferencesCompat.apply(editor); - - mVoiceResultContainedPunctuation = false; - for (CharSequence s : SPEAKABLE_PUNCTUATION.keySet()) { - if (text.indexOf(s.toString()) >= 0) { - mVoiceResultContainedPunctuation = true; - break; - } - } - } - - private boolean shouldShowSwipeHint() { - final SharedPreferences prefs = mPrefs; - - int numUniqueDaysShown = prefs.getInt(PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN, 0); - - // If we've already shown the hint for enough days, we'll return false. - if (numUniqueDaysShown < mSwipeHintMaxDaysToShow) { - - long lastTimeVoiceWasUsed = prefs.getLong(PREF_VOICE_INPUT_LAST_TIME_USED, 0); - - // If the user has used voice today, we'll return false. (We don't show the hint on - // any day that the user has already used voice.) - if (!isFromToday(lastTimeVoiceWasUsed)) { - return true; - } - } - - return false; - } - - /** - * Determines whether the provided time is from some time today (i.e., this day, month, - * and year). - */ - private boolean isFromToday(long timeInMillis) { - if (timeInMillis == 0) return false; - - Calendar today = Calendar.getInstance(); - today.setTimeInMillis(System.currentTimeMillis()); - - Calendar timestamp = Calendar.getInstance(); - timestamp.setTimeInMillis(timeInMillis); - - return (today.get(Calendar.YEAR) == timestamp.get(Calendar.YEAR) && - today.get(Calendar.DAY_OF_MONTH) == timestamp.get(Calendar.DAY_OF_MONTH) && - today.get(Calendar.MONTH) == timestamp.get(Calendar.MONTH)); - } - - private void showHint(int hintViewResource) { - final SharedPreferences prefs = mPrefs; - - int numUniqueDaysShown = prefs.getInt(PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN, 0); - long lastTimeHintWasShown = prefs.getLong(PREF_VOICE_HINT_LAST_TIME_SHOWN, 0); - - // If this is the first time the hint is being shown today, increase the saved values - // to represent that. We don't need to increase the last time the hint was shown unless - // it is a different day from the current value. - if (!isFromToday(lastTimeHintWasShown)) { - SharedPreferences.Editor editor = prefs.edit(); - editor.putInt(PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN, numUniqueDaysShown + 1); - editor.putLong(PREF_VOICE_HINT_LAST_TIME_SHOWN, System.currentTimeMillis()); - SharedPreferencesCompat.apply(editor); - } - - if (mDisplay != null) { - mDisplay.showHint(hintViewResource); - } - } - - private int getAndIncrementPref(String pref) { - final SharedPreferences prefs = mPrefs; - int value = prefs.getInt(pref, 0); - SharedPreferences.Editor editor = prefs.edit(); - editor.putInt(pref, value + 1); - SharedPreferencesCompat.apply(editor); - return value; - } -} diff --git a/java/src/com/android/inputmethod/deprecated/voice/RecognitionView.java b/java/src/com/android/inputmethod/deprecated/voice/RecognitionView.java deleted file mode 100644 index 71d15dc3d..000000000 --- a/java/src/com/android/inputmethod/deprecated/voice/RecognitionView.java +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * 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.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; -import android.graphics.Canvas; -import android.graphics.CornerPathEffect; -import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.PathEffect; -import android.graphics.drawable.Drawable; -import android.os.Handler; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.ProgressBar; -import android.widget.TextView; - -import java.io.ByteArrayOutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.ShortBuffer; -import java.util.Locale; - -/** - * The user interface for the "Speak now" and "working" states. - * Displays a recognition dialog (with waveform, voice meter, etc.), - * plays beeps, shows errors, etc. - */ -public class RecognitionView { - private static final String TAG = "RecognitionView"; - - private Handler mUiHandler; // Reference to UI thread - private View mView; - private Context mContext; - - private TextView mText; - private ImageView mImage; - private View mProgress; - private SoundIndicator mSoundIndicator; - private TextView mLanguage; - private Button mButton; - - private Drawable mInitializing; - private Drawable mError; - - private static final int INIT = 0; - private static final int LISTENING = 1; - private static final int WORKING = 2; - private static final int READY = 3; - - private int mState = INIT; - - private final View mPopupLayout; - - private final Drawable mListeningBorder; - private final Drawable mWorkingBorder; - private final Drawable mErrorBorder; - - public RecognitionView(Context context, OnClickListener clickListener) { - mUiHandler = new Handler(); - - LayoutInflater inflater = (LayoutInflater) context.getSystemService( - Context.LAYOUT_INFLATER_SERVICE); - - mView = inflater.inflate(R.layout.recognition_status, null); - - mPopupLayout= mView.findViewById(R.id.popup_layout); - - // Pre-load volume level images - Resources r = context.getResources(); - - mListeningBorder = r.getDrawable(R.drawable.vs_dialog_red); - mWorkingBorder = r.getDrawable(R.drawable.vs_dialog_blue); - mErrorBorder = r.getDrawable(R.drawable.vs_dialog_yellow); - - mInitializing = r.getDrawable(R.drawable.mic_slash); - mError = r.getDrawable(R.drawable.caution); - - mImage = (ImageView) mView.findViewById(R.id.image); - mProgress = mView.findViewById(R.id.progress); - mSoundIndicator = (SoundIndicator) mView.findViewById(R.id.sound_indicator); - - mButton = (Button) mView.findViewById(R.id.button); - mButton.setOnClickListener(clickListener); - mText = (TextView) mView.findViewById(R.id.text); - mLanguage = (TextView) mView.findViewById(R.id.language); - - mContext = context; - } - - public View getView() { - return mView; - } - - public void restoreState() { - mUiHandler.post(new Runnable() { - @Override - public void run() { - // Restart the spinner - if (mState == WORKING) { - ((ProgressBar) mProgress).setIndeterminate(false); - ((ProgressBar) mProgress).setIndeterminate(true); - } - } - }); - } - - public void showInitializing() { - mUiHandler.post(new Runnable() { - @Override - public void run() { - mState = INIT; - prepareDialog(mContext.getText(R.string.voice_initializing), mInitializing, - mContext.getText(R.string.cancel)); - } - }); - } - - public void showListening() { - Log.d(TAG, "#showListening"); - mUiHandler.post(new Runnable() { - @Override - public void run() { - mState = LISTENING; - prepareDialog(mContext.getText(R.string.voice_listening), null, - mContext.getText(R.string.cancel)); - } - }); - } - - public void updateVoiceMeter(float rmsdB) { - mSoundIndicator.setRmsdB(rmsdB); - } - - public void showError(final String message) { - mUiHandler.post(new Runnable() { - @Override - public void run() { - mState = READY; - prepareDialog(message, mError, mContext.getText(R.string.ok)); - } - }); - } - - public void showWorking( - final ByteArrayOutputStream waveBuffer, - final int speechStartPosition, - final int speechEndPosition) { - mUiHandler.post(new Runnable() { - @Override - public void run() { - mState = WORKING; - prepareDialog(mContext.getText(R.string.voice_working), null, mContext - .getText(R.string.cancel)); - final ShortBuffer buf = ByteBuffer.wrap(waveBuffer.toByteArray()).order( - ByteOrder.nativeOrder()).asShortBuffer(); - buf.position(0); - waveBuffer.reset(); - showWave(buf, speechStartPosition / 2, speechEndPosition / 2); - } - }); - } - - private void prepareDialog(CharSequence text, Drawable image, - CharSequence btnTxt) { - - /* - * The mic of INIT and of LISTENING has to be displayed in the same position. To accomplish - * that, some text visibility are not set as GONE but as INVISIBLE. - */ - switch (mState) { - case INIT: - mText.setVisibility(View.INVISIBLE); - - mProgress.setVisibility(View.GONE); - - mImage.setVisibility(View.VISIBLE); - mImage.setImageResource(R.drawable.mic_slash); - - mSoundIndicator.setVisibility(View.GONE); - mSoundIndicator.stop(); - - mLanguage.setVisibility(View.INVISIBLE); - - mPopupLayout.setBackgroundDrawable(mListeningBorder); - break; - case LISTENING: - mText.setVisibility(View.VISIBLE); - mText.setText(text); - - mProgress.setVisibility(View.GONE); - - mImage.setVisibility(View.GONE); - - mSoundIndicator.setVisibility(View.VISIBLE); - mSoundIndicator.start(); - - Locale locale = SubtypeSwitcher.getInstance().getInputLocale(); - - mLanguage.setVisibility(View.VISIBLE); - mLanguage.setText(Utils.getFullDisplayName(locale, true)); - - mPopupLayout.setBackgroundDrawable(mListeningBorder); - break; - case WORKING: - - mText.setVisibility(View.VISIBLE); - mText.setText(text); - - mProgress.setVisibility(View.VISIBLE); - - mImage.setVisibility(View.VISIBLE); - - mSoundIndicator.setVisibility(View.GONE); - mSoundIndicator.stop(); - - mLanguage.setVisibility(View.GONE); - - mPopupLayout.setBackgroundDrawable(mWorkingBorder); - break; - case READY: - mText.setVisibility(View.VISIBLE); - mText.setText(text); - - mProgress.setVisibility(View.GONE); - - mImage.setVisibility(View.VISIBLE); - mImage.setImageResource(R.drawable.caution); - - mSoundIndicator.setVisibility(View.GONE); - mSoundIndicator.stop(); - - mLanguage.setVisibility(View.GONE); - - mPopupLayout.setBackgroundDrawable(mErrorBorder); - break; - default: - Log.w(TAG, "Unknown state " + mState); - } - mPopupLayout.requestLayout(); - mButton.setText(btnTxt); - } - - /** - * @return an average abs of the specified buffer. - */ - private static int getAverageAbs(ShortBuffer buffer, int start, int i, int npw) { - int from = start + i * npw; - int end = from + npw; - int total = 0; - for (int x = from; x < end; x++) { - total += Math.abs(buffer.get(x)); - } - return total / npw; - } - - - /** - * Shows waveform of input audio. - * - * Copied from version in VoiceSearch's RecognitionActivity. - * - * TODO: adjust stroke width based on the size of data. - * TODO: use dip rather than pixels. - */ - private void showWave(ShortBuffer waveBuffer, int startPosition, int endPosition) { - final int w = ((View) mImage.getParent()).getWidth(); - final int h = ((View) mImage.getParent()).getHeight(); - if (w <= 0 || h <= 0) { - // view is not visible this time. Skip drawing. - return; - } - final Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); - final Canvas c = new Canvas(b); - final Paint paint = new Paint(); - paint.setColor(0xFFFFFFFF); // 0xAARRGGBB - paint.setAntiAlias(true); - paint.setStyle(Paint.Style.STROKE); - paint.setAlpha(80); - - final PathEffect effect = new CornerPathEffect(3); - paint.setPathEffect(effect); - - final int numSamples = waveBuffer.remaining(); - int endIndex; - if (endPosition == 0) { - endIndex = numSamples; - } else { - endIndex = Math.min(endPosition, numSamples); - } - - int startIndex = startPosition - 2000; // include 250ms before speech - if (startIndex < 0) { - startIndex = 0; - } - final int numSamplePerWave = 200; // 8KHz 25ms = 200 samples - final float scale = 10.0f / 65536.0f; - - final int count = (endIndex - startIndex) / numSamplePerWave; - final float deltaX = 1.0f * w / count; - int yMax = h / 2; - Path path = new Path(); - c.translate(0, yMax); - float x = 0; - path.moveTo(x, 0); - for (int i = 0; i < count; i++) { - final int avabs = getAverageAbs(waveBuffer, startIndex, i , numSamplePerWave); - int sign = ( (i & 01) == 0) ? -1 : 1; - final float y = Math.min(yMax, avabs * h * scale) * sign; - path.lineTo(x, y); - x += deltaX; - path.lineTo(x, y); - } - if (deltaX > 4) { - paint.setStrokeWidth(2); - } else { - paint.setStrokeWidth(Math.max(0, (int) (deltaX -.05))); - } - c.drawPath(path, paint); - mImage.setImageBitmap(b); - } - - public void finish() { - mUiHandler.post(new Runnable() { - @Override - public void run() { - mSoundIndicator.stop(); - } - }); - } -} diff --git a/java/src/com/android/inputmethod/deprecated/voice/SettingsUtil.java b/java/src/com/android/inputmethod/deprecated/voice/SettingsUtil.java deleted file mode 100644 index 855a09a1d..000000000 --- a/java/src/com/android/inputmethod/deprecated/voice/SettingsUtil.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * 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.deprecated.voice; - -import android.content.ContentResolver; -import android.provider.Settings; - -/** - * Utility for retrieving settings from Settings.Secure. - */ -public class SettingsUtil { - /** - * A whitespace-separated list of supported locales for voice input from the keyboard. - */ - public static final String LATIN_IME_VOICE_INPUT_SUPPORTED_LOCALES = - "latin_ime_voice_input_supported_locales"; - - /** - * A whitespace-separated list of recommended app packages for voice input from the - * keyboard. - */ - public static final String LATIN_IME_VOICE_INPUT_RECOMMENDED_PACKAGES = - "latin_ime_voice_input_recommended_packages"; - - /** - * The maximum number of unique days to show the swipe hint for voice input. - */ - public static final String LATIN_IME_VOICE_INPUT_SWIPE_HINT_MAX_DAYS = - "latin_ime_voice_input_swipe_hint_max_days"; - - /** - * The maximum number of times to show the punctuation hint for voice input. - */ - public static final String LATIN_IME_VOICE_INPUT_PUNCTUATION_HINT_MAX_DISPLAYS = - "latin_ime_voice_input_punctuation_hint_max_displays"; - - /** - * Endpointer parameters for voice input from the keyboard. - */ - public static final String LATIN_IME_SPEECH_MINIMUM_LENGTH_MILLIS = - "latin_ime_speech_minimum_length_millis"; - public static final String LATIN_IME_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS = - "latin_ime_speech_input_complete_silence_length_millis"; - public static final String LATIN_IME_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS = - "latin_ime_speech_input_possibly_complete_silence_length_millis"; - - /** - * Min and max volume levels that can be displayed on the "speak now" screen. - */ - public static final String LATIN_IME_MIN_MICROPHONE_LEVEL = - "latin_ime_min_microphone_level"; - public static final String LATIN_IME_MAX_MICROPHONE_LEVEL = - "latin_ime_max_microphone_level"; - - /** - * The number of sentence-level alternates to request of the server. - */ - public static final String LATIN_IME_MAX_VOICE_RESULTS = "latin_ime_max_voice_results"; - - /** - * Get a string-valued setting. - * - * @param cr The content resolver to use - * @param key The setting to look up - * @param defaultValue The default value to use if none can be found - * @return The value of the setting, or defaultValue if it couldn't be found - */ - public static String getSettingsString(ContentResolver cr, String key, String defaultValue) { - String result = Settings.Secure.getString(cr, key); - return (result == null) ? defaultValue : result; - } - - /** - * Get an int-valued setting. - * - * @param cr The content resolver to use - * @param key The setting to look up - * @param defaultValue The default value to use if the setting couldn't be found or parsed - * @return The value of the setting, or defaultValue if it couldn't be found or parsed - */ - public static int getSettingsInt(ContentResolver cr, String key, int defaultValue) { - return Settings.Secure.getInt(cr, key, defaultValue); - } - - /** - * Get a float-valued setting. - * - * @param cr The content resolver to use - * @param key The setting to look up - * @param defaultValue The default value to use if the setting couldn't be found or parsed - * @return The value of the setting, or defaultValue if it couldn't be found or parsed - */ - public static float getSettingsFloat(ContentResolver cr, String key, float defaultValue) { - return Settings.Secure.getFloat(cr, key, defaultValue); - } -} diff --git a/java/src/com/android/inputmethod/deprecated/voice/SoundIndicator.java b/java/src/com/android/inputmethod/deprecated/voice/SoundIndicator.java deleted file mode 100644 index 25b314085..000000000 --- a/java/src/com/android/inputmethod/deprecated/voice/SoundIndicator.java +++ /dev/null @@ -1,155 +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.deprecated.voice; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Bitmap.Config; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffXfermode; -import android.graphics.Rect; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.os.Handler; -import android.util.AttributeSet; -import android.widget.ImageView; - -import com.android.inputmethod.latin.R; - -/** - * A widget which shows the volume of audio using a microphone icon - */ -public class SoundIndicator extends ImageView { - @SuppressWarnings("unused") - private static final String TAG = "SoundIndicator"; - - private static final float UP_SMOOTHING_FACTOR = 0.9f; - private static final float DOWN_SMOOTHING_FACTOR = 0.4f; - - private static final float AUDIO_METER_MIN_DB = 7.0f; - private static final float AUDIO_METER_DB_RANGE = 20.0f; - - private static final long FRAME_DELAY = 50; - - private Bitmap mDrawingBuffer; - private Canvas mBufferCanvas; - private Bitmap mEdgeBitmap; - private float mLevel = 0.0f; - private Drawable mFrontDrawable; - private Paint mClearPaint; - private Paint mMultPaint; - private int mEdgeBitmapOffset; - - private Handler mHandler; - - private Runnable mDrawFrame = new Runnable() { - public void run() { - invalidate(); - mHandler.postDelayed(mDrawFrame, FRAME_DELAY); - } - }; - - public SoundIndicator(Context context) { - this(context, null); - } - - public SoundIndicator(Context context, AttributeSet attrs) { - super(context, attrs); - - mFrontDrawable = getDrawable(); - BitmapDrawable edgeDrawable = - (BitmapDrawable) context.getResources().getDrawable(R.drawable.vs_popup_mic_edge); - mEdgeBitmap = edgeDrawable.getBitmap(); - mEdgeBitmapOffset = mEdgeBitmap.getHeight() / 2; - - mDrawingBuffer = - Bitmap.createBitmap(mFrontDrawable.getIntrinsicWidth(), - mFrontDrawable.getIntrinsicHeight(), Config.ARGB_8888); - - mBufferCanvas = new Canvas(mDrawingBuffer); - - // Initialize Paints. - mClearPaint = new Paint(); - mClearPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); - - mMultPaint = new Paint(); - mMultPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY)); - - mHandler = new Handler(); - } - - @Override - public void onDraw(Canvas canvas) { - //super.onDraw(canvas); - - float w = getWidth(); - float h = getHeight(); - - // Clear the buffer canvas - mBufferCanvas.drawRect(0, 0, w, h, mClearPaint); - - // Set its clip so we don't draw the front image all the way to the top - Rect clip = new Rect(0, - (int) ((1.0 - mLevel) * (h + mEdgeBitmapOffset)) - mEdgeBitmapOffset, - (int) w, - (int) h); - - mBufferCanvas.save(); - mBufferCanvas.clipRect(clip); - - // Draw the front image - mFrontDrawable.setBounds(new Rect(0, 0, (int) w, (int) h)); - mFrontDrawable.draw(mBufferCanvas); - - mBufferCanvas.restore(); - - // Draw the edge image on top of the buffer image with a multiply mode - mBufferCanvas.drawBitmap(mEdgeBitmap, 0, clip.top, mMultPaint); - - // Draw the buffer image (on top of the background image) - canvas.drawBitmap(mDrawingBuffer, 0, 0, null); - } - - /** - * Sets the sound level - * - * @param rmsdB The level of the sound, in dB. - */ - public void setRmsdB(float rmsdB) { - float level = ((rmsdB - AUDIO_METER_MIN_DB) / AUDIO_METER_DB_RANGE); - - level = Math.min(Math.max(0.0f, level), 1.0f); - - // We smooth towards the new level - if (level > mLevel) { - mLevel = (level - mLevel) * UP_SMOOTHING_FACTOR + mLevel; - } else { - mLevel = (level - mLevel) * DOWN_SMOOTHING_FACTOR + mLevel; - } - invalidate(); - } - - public void start() { - mHandler.post(mDrawFrame); - } - - public void stop() { - mHandler.removeCallbacks(mDrawFrame); - } -} diff --git a/java/src/com/android/inputmethod/deprecated/voice/VoiceInput.java b/java/src/com/android/inputmethod/deprecated/voice/VoiceInput.java deleted file mode 100644 index 8969a2168..000000000 --- a/java/src/com/android/inputmethod/deprecated/voice/VoiceInput.java +++ /dev/null @@ -1,692 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * 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.deprecated.voice; - -import com.android.inputmethod.latin.EditingUtils; -import com.android.inputmethod.latin.LatinImeLogger; -import com.android.inputmethod.latin.R; -import com.android.inputmethod.latin.StaticInnerHandlerWrapper; - -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import android.content.res.Configuration; -import android.os.Build; -import android.os.Bundle; -import android.os.Message; -import android.os.Parcelable; -import android.speech.RecognitionListener; -import android.speech.RecognizerIntent; -import android.speech.SpeechRecognizer; -import android.util.Log; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.inputmethod.InputConnection; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -/** - * Speech recognition input, including both user interface and a background - * process to stream audio to the network recognizer. This class supplies a - * View (getView()), which it updates as recognition occurs. The user of this - * class is responsible for making the view visible to the user, as well as - * handling various events returned through UiListener. - */ -public class VoiceInput implements OnClickListener { - private static final String TAG = "VoiceInput"; - private static final String EXTRA_RECOGNITION_CONTEXT = - "android.speech.extras.RECOGNITION_CONTEXT"; - private static final String EXTRA_CALLING_PACKAGE = "calling_package"; - private static final String EXTRA_ALTERNATES = "android.speech.extra.ALTERNATES"; - private static final int MAX_ALT_LIST_LENGTH = 6; - private static boolean DBG = LatinImeLogger.sDBG; - - private static final String DEFAULT_RECOMMENDED_PACKAGES = - "com.android.mms " + - "com.google.android.gm " + - "com.google.android.talk " + - "com.google.android.apps.googlevoice " + - "com.android.email " + - "com.android.browser "; - - // WARNING! Before enabling this, fix the problem with calling getExtractedText() in - // landscape view. It causes Extracted text updates to be rejected due to a token mismatch - public static boolean ENABLE_WORD_CORRECTIONS = true; - - // Dummy word suggestion which means "delete current word" - public static final String DELETE_SYMBOL = " \u00D7 "; // times symbol - - private Whitelist mRecommendedList; - private Whitelist mBlacklist; - - private VoiceInputLogger mLogger; - - // Names of a few extras defined in VoiceSearch's RecognitionController - // Note, the version of voicesearch that shipped in Froyo returns the raw - // RecognitionClientAlternates protocol buffer under the key "alternates", - // so a VS market update must be installed on Froyo devices in order to see - // alternatives. - private static final String ALTERNATES_BUNDLE = "alternates_bundle"; - - // This is copied from the VoiceSearch app. - @SuppressWarnings("unused") - private static final class AlternatesBundleKeys { - public static final String ALTERNATES = "alternates"; - public static final String CONFIDENCE = "confidence"; - public static final String LENGTH = "length"; - public static final String MAX_SPAN_LENGTH = "max_span_length"; - public static final String SPANS = "spans"; - public static final String SPAN_KEY_DELIMITER = ":"; - public static final String START = "start"; - public static final String TEXT = "text"; - } - - // Names of a few intent extras defined in VoiceSearch's RecognitionService. - // These let us tweak the endpointer parameters. - private static final String EXTRA_SPEECH_MINIMUM_LENGTH_MILLIS = - "android.speech.extras.SPEECH_INPUT_MINIMUM_LENGTH_MILLIS"; - private static final String EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS = - "android.speech.extras.SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS"; - private static final String EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS = - "android.speech.extras.SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS"; - - // The usual endpointer default value for input complete silence length is 0.5 seconds, - // but that's used for things like voice search. For dictation-like voice input like this, - // we go with a more liberal value of 1 second. This value will only be used if a value - // is not provided from Gservices. - private static final String INPUT_COMPLETE_SILENCE_LENGTH_DEFAULT_VALUE_MILLIS = "1000"; - - // Used to record part of that state for logging purposes. - public static final int DEFAULT = 0; - public static final int LISTENING = 1; - public static final int WORKING = 2; - public static final int ERROR = 3; - - private int mAfterVoiceInputDeleteCount = 0; - private int mAfterVoiceInputInsertCount = 0; - private int mAfterVoiceInputInsertPunctuationCount = 0; - private int mAfterVoiceInputCursorPos = 0; - private int mAfterVoiceInputSelectionSpan = 0; - - private int mState = DEFAULT; - - private final static int MSG_RESET = 1; - - private final UIHandler mHandler = new UIHandler(this); - - private static class UIHandler extends StaticInnerHandlerWrapper<VoiceInput> { - public UIHandler(VoiceInput outerInstance) { - super(outerInstance); - } - - @Override - public void handleMessage(Message msg) { - if (msg.what == MSG_RESET) { - final VoiceInput voiceInput = getOuterInstance(); - voiceInput.mState = DEFAULT; - voiceInput.mRecognitionView.finish(); - voiceInput.mUiListener.onCancelVoice(); - } - } - }; - - /** - * Events relating to the recognition UI. You must implement these. - */ - public interface UiListener { - - /** - * @param recognitionResults a set of transcripts for what the user - * spoke, sorted by likelihood. - */ - public void onVoiceResults( - List<String> recognitionResults, - Map<String, List<CharSequence>> alternatives); - - /** - * Called when the user cancels speech recognition. - */ - public void onCancelVoice(); - } - - private SpeechRecognizer mSpeechRecognizer; - private RecognitionListener mRecognitionListener; - private RecognitionView mRecognitionView; - private UiListener mUiListener; - private Context mContext; - - /** - * @param context the service or activity in which we're running. - * @param uiHandler object to receive events from VoiceInput. - */ - public VoiceInput(Context context, UiListener uiHandler) { - mLogger = VoiceInputLogger.getLogger(context); - mRecognitionListener = new ImeRecognitionListener(); - mSpeechRecognizer = SpeechRecognizer.createSpeechRecognizer(context); - mSpeechRecognizer.setRecognitionListener(mRecognitionListener); - mUiListener = uiHandler; - mContext = context; - newView(); - - String recommendedPackages = SettingsUtil.getSettingsString( - context.getContentResolver(), - SettingsUtil.LATIN_IME_VOICE_INPUT_RECOMMENDED_PACKAGES, - DEFAULT_RECOMMENDED_PACKAGES); - - mRecommendedList = new Whitelist(); - for (String recommendedPackage : recommendedPackages.split("\\s+")) { - mRecommendedList.addApp(recommendedPackage); - } - - mBlacklist = new Whitelist(); - mBlacklist.addApp("com.google.android.setupwizard"); - } - - public void setCursorPos(int pos) { - mAfterVoiceInputCursorPos = pos; - } - - public int getCursorPos() { - return mAfterVoiceInputCursorPos; - } - - public void setSelectionSpan(int span) { - mAfterVoiceInputSelectionSpan = span; - } - - public int getSelectionSpan() { - return mAfterVoiceInputSelectionSpan; - } - - public void incrementTextModificationDeleteCount(int count){ - mAfterVoiceInputDeleteCount += count; - // Send up intents for other text modification types - if (mAfterVoiceInputInsertCount > 0) { - logTextModifiedByTypingInsertion(mAfterVoiceInputInsertCount); - mAfterVoiceInputInsertCount = 0; - } - if (mAfterVoiceInputInsertPunctuationCount > 0) { - logTextModifiedByTypingInsertionPunctuation(mAfterVoiceInputInsertPunctuationCount); - mAfterVoiceInputInsertPunctuationCount = 0; - } - - } - - public void incrementTextModificationInsertCount(int count){ - mAfterVoiceInputInsertCount += count; - if (mAfterVoiceInputSelectionSpan > 0) { - // If text was highlighted before inserting the char, count this as - // a delete. - mAfterVoiceInputDeleteCount += mAfterVoiceInputSelectionSpan; - } - // Send up intents for other text modification types - if (mAfterVoiceInputDeleteCount > 0) { - logTextModifiedByTypingDeletion(mAfterVoiceInputDeleteCount); - mAfterVoiceInputDeleteCount = 0; - } - if (mAfterVoiceInputInsertPunctuationCount > 0) { - logTextModifiedByTypingInsertionPunctuation(mAfterVoiceInputInsertPunctuationCount); - mAfterVoiceInputInsertPunctuationCount = 0; - } - } - - public void incrementTextModificationInsertPunctuationCount(int count){ - mAfterVoiceInputInsertPunctuationCount += count; - if (mAfterVoiceInputSelectionSpan > 0) { - // If text was highlighted before inserting the char, count this as - // a delete. - mAfterVoiceInputDeleteCount += mAfterVoiceInputSelectionSpan; - } - // Send up intents for aggregated non-punctuation insertions - if (mAfterVoiceInputDeleteCount > 0) { - logTextModifiedByTypingDeletion(mAfterVoiceInputDeleteCount); - mAfterVoiceInputDeleteCount = 0; - } - if (mAfterVoiceInputInsertCount > 0) { - logTextModifiedByTypingInsertion(mAfterVoiceInputInsertCount); - mAfterVoiceInputInsertCount = 0; - } - } - - public void flushAllTextModificationCounters() { - if (mAfterVoiceInputInsertCount > 0) { - logTextModifiedByTypingInsertion(mAfterVoiceInputInsertCount); - mAfterVoiceInputInsertCount = 0; - } - if (mAfterVoiceInputDeleteCount > 0) { - logTextModifiedByTypingDeletion(mAfterVoiceInputDeleteCount); - mAfterVoiceInputDeleteCount = 0; - } - if (mAfterVoiceInputInsertPunctuationCount > 0) { - logTextModifiedByTypingInsertionPunctuation(mAfterVoiceInputInsertPunctuationCount); - mAfterVoiceInputInsertPunctuationCount = 0; - } - } - - /** - * The configuration of the IME changed and may have caused the views to be layed out - * again. Restore the state of the recognition view. - */ - public void onConfigurationChanged(Configuration configuration) { - mRecognitionView.restoreState(); - mRecognitionView.getView().dispatchConfigurationChanged(configuration); - } - - /** - * @return true if field is blacklisted for voice - */ - public boolean isBlacklistedField(FieldContext context) { - return mBlacklist.matches(context); - } - - /** - * Used to decide whether to show voice input hints for this field, etc. - * - * @return true if field is recommended for voice - */ - public boolean isRecommendedField(FieldContext context) { - return mRecommendedList.matches(context); - } - - /** - * Start listening for speech from the user. This will grab the microphone - * and start updating the view provided by getView(). It is the caller's - * responsibility to ensure that the view is visible to the user at this stage. - * - * @param context the same FieldContext supplied to voiceIsEnabled() - * @param swipe whether this voice input was started by swipe, for logging purposes - */ - public void startListening(FieldContext context, boolean swipe) { - if (DBG) { - Log.d(TAG, "startListening: " + context); - } - - if (mState != DEFAULT) { - Log.w(TAG, "startListening in the wrong status " + mState); - } - - // If everything works ok, the voice input should be already in the correct state. As this - // class can be called by third-party, we call reset just to be on the safe side. - reset(); - - Locale locale = Locale.getDefault(); - String localeString = locale.getLanguage() + "-" + locale.getCountry(); - - mLogger.start(localeString, swipe); - - mState = LISTENING; - - mRecognitionView.showInitializing(); - startListeningAfterInitialization(context); - } - - /** - * Called only when the recognition manager's initialization completed - * - * @param context context with which {@link #startListening(FieldContext, boolean)} was executed - */ - private void startListeningAfterInitialization(FieldContext context) { - Intent intent = makeIntent(); - intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, ""); - intent.putExtra(EXTRA_RECOGNITION_CONTEXT, context.getBundle()); - intent.putExtra(EXTRA_CALLING_PACKAGE, "VoiceIME"); - intent.putExtra(EXTRA_ALTERNATES, true); - intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, - SettingsUtil.getSettingsInt( - mContext.getContentResolver(), - SettingsUtil.LATIN_IME_MAX_VOICE_RESULTS, - 1)); - // Get endpointer params from Gservices. - // TODO: Consider caching these values for improved performance on slower devices. - final ContentResolver cr = mContext.getContentResolver(); - putEndpointerExtra( - cr, - intent, - SettingsUtil.LATIN_IME_SPEECH_MINIMUM_LENGTH_MILLIS, - EXTRA_SPEECH_MINIMUM_LENGTH_MILLIS, - null /* rely on endpointer default */); - putEndpointerExtra( - cr, - intent, - SettingsUtil.LATIN_IME_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS, - EXTRA_SPEECH_INPUT_COMPLETE_SILENCE_LENGTH_MILLIS, - INPUT_COMPLETE_SILENCE_LENGTH_DEFAULT_VALUE_MILLIS - /* our default value is different from the endpointer's */); - putEndpointerExtra( - cr, - intent, - SettingsUtil. - LATIN_IME_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, - EXTRA_SPEECH_INPUT_POSSIBLY_COMPLETE_SILENCE_LENGTH_MILLIS, - null /* rely on endpointer default */); - - mSpeechRecognizer.startListening(intent); - } - - /** - * Gets the value of the provided Gservices key, attempts to parse it into a long, - * and if successful, puts the long value as an extra in the provided intent. - */ - private void putEndpointerExtra(ContentResolver cr, Intent i, - String gservicesKey, String intentExtraKey, String defaultValue) { - long l = -1; - String s = SettingsUtil.getSettingsString(cr, gservicesKey, defaultValue); - if (s != null) { - try { - l = Long.valueOf(s); - } catch (NumberFormatException e) { - Log.e(TAG, "could not parse value for " + gservicesKey + ": " + s); - } - } - - if (l != -1) i.putExtra(intentExtraKey, l); - } - - public void destroy() { - mSpeechRecognizer.destroy(); - } - - /** - * Creates a new instance of the view that is returned by {@link #getView()} - * Clients should use this when a previously returned view is stuck in a - * layout that is being thrown away and a new one is need to show to the - * user. - */ - public void newView() { - mRecognitionView = new RecognitionView(mContext, this); - } - - /** - * @return a view that shows the recognition flow--e.g., "Speak now" and - * "working" dialogs. - */ - public View getView() { - return mRecognitionView.getView(); - } - - /** - * Handle the cancel button. - */ - @Override - public void onClick(View view) { - switch(view.getId()) { - case R.id.button: - cancel(); - break; - } - } - - public void logTextModifiedByTypingInsertion(int length) { - mLogger.textModifiedByTypingInsertion(length); - } - - public void logTextModifiedByTypingInsertionPunctuation(int length) { - mLogger.textModifiedByTypingInsertionPunctuation(length); - } - - public void logTextModifiedByTypingDeletion(int length) { - mLogger.textModifiedByTypingDeletion(length); - } - - public void logTextModifiedByChooseSuggestion(String suggestion, int index, - String wordSeparators, InputConnection ic) { - String wordToBeReplaced = EditingUtils.getWordAtCursor(ic, wordSeparators); - // If we enable phrase-based alternatives, only send up the first word - // in suggestion and wordToBeReplaced. - mLogger.textModifiedByChooseSuggestion(suggestion.length(), wordToBeReplaced.length(), - index, wordToBeReplaced, suggestion); - } - - public void logKeyboardWarningDialogShown() { - mLogger.keyboardWarningDialogShown(); - } - - public void logKeyboardWarningDialogDismissed() { - mLogger.keyboardWarningDialogDismissed(); - } - - public void logKeyboardWarningDialogOk() { - mLogger.keyboardWarningDialogOk(); - } - - public void logKeyboardWarningDialogCancel() { - mLogger.keyboardWarningDialogCancel(); - } - - public void logSwipeHintDisplayed() { - mLogger.swipeHintDisplayed(); - } - - public void logPunctuationHintDisplayed() { - mLogger.punctuationHintDisplayed(); - } - - public void logVoiceInputDelivered(int length) { - mLogger.voiceInputDelivered(length); - } - - public void logInputEnded() { - mLogger.inputEnded(); - } - - public void flushLogs() { - mLogger.flush(); - } - - private static Intent makeIntent() { - Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); - - // On Cupcake, use VoiceIMEHelper since VoiceSearch doesn't support. - // On Donut, always use VoiceSearch, since VoiceIMEHelper and - // VoiceSearch may conflict. - if (Build.VERSION.RELEASE.equals("1.5")) { - intent = intent.setClassName( - "com.google.android.voiceservice", - "com.google.android.voiceservice.IMERecognitionService"); - } else { - intent = intent.setClassName( - "com.google.android.voicesearch", - "com.google.android.voicesearch.RecognitionService"); - } - - return intent; - } - - /** - * Reset the current voice recognition. - */ - public void reset() { - if (mState != DEFAULT) { - mState = DEFAULT; - - // Remove all pending tasks (e.g., timers to cancel voice input) - mHandler.removeMessages(MSG_RESET); - - mSpeechRecognizer.cancel(); - mRecognitionView.finish(); - } - } - - /** - * Cancel in-progress speech recognition. - */ - public void cancel() { - switch (mState) { - case LISTENING: - mLogger.cancelDuringListening(); - break; - case WORKING: - mLogger.cancelDuringWorking(); - break; - case ERROR: - mLogger.cancelDuringError(); - break; - } - - reset(); - mUiListener.onCancelVoice(); - } - - private int getErrorStringId(int errorType, boolean endpointed) { - switch (errorType) { - // We use CLIENT_ERROR to signify that voice search is not available on the device. - case SpeechRecognizer.ERROR_CLIENT: - return R.string.voice_not_installed; - case SpeechRecognizer.ERROR_NETWORK: - return R.string.voice_network_error; - case SpeechRecognizer.ERROR_NETWORK_TIMEOUT: - return endpointed ? - R.string.voice_network_error : R.string.voice_too_much_speech; - case SpeechRecognizer.ERROR_AUDIO: - return R.string.voice_audio_error; - case SpeechRecognizer.ERROR_SERVER: - return R.string.voice_server_error; - case SpeechRecognizer.ERROR_SPEECH_TIMEOUT: - return R.string.voice_speech_timeout; - case SpeechRecognizer.ERROR_NO_MATCH: - return R.string.voice_no_match; - default: return R.string.voice_error; - } - } - - private void onError(int errorType, boolean endpointed) { - Log.i(TAG, "error " + errorType); - mLogger.error(errorType); - onError(mContext.getString(getErrorStringId(errorType, endpointed))); - } - - private void onError(String error) { - mState = ERROR; - mRecognitionView.showError(error); - // Wait a couple seconds and then automatically dismiss message. - mHandler.sendMessageDelayed(Message.obtain(mHandler, MSG_RESET), 2000); - } - - private class ImeRecognitionListener implements RecognitionListener { - // Waveform data - final ByteArrayOutputStream mWaveBuffer = new ByteArrayOutputStream(); - int mSpeechStart; - private boolean mEndpointed = false; - - @Override - public void onReadyForSpeech(Bundle noiseParams) { - mRecognitionView.showListening(); - } - - @Override - public void onBeginningOfSpeech() { - mEndpointed = false; - mSpeechStart = mWaveBuffer.size(); - } - - @Override - public void onRmsChanged(float rmsdB) { - mRecognitionView.updateVoiceMeter(rmsdB); - } - - @Override - public void onBufferReceived(byte[] buf) { - try { - mWaveBuffer.write(buf); - } catch (IOException e) { - // ignore. - } - } - - @Override - public void onEndOfSpeech() { - mEndpointed = true; - mState = WORKING; - mRecognitionView.showWorking(mWaveBuffer, mSpeechStart, mWaveBuffer.size()); - } - - @Override - public void onError(int errorType) { - mState = ERROR; - VoiceInput.this.onError(errorType, mEndpointed); - } - - @Override - public void onResults(Bundle resultsBundle) { - List<String> results = resultsBundle - .getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION); - // VS Market update is needed for IME froyo clients to access the alternatesBundle - // TODO: verify this. - Bundle alternatesBundle = resultsBundle.getBundle(ALTERNATES_BUNDLE); - mState = DEFAULT; - - final Map<String, List<CharSequence>> alternatives = - new HashMap<String, List<CharSequence>>(); - - if (ENABLE_WORD_CORRECTIONS && alternatesBundle != null && results.size() > 0) { - // Use the top recognition result to map each alternative's start:length to a word. - String[] words = results.get(0).split(" "); - Bundle spansBundle = alternatesBundle.getBundle(AlternatesBundleKeys.SPANS); - for (String key : spansBundle.keySet()) { - // Get the word for which these alternates correspond to. - Bundle spanBundle = spansBundle.getBundle(key); - int start = spanBundle.getInt(AlternatesBundleKeys.START); - int length = spanBundle.getInt(AlternatesBundleKeys.LENGTH); - // Only keep single-word based alternatives. - if (length == 1 && start < words.length) { - // Get the alternatives associated with the span. - // If a word appears twice in a recognition result, - // concatenate the alternatives for the word. - List<CharSequence> altList = alternatives.get(words[start]); - if (altList == null) { - altList = new ArrayList<CharSequence>(); - alternatives.put(words[start], altList); - } - Parcelable[] alternatesArr = spanBundle - .getParcelableArray(AlternatesBundleKeys.ALTERNATES); - for (int j = 0; j < alternatesArr.length && - altList.size() < MAX_ALT_LIST_LENGTH; j++) { - Bundle alternateBundle = (Bundle) alternatesArr[j]; - String alternate = alternateBundle.getString(AlternatesBundleKeys.TEXT); - // Don't allow duplicates in the alternates list. - if (!altList.contains(alternate)) { - altList.add(alternate); - } - } - } - } - } - - if (results.size() > 5) { - results = results.subList(0, 5); - } - mUiListener.onVoiceResults(results, alternatives); - mRecognitionView.finish(); - } - - @Override - public void onPartialResults(final Bundle partialResults) { - // currently - do nothing - } - - @Override - public void onEvent(int eventType, Bundle params) { - // do nothing - reserved for events that might be added in the future - } - } -} diff --git a/java/src/com/android/inputmethod/deprecated/voice/VoiceInputLogger.java b/java/src/com/android/inputmethod/deprecated/voice/VoiceInputLogger.java deleted file mode 100644 index 22e8207bf..000000000 --- a/java/src/com/android/inputmethod/deprecated/voice/VoiceInputLogger.java +++ /dev/null @@ -1,266 +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.deprecated.voice; - -import com.android.common.speech.LoggingEvents; -import com.android.inputmethod.deprecated.compat.VoiceInputLoggerCompatUtils; - -import android.content.Context; -import android.content.Intent; - -/** - * Provides the logging facility for voice input events. This fires broadcasts back to - * the voice search app which then logs on our behalf. - * - * Note that debug console logging does not occur in this class. If you want to - * see console output of these logging events, there is a boolean switch to turn - * on on the VoiceSearch side. - */ -public class VoiceInputLogger { - @SuppressWarnings("unused") - private static final String TAG = VoiceInputLogger.class.getSimpleName(); - - private static VoiceInputLogger sVoiceInputLogger; - - private final Context mContext; - - // The base intent used to form all broadcast intents to the logger - // in VoiceSearch. - private final Intent mBaseIntent; - - // This flag is used to indicate when there are voice events that - // need to be flushed. - private boolean mHasLoggingInfo = false; - - /** - * Returns the singleton of the logger. - * - * @param contextHint a hint context used when creating the logger instance. - * Ignored if the singleton instance already exists. - */ - public static synchronized VoiceInputLogger getLogger(Context contextHint) { - if (sVoiceInputLogger == null) { - sVoiceInputLogger = new VoiceInputLogger(contextHint); - } - return sVoiceInputLogger; - } - - public VoiceInputLogger(Context context) { - mContext = context; - - mBaseIntent = new Intent(LoggingEvents.ACTION_LOG_EVENT); - mBaseIntent.putExtra(LoggingEvents.EXTRA_APP_NAME, LoggingEvents.VoiceIme.APP_NAME); - } - - private Intent newLoggingBroadcast(int event) { - Intent i = new Intent(mBaseIntent); - i.putExtra(LoggingEvents.EXTRA_EVENT, event); - return i; - } - - public void flush() { - if (hasLoggingInfo()) { - Intent i = new Intent(mBaseIntent); - i.putExtra(LoggingEvents.EXTRA_FLUSH, true); - mContext.sendBroadcast(i); - setHasLoggingInfo(false); - } - } - - public void keyboardWarningDialogShown() { - setHasLoggingInfo(true); - mContext.sendBroadcast(newLoggingBroadcast( - LoggingEvents.VoiceIme.KEYBOARD_WARNING_DIALOG_SHOWN)); - } - - public void keyboardWarningDialogDismissed() { - setHasLoggingInfo(true); - mContext.sendBroadcast(newLoggingBroadcast( - LoggingEvents.VoiceIme.KEYBOARD_WARNING_DIALOG_DISMISSED)); - } - - public void keyboardWarningDialogOk() { - setHasLoggingInfo(true); - mContext.sendBroadcast(newLoggingBroadcast( - LoggingEvents.VoiceIme.KEYBOARD_WARNING_DIALOG_OK)); - } - - public void keyboardWarningDialogCancel() { - setHasLoggingInfo(true); - mContext.sendBroadcast(newLoggingBroadcast( - LoggingEvents.VoiceIme.KEYBOARD_WARNING_DIALOG_CANCEL)); - } - - public void settingsWarningDialogShown() { - setHasLoggingInfo(true); - mContext.sendBroadcast(newLoggingBroadcast( - LoggingEvents.VoiceIme.SETTINGS_WARNING_DIALOG_SHOWN)); - } - - public void settingsWarningDialogDismissed() { - setHasLoggingInfo(true); - mContext.sendBroadcast(newLoggingBroadcast( - LoggingEvents.VoiceIme.SETTINGS_WARNING_DIALOG_DISMISSED)); - } - - public void settingsWarningDialogOk() { - setHasLoggingInfo(true); - mContext.sendBroadcast(newLoggingBroadcast( - LoggingEvents.VoiceIme.SETTINGS_WARNING_DIALOG_OK)); - } - - public void settingsWarningDialogCancel() { - setHasLoggingInfo(true); - mContext.sendBroadcast(newLoggingBroadcast( - LoggingEvents.VoiceIme.SETTINGS_WARNING_DIALOG_CANCEL)); - } - - public void swipeHintDisplayed() { - setHasLoggingInfo(true); - mContext.sendBroadcast(newLoggingBroadcast(LoggingEvents.VoiceIme.SWIPE_HINT_DISPLAYED)); - } - - public void cancelDuringListening() { - setHasLoggingInfo(true); - mContext.sendBroadcast(newLoggingBroadcast(LoggingEvents.VoiceIme.CANCEL_DURING_LISTENING)); - } - - public void cancelDuringWorking() { - setHasLoggingInfo(true); - mContext.sendBroadcast(newLoggingBroadcast(LoggingEvents.VoiceIme.CANCEL_DURING_WORKING)); - } - - public void cancelDuringError() { - setHasLoggingInfo(true); - mContext.sendBroadcast(newLoggingBroadcast(LoggingEvents.VoiceIme.CANCEL_DURING_ERROR)); - } - - public void punctuationHintDisplayed() { - setHasLoggingInfo(true); - mContext.sendBroadcast(newLoggingBroadcast( - LoggingEvents.VoiceIme.PUNCTUATION_HINT_DISPLAYED)); - } - - public void error(int code) { - setHasLoggingInfo(true); - Intent i = newLoggingBroadcast(LoggingEvents.VoiceIme.ERROR); - i.putExtra(LoggingEvents.VoiceIme.EXTRA_ERROR_CODE, code); - mContext.sendBroadcast(i); - } - - public void start(String locale, boolean swipe) { - setHasLoggingInfo(true); - Intent i = newLoggingBroadcast(LoggingEvents.VoiceIme.START); - i.putExtra(LoggingEvents.VoiceIme.EXTRA_START_LOCALE, locale); - i.putExtra(LoggingEvents.VoiceIme.EXTRA_START_SWIPE, swipe); - i.putExtra(LoggingEvents.EXTRA_TIMESTAMP, System.currentTimeMillis()); - mContext.sendBroadcast(i); - } - - public void voiceInputDelivered(int length) { - setHasLoggingInfo(true); - Intent i = newLoggingBroadcast(LoggingEvents.VoiceIme.VOICE_INPUT_DELIVERED); - i.putExtra(LoggingEvents.VoiceIme.EXTRA_TEXT_MODIFIED_LENGTH, length); - mContext.sendBroadcast(i); - } - - public void textModifiedByTypingInsertion(int length) { - setHasLoggingInfo(true); - Intent i = newLoggingBroadcast(LoggingEvents.VoiceIme.TEXT_MODIFIED); - i.putExtra(LoggingEvents.VoiceIme.EXTRA_TEXT_MODIFIED_LENGTH, length); - i.putExtra(LoggingEvents.VoiceIme.EXTRA_TEXT_MODIFIED_TYPE, - LoggingEvents.VoiceIme.TEXT_MODIFIED_TYPE_TYPING_INSERTION); - mContext.sendBroadcast(i); - } - - public void textModifiedByTypingInsertionPunctuation(int length) { - setHasLoggingInfo(true); - Intent i = newLoggingBroadcast(LoggingEvents.VoiceIme.TEXT_MODIFIED); - i.putExtra(LoggingEvents.VoiceIme.EXTRA_TEXT_MODIFIED_LENGTH, length); - i.putExtra(LoggingEvents.VoiceIme.EXTRA_TEXT_MODIFIED_TYPE, - LoggingEvents.VoiceIme.TEXT_MODIFIED_TYPE_TYPING_INSERTION_PUNCTUATION); - mContext.sendBroadcast(i); - } - - public void textModifiedByTypingDeletion(int length) { - setHasLoggingInfo(true); - Intent i = newLoggingBroadcast(LoggingEvents.VoiceIme.TEXT_MODIFIED); - i.putExtra(LoggingEvents.VoiceIme.EXTRA_TEXT_MODIFIED_LENGTH, length); - i.putExtra(LoggingEvents.VoiceIme.EXTRA_TEXT_MODIFIED_TYPE, - LoggingEvents.VoiceIme.TEXT_MODIFIED_TYPE_TYPING_DELETION); - - mContext.sendBroadcast(i); - } - - - public void textModifiedByChooseSuggestion(int suggestionLength, int replacedPhraseLength, - int index, String before, String after) { - setHasLoggingInfo(true); - Intent i = newLoggingBroadcast(LoggingEvents.VoiceIme.TEXT_MODIFIED); - i.putExtra(LoggingEvents.VoiceIme.EXTRA_TEXT_MODIFIED_LENGTH, suggestionLength); - i.putExtra(VoiceInputLoggerCompatUtils.EXTRA_TEXT_REPLACED_LENGTH, replacedPhraseLength); - i.putExtra(LoggingEvents.VoiceIme.EXTRA_TEXT_MODIFIED_TYPE, - LoggingEvents.VoiceIme.TEXT_MODIFIED_TYPE_CHOOSE_SUGGESTION); - i.putExtra(LoggingEvents.VoiceIme.EXTRA_N_BEST_CHOOSE_INDEX, index); - i.putExtra(VoiceInputLoggerCompatUtils.EXTRA_BEFORE_N_BEST_CHOOSE, before); - i.putExtra(VoiceInputLoggerCompatUtils.EXTRA_AFTER_N_BEST_CHOOSE, after); - mContext.sendBroadcast(i); - } - - public void inputEnded() { - setHasLoggingInfo(true); - mContext.sendBroadcast(newLoggingBroadcast(LoggingEvents.VoiceIme.INPUT_ENDED)); - } - - public void voiceInputSettingEnabled() { - setHasLoggingInfo(true); - mContext.sendBroadcast(newLoggingBroadcast( - LoggingEvents.VoiceIme.VOICE_INPUT_SETTING_ENABLED)); - } - - public void voiceInputSettingDisabled() { - setHasLoggingInfo(true); - mContext.sendBroadcast(newLoggingBroadcast( - LoggingEvents.VoiceIme.VOICE_INPUT_SETTING_DISABLED)); - } - - private void setHasLoggingInfo(boolean hasLoggingInfo) { - mHasLoggingInfo = hasLoggingInfo; - // If applications that call UserHappinessSignals.userAcceptedImeText - // make that call after VoiceInputLogger.flush() calls this method with false, we - // will lose those happiness signals. For example, consider the gmail sequence: - // 1. compose message - // 2. speak message into message field - // 3. type subject into subject field - // 4. press send - // We will NOT get the signal that the user accepted the voice inputted message text - // because when the user tapped on the subject field, the ime's flush will be triggered - // and the hasLoggingInfo will be then set to false. So by the time the user hits send - // we have essentially forgotten about any voice input. - // However the following (more common) use case is properly logged - // 1. compose message - // 2. type subject in subject field - // 3. speak message in message field - // 4. press send - VoiceInputLoggerCompatUtils.setHasVoiceLoggingInfoCompat(hasLoggingInfo); - } - - private boolean hasLoggingInfo(){ - return mHasLoggingInfo; - } - -} diff --git a/java/src/com/android/inputmethod/deprecated/voice/WaveformImage.java b/java/src/com/android/inputmethod/deprecated/voice/WaveformImage.java deleted file mode 100644 index 8ed279f42..000000000 --- a/java/src/com/android/inputmethod/deprecated/voice/WaveformImage.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2008-2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * 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.deprecated.voice; - -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Paint; - -import java.io.ByteArrayOutputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.ShortBuffer; - -/** - * Utility class to draw a waveform into a bitmap, given a byte array - * that represents the waveform as a sequence of 16-bit integers. - * Adapted from RecognitionActivity.java. - */ -public class WaveformImage { - private static final int SAMPLING_RATE = 8000; - - private WaveformImage() { - // Intentional empty constructor. - } - - public static Bitmap drawWaveform( - ByteArrayOutputStream waveBuffer, int w, int h, int start, int end) { - final Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); - final Canvas c = new Canvas(b); - final Paint paint = new Paint(); - paint.setColor(0xFFFFFFFF); // 0xRRGGBBAA - paint.setAntiAlias(true); - paint.setStrokeWidth(0); - - final ShortBuffer buf = ByteBuffer - .wrap(waveBuffer.toByteArray()) - .order(ByteOrder.nativeOrder()) - .asShortBuffer(); - buf.position(0); - - final int numSamples = waveBuffer.size() / 2; - final int delay = (SAMPLING_RATE * 100 / 1000); - int endIndex = end / 2 + delay; - if (end == 0 || endIndex >= numSamples) { - endIndex = numSamples; - } - int index = start / 2 - delay; - if (index < 0) { - index = 0; - } - final int size = endIndex - index; - int numSamplePerPixel = 32; - int delta = size / (numSamplePerPixel * w); - if (delta == 0) { - numSamplePerPixel = size / w; - delta = 1; - } - - final float scale = 3.5f / 65536.0f; - // do one less column to make sure we won't read past - // the buffer. - try { - for (int i = 0; i < w - 1 ; i++) { - final float x = i; - for (int j = 0; j < numSamplePerPixel; j++) { - final short s = buf.get(index); - final float y = (h / 2) - (s * h * scale); - c.drawPoint(x, y, paint); - index += delta; - } - } - } catch (IndexOutOfBoundsException e) { - // this can happen, but we don't care - } - - return b; - } -} diff --git a/java/src/com/android/inputmethod/deprecated/voice/Whitelist.java b/java/src/com/android/inputmethod/deprecated/voice/Whitelist.java deleted file mode 100644 index 6c5f52ae2..000000000 --- a/java/src/com/android/inputmethod/deprecated/voice/Whitelist.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * 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.deprecated.voice; - -import android.os.Bundle; - -import java.util.ArrayList; -import java.util.List; - -/** - * A set of text fields where speech has been explicitly enabled. - */ -public class Whitelist { - private List<Bundle> mConditions; - - public Whitelist() { - mConditions = new ArrayList<Bundle>(); - } - - public Whitelist(List<Bundle> conditions) { - this.mConditions = conditions; - } - - public void addApp(String app) { - Bundle bundle = new Bundle(); - bundle.putString("packageName", app); - mConditions.add(bundle); - } - - /** - * @return true if the field is a member of the whitelist. - */ - public boolean matches(FieldContext context) { - for (Bundle condition : mConditions) { - if (matches(condition, context.getBundle())) { - return true; - } - } - return false; - } - - /** - * @return true of all values in condition are matched by a value - * in target. - */ - private boolean matches(Bundle condition, Bundle target) { - for (String key : condition.keySet()) { - if (!condition.getString(key).equals(target.getString(key))) { - return false; - } - } - return true; - } -} diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java index f1ae0b313..0a2b010b6 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 = computeHashCode(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 = computeHashCode(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 computeHashCode(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..13e909c7e 100644 --- a/java/src/com/android/inputmethod/keyboard/KeyDetector.java +++ b/java/src/com/android/inputmethod/keyboard/KeyDetector.java @@ -16,17 +16,9 @@ package com.android.inputmethod.keyboard; -import android.util.Log; - -import java.util.Arrays; -import java.util.List; public class KeyDetector { - private static final String TAG = KeyDetector.class.getSimpleName(); - private static final boolean DEBUG = false; - public static final int NOT_A_CODE = -1; - public static final int NOT_A_KEY = -1; private final int mKeyHysteresisDistanceSquared; @@ -34,12 +26,6 @@ public class KeyDetector { private int mCorrectionX; private int mCorrectionY; private boolean mProximityCorrectOn; - private int mProximityThresholdSquare; - - // 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]; /** * This class handles key detection. @@ -57,19 +43,17 @@ public class KeyDetector { mCorrectionX = (int)correctionX; mCorrectionY = (int)correctionY; mKeyboard = keyboard; - final int threshold = keyboard.mMostCommonKeyWidth; - mProximityThresholdSquare = threshold * threshold; } public int getKeyHysteresisDistanceSquared() { 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; } @@ -87,137 +71,49 @@ public class KeyDetector { return mProximityCorrectOn; } - public void setProximityThreshold(int threshold) { - mProximityThresholdSquare = threshold * threshold; - } - public boolean alwaysAllowsSlidingInput() { return false; } /** - * Computes 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 indices returned - * by {@link #getKeyIndexAndNearbyCodes}. - */ - protected int getMaxNearbyKeys() { - return MAX_NEARBY_KEYS; - } - - /** - * Allocates array that can hold all key indices returned by {@link #getKeyIndexAndNearbyCodes} - * 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 - * initialized by {@link #NOT_A_CODE} value. - */ - public int[] newCodeArray() { - int[] codes = new int[getMaxNearbyKeys()]; - Arrays.fill(codes, NOT_A_CODE); - return codes; - } - - private void initializeNearbyKeys() { - Arrays.fill(mDistances, Integer.MAX_VALUE); - Arrays.fill(mIndices, NOT_A_KEY); - } - - /** - * Insert the key into nearby keys buffer and sort nearby keys by ascending order of distance. - * 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 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) { - final int[] distances = mDistances; - final int[] indices = mIndices; - for (int insertPos = 0; insertPos < distances.length; insertPos++) { - final int comparingDistance = distances[insertPos]; - if (distance < comparingDistance || (distance == comparingDistance && isOnKey)) { - final int nextPos = insertPos + 1; - if (nextPos < distances.length) { - System.arraycopy(distances, insertPos, distances, nextPos, - distances.length - nextPos); - System.arraycopy(indices, insertPos, indices, nextPos, - indices.length - nextPos); - } - distances[insertPos] = distance; - indices[insertPos] = keyIndex; - return insertPos; - } - } - return distances.length; - } - - private void getNearbyKeyCodes(final int[] allCodes) { - final List<Key> keys = getKeyboard().mKeys; - final int[] indices = mIndices; - - // allCodes[0] should always have the key code even if it is a non-letter key. - if (indices[0] == NOT_A_KEY) { - 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) - break; - final int code = keys.get(index).mCode; - // filter out a non-letter key from nearby keys - if (code < Keyboard.CODE_SPACE) - continue; - allCodes[numCodes++] = code; - } - } - - /** - * 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 - * {@link #setProximityThreshold(int)} and the mode set by - * {@link #setProximityCorrectionEnabled(boolean)}. + * 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 - * @param allCodes All nearby key code except functional key are returned in this array - * @return The nearest key index + * @return the key that the touch point hits. */ - public int getKeyIndexAndNearbyCodes(int x, int y, final int[] allCodes) { - final List<Key> keys = getKeyboard().mKeys; + public Key detectHitKey(int x, int y) { 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); + int minDistance = Integer.MAX_VALUE; + 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; + // To take care of hitbox overlaps, we compare mCode here too. + if (primaryKey == null || distance < minDistance + || (distance == minDistance && isOnKey && key.mCode > primaryKey.mCode)) { + minDistance = distance; + primaryKey = key; } } + return primaryKey; + } - 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)); - } - } + public static String printableCode(Key key) { + return key != null ? Keyboard.printableCode(key.mCode) : "none"; + } - return primaryIndex; + 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 (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..67e4e4a96 100644 --- a/java/src/com/android/inputmethod/keyboard/Keyboard.java +++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java @@ -16,17 +16,32 @@ package com.android.inputmethod.keyboard; -import android.graphics.drawable.Drawable; -import android.text.TextUtils; +import android.content.Context; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.content.res.XmlResourceParser; +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.Utils; +import com.android.inputmethod.latin.XmlParseUtils; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; +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; /** * Loads an XML description of a keyboard and stores the attributes of the keys. A keyboard @@ -47,7 +62,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 +81,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 +118,1195 @@ 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; + private final boolean mProximityCharsCorrectionEnabled; - public Keyboard(KeyboardParams params) { + 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; - mProximityInfo = new ProximityInfo( + mProximityInfo = new ProximityInfo(params.mId.mLocale.toString(), params.GRID_WIDTH, params.GRID_HEIGHT, mOccupiedWidth, mOccupiedHeight, mMostCommonKeyWidth, mMostCommonKeyHeight, mKeys, params.mTouchPositionCorrection); + mProximityCharsCorrectionEnabled = params.mProximityCharsCorrectionEnabled; + } + + public boolean hasProximityCharsCorrection(int code) { + if (!mProximityCharsCorrectionEnabled) { + return false; + } + // Note: The native code has the main keyboard layout only at this moment. + // TODO: Figure out how to handle proximity characters information of all layouts. + final boolean canAssumeNativeHasProximityCharsInfoOfAllKeys = ( + mId.mElementId == KeyboardId.ELEMENT_ALPHABET + || mId.mElementId == KeyboardId.ELEMENT_ALPHABET_AUTOMATIC_SHIFTED); + return canAssumeNativeHasProximityCharsInfoOfAllKeys || Character.isLetter(code); } 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(); + + public KeyboardSet.KeysCache mKeysCache; + + public int mMostCommonKeyHeight = 0; + public int mMostCommonKeyWidth = 0; + + public boolean mProximityCharsCorrectionEnabled; + + 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(); - } + // TODO: Remove this method. + 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 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; + 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_LANGUAGE_SWITCH: return "languageSwitch"; + 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); + } + } + + /** + * 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="32.0dp" /< + * >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; + + params.GRID_WIDTH = res.getInteger(R.integer.config_keyboard_grid_width); + params.GRID_HEIGHT = res.getInteger(R.integer.config_keyboard_grid_height); + } + + 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; + } + + // TODO: Remove this method. + public void setTouchPositionCorrectionEnabled(boolean enabled) { + mParams.mTouchPositionCorrection.setEnabled(enabled); + } + + public void setProximityCharsCorrectionEnabled(boolean enabled) { + mParams.mProximityCharsCorrectionEnabled = 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 String keyboardHeightString = Utils.getDeviceOverrideValue( + mResources, R.array.keyboard_heights, null); + final float keyboardHeight; + if (keyboardHeightString != null) { + keyboardHeight = Float.parseFloat(keyboardHeightString) + * mDisplayMetrics.density; + } else { + keyboardHeight = keyboardAttr.getDimension( + R.styleable.Keyboard_keyboardHeight, displayHeight / 2); + } + final float maxKeyboardHeight = getDimensionOrFraction(keyboardAttr, + R.styleable.Keyboard_maxKeyboardHeight, displayHeight, displayHeight / 2); + float minKeyboardHeight = 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 = -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 = (int)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.mThemeId = keyboardAttr.getInt(R.styleable.Keyboard_themeId, 0); + params.mIconsSet.loadIcons(keyboardAttr); + + final int resourceId = keyboardAttr.getResourceId( + R.styleable.Keyboard_touchPositionCorrectionData, 0); + params.mTouchPositionCorrection.setEnabled(resourceId != 0); + if (resourceId != 0) { + final String[] data = mResources.getStringArray(resourceId); + params.mTouchPositionCorrection.load(data); + } + } 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..275aacf36 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 PointerTracker} or so, the value should be {@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 PointerTracker} or so, the value should be {@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..e35081867 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 com.android.inputmethod.latin.InputTypeUtils; 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; - 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.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, - }); + public KeyboardId(int elementId, Locale locale, int orientation, int width, int mode, + EditorInfo editorInfo, boolean clobberSettingsKey, boolean shortcutKeyEnabled, + boolean hasShortcutKey, boolean languageSwitchKeyEnabled) { + mLocale = locale; + mOrientation = orientation; + mWidth = width; + mMode = mode; + mElementId = elementId; + mEditorInfo = editorInfo; + mClobberSettingsKey = clobberSettingsKey; + mShortcutKeyEnabled = shortcutKeyEnabled; + mHasShortcutKey = hasShortcutKey; + mLanguageSwitchKeyEnabled = languageSwitchKeyEnabled; + mCustomActionLabel = (editorInfo.actionLabel != null) + ? editorInfo.actionLabel.toString() : null; + + mHashCode = computeHashCode(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 computeHashCode(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 == mOrientation + && other.mElementId == mElementId + && other.mMode == mMode + && other.mWidth == mWidth + && other.passwordInput() == passwordInput() + && other.mClobberSettingsKey == mClobberSettingsKey + && other.mShortcutKeyEnabled == mShortcutKeyEnabled + && other.mHasShortcutKey == mHasShortcutKey + && other.mLanguageSwitchKeyEnabled == mLanguageSwitchKeyEnabled + && other.isMultiLine() == isMultiLine() + && other.imeAction() == imeAction() + && TextUtils.equals(other.mCustomActionLabel, mCustomActionLabel) + && other.navigateNext() == navigateNext() + && other.navigatePrevious() == navigatePrevious() + && other.mLocale.equals(mLocale); } public boolean isAlphabetKeyboard() { - return mXmlId == R.xml.kbd_qwerty; + return mElementId < ELEMENT_SYMBOLS; } - public boolean isSymbolsKeyboard() { - return mXmlId == R.xml.kbd_symbols || mXmlId == R.xml.kbd_symbols_shift; + public boolean navigateNext() { + return (mEditorInfo.imeOptions & EditorInfo.IME_FLAG_NAVIGATE_NEXT) != 0; } - public boolean isPhoneKeyboard() { - return mMode == MODE_PHONE; + public boolean navigatePrevious() { + return (mEditorInfo.imeOptions & EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS) != 0; } - public boolean isPhoneShiftKeyboard() { - return mXmlId == R.xml.kbd_phone_shift; + public boolean passwordInput() { + final int inputType = mEditorInfo.inputType; + return InputTypeUtils.isPasswordInputType(inputType) + || InputTypeUtils.isVisiblePasswordInputType(inputType); } - public boolean isNumberKeyboard() { - return mMode == MODE_NUMBER; + public boolean isMultiLine() { + return (mEditorInfo.inputType & InputType.TYPE_TEXT_FLAG_MULTI_LINE) != 0; + } + + 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 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..263f17f74 --- /dev/null +++ b/java/src/com/android/inputmethod/keyboard/KeyboardSet.java @@ -0,0 +1,406 @@ +/* + * 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.keyboard.KeyboardSet.Params.ElementParams; +import com.android.inputmethod.latin.InputTypeUtils; +import com.android.inputmethod.latin.LatinIME; +import com.android.inputmethod.latin.LatinImeLogger; +import com.android.inputmethod.latin.LocaleUtils.RunInLocale; +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; + +/** + * 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 = "KeyboardSet"; + 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(); + + 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 HashMap<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 mDisableShortcutKey; + boolean mVoiceKeyEnabled; + boolean mVoiceKeyOnMain; + boolean mNoSettingsKey; + boolean mLanguageSwitchKeyEnabled; + Locale mLocale; + int mOrientation; + int mWidth; + // KeyboardSet element id to element's parameters map. + final HashMap<Integer, ElementParams> mKeyboardSetElementIdToParamsMap = + new HashMap<Integer, ElementParams>(); + + static class ElementParams { + int mKeyboardXmlId; + boolean mProximityCharsCorrectionEnabled; + } + } + + 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; + } + + ElementParams elementParams = mParams.mKeyboardSetElementIdToParamsMap.get( + keyboardSetElementId); + if (elementParams == null) { + elementParams = mParams.mKeyboardSetElementIdToParamsMap.get( + KeyboardId.ELEMENT_ALPHABET); + } + final KeyboardId id = getKeyboardId(keyboardSetElementId); + try { + return getKeyboard(mContext, elementParams, id); + } catch (RuntimeException e) { + throw new KeyboardSetException(e, id); + } + } + + private Keyboard getKeyboard(Context context, ElementParams elementParams, + final KeyboardId id) { + final SoftReference<Keyboard> ref = sKeyboardCache.get(id); + Keyboard keyboard = (ref == null) ? null : ref.get(); + if (keyboard == null) { + final Keyboard.Builder<Keyboard.Params> builder = + new Keyboard.Builder<Keyboard.Params>(mContext, new Keyboard.Params()); + if (id.isAlphabetKeyboard()) { + builder.setAutoGenerate(sKeysCache); + } + final int keyboardXmlId = elementParams.mKeyboardXmlId; + final RunInLocale<Void> job = new RunInLocale<Void>() { + @Override + protected Void job(Resources res) { + builder.load(keyboardXmlId, id); + return null; + } + }; + job.runInLocale(context.getResources(), id.mLocale); + builder.setTouchPositionCorrectionEnabled(mParams.mTouchPositionCorrectionEnabled); + builder.setProximityCharsCorrectionEnabled( + elementParams.mProximityCharsCorrectionEnabled); + keyboard = builder.build(); + 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 voiceKeyEnabled = params.mVoiceKeyEnabled && !params.mDisableShortcutKey; + final boolean hasShortcutKey = voiceKeyEnabled && (isSymbols != params.mVoiceKeyOnMain); + return new KeyboardId(keyboardSetElementId, params.mLocale, params.mOrientation, + params.mWidth, params.mMode, params.mEditorInfo, params.mNoSettingsKey, + voiceKeyEnabled, 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(); + + private static final EditorInfo EMPTY_EDITOR_INFO = new EditorInfo(); + + 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; + } + + public Builder setSubtype(Locale inputLocale, boolean asciiCapable) { + 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; + 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 void setTouchPositionCorrectionEnabled(boolean enabled) { + mParams.mTouchPositionCorrectionEnabled = enabled; + } + + 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 RunInLocale<Void> job = new RunInLocale<Void>() { + @Override + protected Void job(Resources res) { + try { + parseKeyboardSet(res, R.xml.keyboard_set); + } catch (Exception e) { + throw new RuntimeException(e.getMessage() + " in " + + res.getResourceName(R.xml.keyboard_set) + + " of locale " + mParams.mLocale); + } + return null; + } + }; + job.runInLocale(mResources, mParams.mLocale); + 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)) { + final TypedArray a = mResources.obtainAttributes( + Xml.asAttributeSet(parser), R.styleable.KeyboardSet); + mParams.mDisableShortcutKey = a.getBoolean( + R.styleable.KeyboardSet_disableShortcutKey, false); + a.recycle(); + 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 ElementParams elementParams = new ElementParams(); + final int elementName = a.getInt( + R.styleable.KeyboardSet_Element_elementName, 0); + elementParams.mKeyboardXmlId = a.getResourceId( + R.styleable.KeyboardSet_Element_elementKeyboard, 0); + elementParams.mProximityCharsCorrectionEnabled = a.getBoolean( + R.styleable.KeyboardSet_Element_enableProximityCharsCorrection, false); + mParams.mKeyboardSetElementIdToParamsMap.put(elementName, elementParams); + } 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 (InputTypeUtils.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; + } + } + } +} diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java index ac718fc62..93d8704de 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,64 @@ 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)); + 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 +173,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 +348,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..b51dbb906 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; @@ -38,28 +37,29 @@ import android.view.ViewGroup; import android.widget.RelativeLayout; import android.widget.TextView; -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 +69,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 +81,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,15 +94,16 @@ 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; + protected final KeyDrawParams mKeyDrawParams; // Key preview private final int mKeyPreviewLayoutId; protected final KeyPreviewDrawParams mKeyPreviewDrawParams; private boolean mShowKeyPreviewPopup = true; - private final int mDelayBeforePreview; private int mDelayAfterPreview; private ViewGroup mPreviewPlacer; @@ -111,17 +112,18 @@ 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 */ private Canvas mCanvas; private final Paint mPaint = new Paint(); + private final Paint.FontMetrics mFontMetrics = new Paint.FontMetrics(); // This map caches key label text height in pixel as value and key label text size as map key. private static final HashMap<Integer, Float> sTextHeightCache = new HashMap<Integer, Float>(); @@ -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 { + protected 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,16 @@ 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 +366,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 +440,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 +494,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); + + canvas.translate(-keyDrawX, -keyDrawY); + } - // Draw key top visuals. + // 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 +591,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 +600,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 +619,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 +628,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,22 +655,23 @@ 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.getFontMetrics(mFontMetrics); + hintY = -mFontMetrics.top + params.mKeyShiftedLetterHintPadding; paint.setTextAlign(Align.CENTER); } else { // key.hasHintLetter() // The hint label is placed at top-right corner of the key. Used mainly on phone. hintX = keyWidth - params.mKeyHintLetterPadding - getCharWidth(KEY_NUMERIC_HINT_LABEL_REFERENCE_CHAR, paint) / 2; - hintY = -paint.ascent(); + hintY = -paint.ascent() + params.mKeyHintLetterPadding; paint.setTextAlign(Align.CENTER); } 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,38 +696,43 @@ 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); - private static int getCharGeometryCacheKey(char reference, Paint 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 referenceChar, Paint paint) { final int labelSize = (int)paint.getTextSize(); final Typeface face = paint.getTypeface(); - final int codePointOffset = reference << 15; + final int codePointOffset = referenceChar << 15; if (face == Typeface.DEFAULT) { return codePointOffset + labelSize; } else if (face == Typeface.DEFAULT_BOLD) { @@ -746,42 +744,39 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { } } - private static float getCharHeight(char[] character, Paint paint) { - final Integer key = getCharGeometryCacheKey(character[0], paint); + // Working variable for the following methods. + private final Rect mTextBounds = new Rect(); + + private float getCharHeight(char[] referenceChar, Paint paint) { + final Integer key = getCharGeometryCacheKey(referenceChar[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(referenceChar, 0, 1, mTextBounds); + final float height = mTextBounds.height(); sTextHeightCache.put(key, height); return height; } - private static float getCharWidth(char[] character, Paint paint) { - final Integer key = getCharGeometryCacheKey(character[0], paint); + private float getCharWidth(char[] referenceChar, Paint paint) { + final Integer key = getCharGeometryCacheKey(referenceChar[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(referenceChar, 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(); + public float getLabelWidth(String label, Paint paint) { + paint.getTextBounds(label.toString(), 0, label.length(), mTextBounds); + return mTextBounds.width(); } - public float getDefaultLabelWidth(CharSequence 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); @@ -814,6 +809,14 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { canvas.translate(-x, -y); } + public Paint newDefaultLabelPaint() { + final Paint paint = new Paint(); + paint.setAntiAlias(true); + paint.setTypeface(mKeyDrawParams.mKeyTextStyle); + paint.setTextSize(mKeyDrawParams.mKeyLabelSize); + return paint; + } + public void cancelAllMessages() { mDrawingHandler.cancelAllMessages(); } @@ -830,20 +833,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); } @@ -855,10 +852,10 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy { windowContentView.addView(mPreviewPlacer); } mPreviewPlacer.addView( - keyPreview, FrameLayoutCompatUtils.newLayoutParam(mPreviewPlacer, 0, 0)); + keyPreview, ViewLayoutUtils.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 +864,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 +874,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,19 +902,23 @@ 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 previewText.getBackground().setState( key.mMoreKeys != null ? LONG_PRESSABLE_STATE_SET : EMPTY_STATE_SET); previewText.setTextColor(params.mPreviewTextColor); - FrameLayoutCompatUtils.placeViewAt( + ViewLayoutUtils.placeViewAt( previewText, previewX, previewY, previewWidth, previewHeight); previewText.setVisibility(VISIBLE); } @@ -930,7 +930,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 +945,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..e2af97185 100644 --- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java +++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java @@ -16,33 +16,44 @@ package com.android.inputmethod.keyboard; +import android.animation.AnimatorInflater; +import android.animation.ObjectAnimator; 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; 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.ResearchLogger; 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 com.android.inputmethod.latin.define.ProductionFlag; +import java.util.Locale; import java.util.WeakHashMap; /** @@ -56,45 +67,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 final int mLanguageOnSpacebarFinalAlpha; + private ObjectAnimator mLanguageOnSpacebarFadeoutAnimator; + private static final int ALPHA_OPAQUE = 255; + private boolean mNeedsToDisplayLanguage; + private Locale mSpacebarLocale; + private int mLanguageOnSpacebarAnimAlpha = ALPHA_OPAQUE; + 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 ObjectAnimator mAltCodeKeyWhileTypingFadeoutAnimator; + private ObjectAnimator mAltCodeKeyWhileTypingFadeinAnimator; + private int mAltCodeKeyWhileTypingAnimAlpha = ALPHA_OPAQUE; + + // 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 +141,31 @@ 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: + cancelAndStartAnimators(keyboardView.mAltCodeKeyWhileTypingFadeoutAnimator, + keyboardView.mAltCodeKeyWhileTypingFadeinAnimator); 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 +178,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 @@ -138,73 +228,118 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke removeMessages(MSG_LONGPRESS_KEY); } + public static void cancelAndStartAnimators(ObjectAnimator animatorToCancel, + ObjectAnimator animatorToStart) { + if (animatorToCancel != null && animatorToCancel.isStarted()) { + animatorToCancel.cancel(); + } + // TODO: Start the animation with an initial value that is the same as the final value + // of the above animation when it gets cancelled. + if (animatorToStart != null && !animatorToStart.isStarted()) { + animatorToStart.start(); + } + } + + private void cancelTypingStateTimer() { + removeMessages(MSG_TYPING_STATE_EXPIRED); + } + @Override - public void cancelKeyTimers() { - cancelKeyRepeatTimer(); - cancelLongPressTimer(); - removeMessages(MSG_IGNORE_DOUBLE_TAP); + public void startTypingStateTimer() { + final boolean isTyping = isTypingState(); + cancelTypingStateTimer(); + sendMessageDelayed( + obtainMessage(MSG_TYPING_STATE_EXPIRED), mParams.mIgnoreAltCodeKeyTimeout); + if (isTyping) { + return; + } + final LatinKeyboardView keyboardView = getOuterInstance(); + cancelAndStartAnimators(keyboardView.mAltCodeKeyWhileTypingFadeinAnimator, + keyboardView.mAltCodeKeyWhileTypingFadeoutAnimator); } - 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() { cancelKeyTimers(); + cancelTypingStateTimer(); } } - 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; + + 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 +347,80 @@ 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); + mHasDistinctMultitouch = context.getPackageManager() + .hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT); + + 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); + mLanguageOnSpacebarFinalAlpha = a.getInt( + R.styleable.LatinKeyboardView_languageOnSpacebarFinalAlpha, ALPHA_OPAQUE); + 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(); - final boolean ignoreMultitouch = true; - mGestureDetector = new GestureDetector( - getContext(), new DoubleTapListener(), null, ignoreMultitouch); - mGestureDetector.setIsLongpressEnabled(false); + PointerTracker.setParameters(mPointerTrackerParams); - mHasDistinctMultitouch = context.getPackageManager() - .hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT); - mKeyRepeatInterval = res.getInteger(R.integer.config_key_repeat_interval); + mLanguageOnSpacebarFadeoutAnimator = loadObjectAnimator( + languageOnSpacebarFadeoutAnimatorResId, this); + mAltCodeKeyWhileTypingFadeoutAnimator = loadObjectAnimator( + altCodeKeyWhileTypingFadeoutAnimatorResId, this); + mAltCodeKeyWhileTypingFadeinAnimator = loadObjectAnimator( + altCodeKeyWhileTypingFadeinAnimatorResId, this); + } + + private ObjectAnimator loadObjectAnimator(int resId, Object target) { + if (resId == 0) return null; + final ObjectAnimator animator = (ObjectAnimator)AnimatorInflater.loadAnimator( + getContext(), resId); + if (animator != null) { + animator.setTarget(target); + } + return animator; + } + + // Getter/setter methods for {@link ObjectAnimator}. + public int getLanguageOnSpacebarAnimAlpha() { + return mLanguageOnSpacebarAnimAlpha; + } + + public void setLanguageOnSpacebarAnimAlpha(int alpha) { + mLanguageOnSpacebarAnimAlpha = alpha; + invalidateKey(mSpaceKey); + } - PointerTracker.init(mHasDistinctMultitouch, getContext()); + public int getAltCodeKeyWhileTypingAnimAlpha() { + return mAltCodeKeyWhileTypingAnimAlpha; } - public void startIgnoringDoubleTap() { - if (ENABLE_CAPSLOCK_BY_DOUBLETAP) - mKeyTimerHandler.startIgnoringDoubleTap(); + public void setAltCodeKeyWhileTypingAnimAlpha(int alpha) { + mAltCodeKeyWhileTypingAnimAlpha = alpha; + updateAltCodeKeyWhileTyping(); } public void setKeyboardActionListener(KeyboardActionListener listener) { @@ -264,20 +452,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. @@ -292,10 +466,15 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke super.setKeyboard(keyboard); mKeyDetector.setKeyboard( keyboard, -getPaddingLeft(), -getPaddingTop() + mVerticalCorrection); - mKeyDetector.setProximityThreshold(keyboard.mMostCommonKeyWidth); 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; } /** @@ -306,6 +485,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 +512,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 +521,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 +535,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 +556,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 +600,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 +653,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 +664,52 @@ 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)) { + final float size = me.getSize(index); + final float pressure = me.getPressure(index); + UsabilityStudyLogUtils.getInstance().write( + eventTag + eventTime + "," + id + "," + x + "," + y + "," + + size + "," + pressure); + } + } + if (ProductionFlag.IS_EXPERIMENTAL) { + if (ResearchLogger.sIsLogging) { + // TODO: remove redundant calculations of size and pressure by + // removing UsabilityStudyLog code once the ResearchLogger is mature enough + final float size = me.getSize(index); + final float pressure = me.getPressure(index); + if (action != MotionEvent.ACTION_MOVE) { + // Skip ACTION_MOVE events as they are logged below + ResearchLogger.getInstance().logMotionEvent(action, eventTime, id, x, y, + size, pressure); + } + } + } 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 +723,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 +739,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 +752,9 @@ 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 int pointerId = me.getPointerId(i); + final PointerTracker tracker = PointerTracker.getPointerTracker( + pointerId, this); final int px, py; if (mMoreKeysPanel != null && tracker.mPointerId == mMoreKeysPanelPointerTrackerId) { @@ -583,9 +765,26 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke py = (int)me.getY(i); } tracker.onMoveEvent(px, py, eventTime); + if (ENABLE_USABILITY_STUDY_LOG) { + final float pointerSize = me.getSize(i); + final float pointerPressure = me.getPressure(i); + UsabilityStudyLogUtils.getInstance().write("[Move]" + eventTime + "," + + pointerId + "," + px + "," + py + "," + + pointerSize + "," + pointerPressure); + } + if (ProductionFlag.IS_EXPERIMENTAL) { + if (ResearchLogger.sIsLogging) { + // TODO: earlier comment about redundant calculations applies here too + final float pointerSize = me.getSize(i); + final float pointerPressure = me.getPressure(i); + ResearchLogger.getInstance().logMotionEvent(action, eventTime, pointerId, + px, py, pointerSize, pointerPressure); + } + } } } 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,44 +822,176 @@ 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); } } } - @Override - protected void onAttachedToWindow() { - // Token is available from here. - 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 - * lower SDK versions, this method is never called. + * Receives hover events from the input framework. * * @param event The motion event to be dispatched. * @return {@code true} if the event was handled by the view, {@code false} * otherwise */ + @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 ObjectAnimator animator = mLanguageOnSpacebarFadeoutAnimator; + mNeedsToDisplayLanguage = needsToDisplayLanguage; + if (animator == null) { + mNeedsToDisplayLanguage = false; + } else { + if (subtypeChanged && needsToDisplayLanguage) { + setLanguageOnSpacebarAnimAlpha(ALPHA_OPAQUE); + if (animator.isStarted()) { + animator.cancel(); + } + animator.start(); + } else { + if (!animator.isStarted()) { + mLanguageOnSpacebarAnimAlpha = mLanguageOnSpacebarFinalAlpha; + } + } + } + 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(mLanguageOnSpacebarAnimAlpha); + canvas.drawText(language, width / 2, baseline - descent - 1, paint); + paint.setColor(mSpacebarTextColor); + paint.setAlpha(mLanguageOnSpacebarAnimAlpha); + 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..cd4e3001e 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; @@ -35,30 +33,19 @@ public class MoreKeysDetector extends KeyDetector { } @Override - protected int getMaxNearbyKeys() { - // No nearby key will be returned. - return 1; - } - - @Override - public int getKeyIndexAndNearbyCodes(int x, int y, final int[] allCodes) { - final List<Key> keys = getKeyboard().mKeys; + public Key detectHitKey(int x, int y) { 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; + 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..72a5d0f05 --- /dev/null +++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboard.java @@ -0,0 +1,363 @@ +/* + * 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)); + final Paint paint = view.newDefaultLabelPaint(); + paint.setTextSize(parentKey.hasLabelsInMoreKeys() + ? view.mKeyDrawParams.mKeyLabelSize + : view.mKeyDrawParams.mKeyLetterSize); + 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) { + final int width = (int)view.getLabelWidth(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 f2c5b7b49..e60fc9598 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,13 @@ 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) { + // Because a more keys keyboard doesn't need proximity characters correction, we don't + // send touch event coordinates. + mListener.onCodeInput(primaryCode, NOT_A_TOUCH_COORDINATE, NOT_A_TOUCH_COORDINATE); } @Override @@ -61,25 +63,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 +112,7 @@ public class MiniKeyboardView extends KeyboardView implements MoreKeysPanel { @Override public KeyboardActionListener getKeyboardActionListener() { - return mMiniKeyboardListener; + return mMoreKeysKeyboardListener; } @Override @@ -124,53 +127,34 @@ 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 miniKeyboard = (MiniKeyboard)getKeyboard(); - - parentView.getLocationInWindow(mCoordinates); - final int miniKeyboardLeft = pointX - miniKeyboard.getDefaultCoordX() + 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() + parentView.getPaddingLeft(); - final int x = wrapUp(Math.max(0, Math.min(miniKeyboardLeft, - parentView.getWidth() - miniKeyboard.mOccupiedWidth)) - - container.getPaddingLeft() + mCoordinates[0], - container.getMeasuredWidth(), 0, parentView.getWidth()); - final int y = pointY - - (container.getMeasuredHeight() - container.getPaddingBottom()) - + parentView.getPaddingTop() + mCoordinates[1]; + final int y = pointY - container.getMeasuredHeight() + container.getPaddingBottom() + + parentView.getPaddingTop(); window.setContentView(container); window.setWidth(container.getMeasuredWidth()); window.setHeight(container.getMeasuredHeight()); - window.showAtLocation(parentView, Gravity.NO_GRAVITY, x, y); - - mOriginX = x + container.getPaddingLeft() - mCoordinates[0]; - mOriginY = y + container.getPaddingTop() - mCoordinates[1]; - } + parentView.getLocationInWindow(mCoordinates); + window.showAtLocation(parentView, Gravity.NO_GRAVITY, + x + mCoordinates[0], y + mCoordinates[1]); - private static int wrapUp(int x, int width, int left, int right) { - if (x < left) - return left; - if (x + width > right) - return right - width; - return x; + mOriginX = x + container.getPaddingLeft(); + mOriginY = y + container.getPaddingTop(); } private boolean mIsDismissing; 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..6b59a8dae 100644 --- a/java/src/com/android/inputmethod/keyboard/ProximityInfo.java +++ b/java/src/com/android/inputmethod/keyboard/ProximityInfo.java @@ -17,20 +17,20 @@ 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.List; +import java.util.HashMap; 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 +41,18 @@ public class ProximityInfo { // TODO: Find a proper name for mKeyboardMinWidth private final int mKeyboardMinWidth; private final int mKeyboardHeight; - private final int[][] mGridNeighbors; + private final int mMostCommonKeyWidth; + private final Key[][] mGridNeighbors; + private final String mLocaleStr; - ProximityInfo(int gridWidth, int gridHeight, int minWidth, int height, int keyWidth, - int keyHeight, List<Key> keys, TouchPositionCorrection touchPositionCorrection) { + ProximityInfo(String localeStr, int gridWidth, int gridHeight, int minWidth, int height, + int mostCommonKeyWidth, int mostCommonKeyHeight, final Key[] keys, + TouchPositionCorrection touchPositionCorrection) { + if (TextUtils.isEmpty(localeStr)) { + mLocaleStr = ""; + } else { + mLocaleStr = localeStr; + } mGridWidth = gridWidth; mGridHeight = gridHeight; mGridSize = mGridWidth * mGridHeight; @@ -52,60 +60,72 @@ 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); } 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); } - public static ProximityInfo createSpellCheckerProximityInfo() { + public static ProximityInfo createSpellCheckerProximityInfo(final int[] proximity) { final ProximityInfo spellCheckerProximityInfo = createDummyProximityInfo(); spellCheckerProximityInfo.mNativeProximityInfo = - spellCheckerProximityInfo.setProximityInfoNative( + spellCheckerProximityInfo.setProximityInfoNative("", SpellCheckerProximityInfo.ROW_SIZE, - 480, 300, 10, 3, SpellCheckerProximityInfo.PROXIMITY, - 0, null, null, null, null, null, null, null, null); + SpellCheckerProximityInfo.PROXIMITY_GRID_WIDTH, + SpellCheckerProximityInfo.PROXIMITY_GRID_HEIGHT, + SpellCheckerProximityInfo.PROXIMITY_GRID_WIDTH, + SpellCheckerProximityInfo.PROXIMITY_GRID_HEIGHT, + 1, 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 +133,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 +182,16 @@ public class ProximityInfo { } } - private void computeNearestNeighbors(int defaultWidth, List<Key> keys, + private void computeNearestNeighbors(int defaultWidth, final Key[] keys, TouchPositionCorrection touchPositionCorrection) { + 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 +199,55 @@ 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; + } } - 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 void fillArrayWithNearestKeyCodes(int x, int y, int primaryKeyCode, int[] dest) { + final int destLength = dest.length; + if (destLength < 1) { + return; + } + int index = 0; + if (primaryKeyCode > Keyboard.CODE_SPACE) { + dest[index++] = primaryKeyCode; + } + final Key[] nearestKeys = getNearestKeys(x, y); + for (Key key : nearestKeys) { + if (index >= destLength) { + break; + } + final int code = key.mCode; + if (code <= Keyboard.CODE_SPACE) { + break; + } + dest[index++] = code; + } + if (index < destLength) { + dest[index] = KeyDetector.NOT_A_CODE; + } + } + + 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/SuddenJumpingTouchEventHandler.java b/java/src/com/android/inputmethod/keyboard/SuddenJumpingTouchEventHandler.java index 62a9259f9..347383f95 100644 --- a/java/src/com/android/inputmethod/keyboard/SuddenJumpingTouchEventHandler.java +++ b/java/src/com/android/inputmethod/keyboard/SuddenJumpingTouchEventHandler.java @@ -17,12 +17,12 @@ package com.android.inputmethod.keyboard; import android.content.Context; -import android.os.Build; import android.util.Log; import android.view.MotionEvent; import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.Utils; public class SuddenJumpingTouchEventHandler { private static final String TAG = SuddenJumpingTouchEventHandler.class.getSimpleName(); @@ -49,18 +49,8 @@ public class SuddenJumpingTouchEventHandler { public SuddenJumpingTouchEventHandler(Context context, ProcessMotionEvent view) { mView = view; - final String[] deviceList = context.getResources().getStringArray( - R.array.sudden_jumping_touch_event_device_list); - mNeedsSuddenJumpingHack = needsSuddenJumpingHack(Build.HARDWARE, deviceList); - } - - private static boolean needsSuddenJumpingHack(String deviceName, String[] deviceList) { - for (String device : deviceList) { - if (device.equalsIgnoreCase(deviceName)) { - return true; - } - } - return false; + mNeedsSuddenJumpingHack = Boolean.parseBoolean(Utils.getDeviceOverrideValue( + context.getResources(), R.array.sudden_jumping_touch_event_device_list, "false")); } public void setKeyboard(Keyboard newKeyboard) { diff --git a/java/src/com/android/inputmethod/compat/FrameLayoutCompatUtils.java b/java/src/com/android/inputmethod/keyboard/ViewLayoutUtils.java index 523bf7d0e..ee5047083 100644 --- a/java/src/com/android/inputmethod/compat/FrameLayoutCompatUtils.java +++ b/java/src/com/android/inputmethod/keyboard/ViewLayoutUtils.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.inputmethod.compat; +package com.android.inputmethod.keyboard; import android.view.View; import android.view.ViewGroup; @@ -22,20 +22,9 @@ import android.view.ViewGroup.MarginLayoutParams; import android.widget.FrameLayout; import android.widget.RelativeLayout; -public class FrameLayoutCompatUtils { - private static final boolean NEEDS_FRAME_LAYOUT_HACK = ( - android.os.Build.VERSION.SDK_INT < 11 /* Honeycomb */); - - public static ViewGroup getPlacer(ViewGroup container) { - if (NEEDS_FRAME_LAYOUT_HACK) { - // Insert RelativeLayout to be able to setMargin because pre-Honeycomb FrameLayout - // could not handle setMargin properly. - final ViewGroup placer = new RelativeLayout(container.getContext()); - container.addView(placer); - return placer; - } else { - return container; - } +public class ViewLayoutUtils { + private ViewLayoutUtils() { + // This utility class is not publicly instantiable. } public static MarginLayoutParams newLayoutParam(ViewGroup placer, int width, int height) { 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..ded89b1b8 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardIconsSet.java @@ -23,86 +23,94 @@ 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 = 16; + + 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); + addIconIdMap(15, "zwnjKey", R.styleable.Keyboard_iconZwnjKey); + addIconIdMap(16, "zwjKey", R.styleable.Keyboard_iconZwjKey); + } + + 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..55664d411 --- /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.keyboard.Keyboard; +import com.android.inputmethod.latin.VibratorUtils; + +/** + * 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 VibratorUtils mVibratorUtils; + private boolean mSoundOn; + + public AudioAndHapticFeedbackManager(final LatinIME latinIme, + final SettingsValues settingsValues) { + mSettingsValues = settingsValues; + mVibratorUtils = VibratorUtils.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 (mVibratorUtils != null) { + mVibratorUtils.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..38444a10c 100644 --- a/java/src/com/android/inputmethod/latin/AutoCorrection.java +++ b/java/src/com/android/inputmethod/latin/AutoCorrection.java @@ -16,57 +16,41 @@ package com.android.inputmethod.latin; +import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; + import android.text.TextUtils; import android.util.Log; import java.util.ArrayList; -import java.util.Map; +import java.util.HashMap; 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; - } - - public boolean hasAutoCorrection() { - return mHasAutoCorrection; - } - - public CharSequence getAutoCorrectionWord() { - return mAutoCorrectionWord; - } - public double getNormalizedScore() { - return mNormalizedScore; + private AutoCorrection() { + // Purely static class: can't instantiate. } - public void updateAutoCorrectionStatus(Map<String, Dictionary> dictionaries, - WordComposer wordComposer, ArrayList<CharSequence> suggestions, int[] sortedScores, - CharSequence typedWord, double autoCorrectionThreshold, int correctionMode, + public static CharSequence computeAutoCorrectionWord( + HashMap<String, Dictionary> dictionaries, + WordComposer wordComposer, ArrayList<SuggestedWordInfo> suggestions, + 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, + consideredWord, autoCorrectionThreshold)) { + return suggestions.get(0).mWord; } + return null; } public static boolean isValidWord( - Map<String, Dictionary> dictionaries, CharSequence word, boolean ignoreCase) { + HashMap<String, Dictionary> dictionaries, CharSequence word, boolean ignoreCase) { if (TextUtils.isEmpty(word)) { return false; } @@ -74,6 +58,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; @@ -83,7 +75,7 @@ public class AutoCorrection { } public static boolean allowsToBeAutoCorrected( - Map<String, Dictionary> dictionaries, CharSequence word, boolean ignoreCase) { + HashMap<String, Dictionary> dictionaries, CharSequence word, boolean ignoreCase) { final WhitelistDictionary whitelistDictionary = (WhitelistDictionary)dictionaries.get(Suggest.DICT_KEY_WHITELIST); // If "word" is in the whitelist dictionary, it should not be auto corrected. @@ -98,34 +90,32 @@ 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( + HashMap<String, Dictionary> dictionaries, WordComposer wordComposer, + ArrayList<SuggestedWordInfo> 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) { - final CharSequence autoCorrectionSuggestion = suggestions.get(0); - final int autoCorrectionSuggestionScore = sortedScores[0]; + private static boolean hasAutoCorrectionForBinaryDictionary(WordComposer wordComposer, + ArrayList<SuggestedWordInfo> suggestions, + CharSequence consideredWord, double autoCorrectionThreshold) { + if (wordComposer.size() > 1 && suggestions.size() > 0) { + final SuggestedWordInfo autoCorrectionSuggestion = suggestions.get(0); + //final int autoCorrectionSuggestionScore = sortedScores[0]; + final int autoCorrectionSuggestionScore = autoCorrectionSuggestion.mScore; // 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.mWord.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..c43683f2d 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -40,14 +40,13 @@ public class BinaryDictionary extends Dictionary { public static final int MAX_WORDS = 18; private static final String TAG = "BinaryDictionary"; - private static final int MAX_PROXIMITY_CHARS_SIZE = ProximityInfo.MAX_PROXIMITY_CHARS_SIZE; private static final int MAX_BIGRAMS = 60; private static final int TYPED_LETTER_MULTIPLIER = 2; private int mDicTypeId; - private int mNativeDict; - private final int[] mInputCodes = new int[MAX_WORD_LENGTH * MAX_PROXIMITY_CHARS_SIZE]; + private long mNativeDict; + private final int[] mInputCodes = new int[MAX_WORD_LENGTH]; private final char[] mOutputChars = new char[MAX_WORD_LENGTH * MAX_WORDS]; private final char[] mOutputChars_bigrams = new char[MAX_WORD_LENGTH * MAX_BIGRAMS]; private final int[] mScores = new int[MAX_WORDS]; @@ -55,6 +54,8 @@ public class BinaryDictionary extends Dictionary { public static final Flag FLAG_REQUIRES_GERMAN_UMLAUT_PROCESSING = new Flag(R.bool.config_require_umlaut_processing, 0x1); + public static final Flag FLAG_REQUIRES_FRENCH_LIGATURES_PROCESSING = + new Flag(R.bool.config_require_ligatures_processing, 0x4); // FULL_EDIT_DISTANCE is a flag that forces the dictionary to use full words // when computing edit distance, instead of the default behavior of stopping @@ -77,6 +78,7 @@ public class BinaryDictionary extends Dictionary { // actual value will be read from the configuration/extra value at run time for // the configuration at dictionary creation time. FLAG_REQUIRES_GERMAN_UMLAUT_PROCESSING, + FLAG_REQUIRES_FRENCH_LIGATURES_PROCESSING, }; private int mFlags = 0; @@ -104,25 +106,27 @@ public class BinaryDictionary extends Dictionary { } static { - Utils.loadNativeLibrary(); + JniUtils.loadNativeLibrary(); } - private native int 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 long openNative(String sourceDir, long dictOffset, long dictSize, + int typedLetterMultiplier, int fullWordMultiplier, int maxWordLength, int maxWords); + 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); + int maxWordLength, int maxBigrams); + 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, - TYPED_LETTER_MULTIPLIER, FULL_WORD_SCORE_MULTIPLIER, - MAX_WORD_LENGTH, MAX_WORDS, MAX_PROXIMITY_CHARS_SIZE); + TYPED_LETTER_MULTIPLIER, FULL_WORD_SCORE_MULTIPLIER, MAX_WORD_LENGTH, MAX_WORDS); } @Override @@ -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) { + mInputCodes[0] = codes.getCodeAt(0); + } int count = getBigramsNative(mNativeDict, chars, chars.length, mInputCodes, codesSize, - mOutputChars_bigrams, mBigramScores, MAX_WORD_LENGTH, MAX_BIGRAMS, - MAX_PROXIMITY_CHARS_SIZE); + mOutputChars_bigrams, mBigramScores, MAX_WORD_LENGTH, MAX_BIGRAMS); + if (count > MAX_BIGRAMS) { + count = MAX_BIGRAMS; + } 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); } } } @@ -198,9 +199,7 @@ public class BinaryDictionary extends Dictionary { Arrays.fill(mInputCodes, WordComposer.NOT_A_CODE); for (int i = 0; i < codesSize; i++) { - int[] alternatives = codes.getCodesAt(i); - System.arraycopy(alternatives, 0, mInputCodes, i * MAX_PROXIMITY_CHARS_SIZE, - Math.min(alternatives.length, MAX_PROXIMITY_CHARS_SIZE)); + mInputCodes[i] = codes.getCodeAt(i); } Arrays.fill(outputChars, (char) 0); Arrays.fill(scores, 0); @@ -211,6 +210,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/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java index 9ffc7d0a2..311d3dc9d 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java @@ -196,8 +196,8 @@ public class BinaryDictionaryFileDumper { } finally { // Ignore exceptions while closing files. try { - // afd.close() will close inputStream, we should not call inputStream.close(). - if (null != afd) afd.close(); + // inputStream.close() will close afd, we should not call afd.close(). + if (null != inputStream) inputStream.close(); } catch (Exception e) { Log.e(TAG, "Exception while closing a cross-process file descriptor : " + e); } @@ -252,7 +252,7 @@ public class BinaryDictionaryFileDumper { * also apply. * * @param input the stream to be copied. - * @param outputFile an outputstream to copy the data to. + * @param output an output stream to copy the data to. */ private static void checkMagicAndCopyFileTo(final BufferedInputStream input, final FileOutputStream output) throws FileNotFoundException, IOException { diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java index b333e4873..e4d839690 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java @@ -23,9 +23,10 @@ import android.content.res.AssetFileDescriptor; import android.content.res.Resources; import android.util.Log; +import com.android.inputmethod.latin.LocaleUtils.RunInLocale; + import java.io.File; import java.util.ArrayList; -import java.util.List; import java.util.Locale; /** @@ -75,7 +76,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 +94,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); @@ -153,11 +156,13 @@ class BinaryDictionaryGetter { */ private static AssetFileAddress loadFallbackResource(final Context context, final int fallbackResId, final Locale locale) { - final Resources res = context.getResources(); - final Locale savedLocale = LocaleUtils.setSystemLocale(res, locale); - final AssetFileDescriptor afd = res.openRawResourceFd(fallbackResId); - LocaleUtils.setSystemLocale(res, savedLocale); - + final RunInLocale<AssetFileDescriptor> job = new RunInLocale<AssetFileDescriptor>() { + @Override + protected AssetFileDescriptor job(Resources res) { + return res.openRawResourceFd(fallbackResId); + } + }; + final AssetFileDescriptor afd = job.runInLocale(context.getResources(), locale); if (afd == null) { Log.e(TAG, "Found the resource but cannot read it. Is it compressed? resId=" + fallbackResId); @@ -262,9 +267,9 @@ class BinaryDictionaryGetter { * - Gets a file name from the fallback resource passed as an argument. * If that fails: * - Returns null. - * @return The address of a valid file, or null. + * @return The list of addresses of valid dictionary files, or null. */ - public static List<AssetFileAddress> getDictionaryFiles(final Locale locale, + public static ArrayList<AssetFileAddress> getDictionaryFiles(final Locale locale, final Context context, final int fallbackResId) { // cacheWordListsFromContentProvider returns the list of files it copied to local 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..23d63b42a 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 TAG = DebugSettings.class.getSimpleName(); 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..9d26a2343 100644 --- a/java/src/com/android/inputmethod/latin/Dictionary.java +++ b/java/src/com/android/inputmethod/latin/Dictionary.java @@ -33,13 +33,12 @@ 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. - * @see #getWords(WordComposer, WordCallback) + * @see #getWords(WordComposer, WordCallback, ProximityInfo) */ public interface WordCallback { /** @@ -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..5de770a4a 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryCollection.java +++ b/java/src/com/android/inputmethod/latin/DictionaryCollection.java @@ -18,17 +18,18 @@ 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; import java.util.concurrent.CopyOnWriteArrayList; /** * Class for a collection of dictionaries that behave like one dictionary. */ public class DictionaryCollection extends Dictionary { - - protected final List<Dictionary> mDictionaries; + private final String TAG = DictionaryCollection.class.getSimpleName(); + protected final CopyOnWriteArrayList<Dictionary> mDictionaries; public DictionaryCollection() { mDictionaries = new CopyOnWriteArrayList<Dictionary>(); @@ -75,7 +76,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..7be374db5 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java @@ -21,16 +21,17 @@ import android.content.res.AssetFileDescriptor; import android.content.res.Resources; import android.util.Log; +import com.android.inputmethod.latin.LocaleUtils.RunInLocale; + import java.io.File; +import java.util.ArrayList; import java.util.LinkedList; -import java.util.List; import java.util.Locale; /** * Factory for dictionary instances. */ public class DictionaryFactory { - private static String TAG = DictionaryFactory.class.getSimpleName(); /** @@ -52,8 +53,8 @@ public class DictionaryFactory { return new DictionaryCollection(createBinaryDictionary(context, fallbackResId, locale)); } - final List<Dictionary> dictList = new LinkedList<Dictionary>(); - final List<AssetFileAddress> assetFileList = + final LinkedList<Dictionary> dictList = new LinkedList<Dictionary>(); + final ArrayList<AssetFileAddress> assetFileList = BinaryDictionaryGetter.getDictionaryFiles(locale, context, fallbackResId); if (null != assetFileList) { for (final AssetFileAddress f : assetFileList) { @@ -98,14 +99,13 @@ public class DictionaryFactory { final int resId, final Locale locale) { AssetFileDescriptor afd = null; try { - final Resources res = context.getResources(); - if (null != locale) { - final Locale savedLocale = LocaleUtils.setSystemLocale(res, locale); - afd = res.openRawResourceFd(resId); - LocaleUtils.setSystemLocale(res, savedLocale); - } else { - afd = res.openRawResourceFd(resId); - } + final RunInLocale<AssetFileDescriptor> job = new RunInLocale<AssetFileDescriptor>() { + @Override + protected AssetFileDescriptor job(Resources res) { + return res.openRawResourceFd(resId); + } + }; + afd = job.runInLocale(context.getResources(), locale); if (afd == null) { Log.e(TAG, "Found the resource but it is compressed. resId=" + resId); return null; @@ -161,39 +161,41 @@ public class DictionaryFactory { * @return whether a (non-placeholder) dictionary is available or not. */ public static boolean isDictionaryAvailable(Context context, Locale locale) { - final Resources res = context.getResources(); - final Locale saveLocale = LocaleUtils.setSystemLocale(res, locale); - - final int resourceId = Utils.getMainDictionaryResourceId(res); - final AssetFileDescriptor afd = res.openRawResourceFd(resourceId); - final boolean hasDictionary = isFullDictionary(afd); - try { - if (null != afd) afd.close(); - } catch (java.io.IOException e) { - /* Um, what can we do here exactly? */ - } - - LocaleUtils.setSystemLocale(res, saveLocale); - return hasDictionary; + final RunInLocale<Boolean> job = new RunInLocale<Boolean>() { + @Override + protected Boolean job(Resources res) { + final int resourceId = getMainDictionaryResourceId(res); + final AssetFileDescriptor afd = res.openRawResourceFd(resourceId); + final boolean hasDictionary = isFullDictionary(afd); + try { + if (null != afd) afd.close(); + } catch (java.io.IOException e) { + /* Um, what can we do here exactly? */ + } + return hasDictionary; + } + }; + return job.runInLocale(context.getResources(), locale); } // TODO: Do not use the size of the dictionary as an unique dictionary ID. public static Long getDictionaryId(final Context context, final Locale locale) { - final Resources res = context.getResources(); - final Locale saveLocale = LocaleUtils.setSystemLocale(res, locale); - - final int resourceId = Utils.getMainDictionaryResourceId(res); - final AssetFileDescriptor afd = res.openRawResourceFd(resourceId); - final Long size = (afd != null && afd.getLength() > PLACEHOLDER_LENGTH) - ? afd.getLength() - : null; - try { - if (null != afd) afd.close(); - } catch (java.io.IOException e) { - } - - LocaleUtils.setSystemLocale(res, saveLocale); - return size; + final RunInLocale<Long> job = new RunInLocale<Long>() { + @Override + protected Long job(Resources res) { + final int resourceId = getMainDictionaryResourceId(res); + final AssetFileDescriptor afd = res.openRawResourceFd(resourceId); + final Long size = (afd != null && afd.getLength() > PLACEHOLDER_LENGTH) + ? afd.getLength() + : null; + try { + if (null != afd) afd.close(); + } catch (java.io.IOException e) { + } + return size; + } + }; + return job.runInLocale(context.getResources(), locale); } // TODO: Find the Right Way to find out whether the resource is a placeholder or not. @@ -209,4 +211,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..b3f613bae 100644 --- a/java/src/com/android/inputmethod/latin/EditingUtils.java +++ b/java/src/com/android/inputmethod/latin/EditingUtils.java @@ -1,12 +1,12 @@ /* * Copyright (C) 2009 The Android Open Source Project - * + * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * 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,8 +16,6 @@ package com.android.inputmethod.latin; -import com.android.inputmethod.compat.InputConnectionCompatUtils; - import android.text.TextUtils; import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedTextRequest; @@ -87,23 +85,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 { @@ -263,7 +244,7 @@ public class EditingUtils { if (selStart == selEnd) { // There is just a cursor, so get the word at the cursor // getWordRangeAtCursor returns null if the connection is null - EditingUtils.Range range = getWordRangeAtCursor(ic, wordSeparators); + final EditingUtils.Range range = getWordRangeAtCursor(ic, wordSeparators); if (range != null && !TextUtils.isEmpty(range.mWord)) { return new SelectedWord(selStart - range.mCharsBefore, selEnd + range.mCharsAfter, range.mWord); @@ -271,20 +252,19 @@ public class EditingUtils { } else { if (null == ic) return null; // Is the previous character empty or a word separator? If not, return null. - CharSequence charsBefore = ic.getTextBeforeCursor(1, 0); + final CharSequence charsBefore = ic.getTextBeforeCursor(1, 0); if (!isWordBoundary(charsBefore, wordSeparators)) { return null; } // Is the next character empty or a word separator? If not, return null. - CharSequence charsAfter = ic.getTextAfterCursor(1, 0); + final CharSequence charsAfter = ic.getTextAfterCursor(1, 0); if (!isWordBoundary(charsAfter, wordSeparators)) { return null; } // Extract the selection alone - CharSequence touching = InputConnectionCompatUtils.getSelectedText( - ic, selStart, selEnd); + final CharSequence touching = ic.getSelectedText(0); if (TextUtils.isEmpty(touching)) return null; // Is any part of the selection a separator? If so, return null. final int length = touching.length(); diff --git a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java index cad69bb0e..46d11fa37 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java @@ -18,6 +18,7 @@ package com.android.inputmethod.latin; import android.content.Context; +import com.android.inputmethod.keyboard.KeyDetector; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.ProximityInfo; @@ -28,17 +29,12 @@ import java.util.LinkedList; * be searched for suggestions and valid words. */ public class ExpandableDictionary extends Dictionary { - /** - * There is difference between what java and native code can handle. - * It uses 32 because Java stack overflows when greater value is used. - */ - protected static final int MAX_WORD_LENGTH = 32; // Bigram frequency is a fixed point number with 1 meaning 1.2 and 255 meaning 1.8. protected static final int BIGRAM_MAX_FREQUENCY = 255; private Context mContext; - private char[] mWordBuilder = new char[MAX_WORD_LENGTH]; + private char[] mWordBuilder = new char[BinaryDictionary.MAX_WORD_LENGTH]; private int mDicTypeId; private int mMaxDepth; private int mInputLength; @@ -51,6 +47,7 @@ public class ExpandableDictionary extends Dictionary { private Object mUpdatingLock = new Object(); private static class Node { + Node() {} char mCode; int mFrequency; boolean mTerminal; @@ -112,7 +109,7 @@ public class ExpandableDictionary extends Dictionary { public ExpandableDictionary(Context context, int dicTypeId) { mContext = context; clearDictionary(); - mCodes = new int[MAX_WORD_LENGTH][]; + mCodes = new int[BinaryDictionary.MAX_WORD_LENGTH][]; mDicTypeId = dicTypeId; } @@ -150,10 +147,13 @@ public class ExpandableDictionary extends Dictionary { } public int getMaxWordLength() { - return MAX_WORD_LENGTH; + return BinaryDictionary.MAX_WORD_LENGTH; } public void addWord(String word, int frequency) { + if (word.length() >= BinaryDictionary.MAX_WORD_LENGTH) { + return; + } addWordRec(mRoots, word, 0, frequency, null); } @@ -200,6 +200,9 @@ public class ExpandableDictionary extends Dictionary { // Currently updating contacts, don't return any results. if (mUpdatingDictionary) return; } + if (codes.size() >= BinaryDictionary.MAX_WORD_LENGTH) { + return; + } getWordsInner(codes, callback, proximityInfo); } @@ -207,9 +210,19 @@ public class ExpandableDictionary extends Dictionary { @SuppressWarnings("unused") final ProximityInfo proximityInfo) { mInputLength = codes.size(); if (mCodes.length < mInputLength) mCodes = new int[mInputLength][]; + final int[] xCoordinates = codes.getXCoordinates(); + final int[] yCoordinates = codes.getYCoordinates(); // Cache the codes so that we don't have to lookup an array list for (int i = 0; i < mInputLength; i++) { - mCodes[i] = codes.getCodesAt(i); + // TODO: Calculate proximity info here. + if (mCodes[i] == null || mCodes[i].length < 1) { + mCodes[i] = new int[ProximityInfo.MAX_PROXIMITY_CHARS_SIZE]; + } + final int x = xCoordinates != null && i < xCoordinates.length ? + xCoordinates[i] : WordComposer.NOT_A_COORDINATE; + final int y = xCoordinates != null && i < yCoordinates.length ? + yCoordinates[i] : WordComposer.NOT_A_COORDINATE; + proximityInfo.fillArrayWithNearestKeyCodes(x, y, codes.getCodeAt(i), mCodes[i]); } mMaxDepth = mInputLength * 3; getWordsRec(mRoots, codes, mWordBuilder, 0, false, 1, 0, -1, callback); @@ -300,7 +313,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; } } @@ -318,11 +331,11 @@ public class ExpandableDictionary extends Dictionary { } } else { // Don't use alternatives if we're looking for missing characters - final int alternativesSize = skipPos >= 0? 1 : currentChars.length; + final int alternativesSize = skipPos >= 0 ? 1 : currentChars.length; for (int j = 0; j < alternativesSize; j++) { final int addedAttenuation = (j > 0 ? 1 : 2); final int currentChar = currentChars[j]; - if (currentChar == -1) { + if (currentChar == KeyDetector.NOT_A_CODE) { break; } if (currentChar == lowerC || currentChar == c) { @@ -341,7 +354,7 @@ public class ExpandableDictionary extends Dictionary { snr * addedAttenuation, mInputLength); } callback.addWord(word, 0, depth + 1, finalFreq, mDicTypeId, - DataType.UNIGRAM); + Dictionary.UNIGRAM); } } if (children != null) { @@ -483,7 +496,7 @@ public class ExpandableDictionary extends Dictionary { } // Local to reverseLookUp, but do not allocate each time. - private final char[] mLookedUpString = new char[MAX_WORD_LENGTH]; + private final char[] mLookedUpString = new char[BinaryDictionary.MAX_WORD_LENGTH]; /** * reverseLookUp retrieves the full word given a list of terminal nodes and adds those words @@ -497,15 +510,15 @@ public class ExpandableDictionary extends Dictionary { for (NextWord nextWord : terminalNodes) { node = nextWord.mWord; freq = nextWord.getFrequency(); - int index = MAX_WORD_LENGTH; + int index = BinaryDictionary.MAX_WORD_LENGTH; do { --index; mLookedUpString[index] = node.mCode; node = node.mParent; } while (node != null); - callback.addWord(mLookedUpString, index, MAX_WORD_LENGTH - index, freq, mDicTypeId, - DataType.BIGRAM); + callback.addWord(mLookedUpString, index, BinaryDictionary.MAX_WORD_LENGTH - index, + freq, mDicTypeId, Dictionary.BIGRAM); } } @@ -547,6 +560,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..a6ce04069 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/InputAttributes.java @@ -0,0 +1,165 @@ +/* + * 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; + +/** + * 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 (InputTypeUtils.isPasswordInputType(inputType) + || InputTypeUtils.isVisiblePasswordInputType(inputType) + || InputTypeUtils.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; + } + } + + @SuppressWarnings("unused") + 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/InputTypeUtils.java b/java/src/com/android/inputmethod/latin/InputTypeUtils.java new file mode 100644 index 000000000..40c3b765e --- /dev/null +++ b/java/src/com/android/inputmethod/latin/InputTypeUtils.java @@ -0,0 +1,90 @@ +/* + * 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.InputType; + +public class InputTypeUtils implements InputType { + private static final int WEB_TEXT_PASSWORD_INPUT_TYPE = + TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_WEB_PASSWORD; + private static final int WEB_TEXT_EMAIL_ADDRESS_INPUT_TYPE = + TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS; + private static final int NUMBER_PASSWORD_INPUT_TYPE = + TYPE_CLASS_NUMBER | TYPE_NUMBER_VARIATION_PASSWORD; + private static final int TEXT_PASSWORD_INPUT_TYPE = + TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_PASSWORD; + private static final int TEXT_VISIBLE_PASSWORD_INPUT_TYPE = + TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_VISIBLE_PASSWORD; + + private InputTypeUtils() { + // This utility class is not publicly instantiable. + } + + private static boolean isWebEditTextInputType(int inputType) { + return inputType == (TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_WEB_EDIT_TEXT); + } + + private static boolean isWebPasswordInputType(int inputType) { + return WEB_TEXT_PASSWORD_INPUT_TYPE != 0 + && inputType == WEB_TEXT_PASSWORD_INPUT_TYPE; + } + + private static boolean isWebEmailAddressInputType(int inputType) { + return WEB_TEXT_EMAIL_ADDRESS_INPUT_TYPE != 0 + && inputType == WEB_TEXT_EMAIL_ADDRESS_INPUT_TYPE; + } + + private static boolean isNumberPasswordInputType(int inputType) { + return NUMBER_PASSWORD_INPUT_TYPE != 0 + && inputType == NUMBER_PASSWORD_INPUT_TYPE; + } + + private static boolean isTextPasswordInputType(int inputType) { + return inputType == TEXT_PASSWORD_INPUT_TYPE; + } + + private static boolean isWebEmailAddressVariation(int variation) { + return variation == TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS; + } + + public static boolean isEmailVariation(int variation) { + return variation == TYPE_TEXT_VARIATION_EMAIL_ADDRESS + || isWebEmailAddressVariation(variation); + } + + public static boolean isWebInputType(int inputType) { + final int maskedInputType = + inputType & (TYPE_MASK_CLASS | TYPE_MASK_VARIATION); + return isWebEditTextInputType(maskedInputType) || isWebPasswordInputType(maskedInputType) + || isWebEmailAddressInputType(maskedInputType); + } + + // Please refer to TextView.isPasswordInputType + public static boolean isPasswordInputType(int inputType) { + final int maskedInputType = + inputType & (TYPE_MASK_CLASS | TYPE_MASK_VARIATION); + return isTextPasswordInputType(maskedInputType) || isWebPasswordInputType(maskedInputType) + || isNumberPasswordInputType(maskedInputType); + } + + // Please refer to TextView.isVisiblePasswordInputType + public static boolean isVisiblePasswordInputType(int inputType) { + final int maskedInputType = + inputType & (TYPE_MASK_CLASS | TYPE_MASK_VARIATION); + return maskedInputType == TEXT_VISIBLE_PASSWORD_INPUT_TYPE; + } +} 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..af0ef4b37 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/LastComposedWord.java @@ -0,0 +1,84 @@ +/* + * 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; + +/** + * 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 int[] mPrimaryKeyCodes; + 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 int[] primaryKeyCodes, final int[] xCoordinates, + final int[] yCoordinates, final String typedWord, final String committedWord, + final int separatorCode) { + mPrimaryKeyCodes = primaryKeyCodes; + 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 249dc564e..db57044e9 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -30,6 +30,7 @@ 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; @@ -39,47 +40,45 @@ 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.ViewParent; import android.view.ViewGroup.LayoutParams; +import android.view.ViewParent; +import android.view.Window; +import android.view.WindowManager; import android.view.inputmethod.CompletionInfo; +import android.view.inputmethod.CorrectionInfo; import android.view.inputmethod.EditorInfo; -import android.view.inputmethod.ExtractedText; import android.view.inputmethod.InputConnection; +import android.view.inputmethod.InputMethodSubtype; 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.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.LocaleUtils.RunInLocale; +import com.android.inputmethod.latin.define.ProductionFlag; +import com.android.inputmethod.latin.suggestions.SuggestionsView; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.util.ArrayList; import java.util.Locale; /** * Input method implementation for Qwerty'ish keyboard. */ -public class LatinIME extends InputMethodServiceCompatWrapper implements KeyboardActionListener, +public class LatinIME extends InputMethodService 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; @@ -109,7 +108,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"; /** @@ -119,12 +121,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar public static final String SUBTYPE_EXTRA_VALUE_ASCII_CAPABLE = "AsciiCapable"; /** - * The subtype extra value used to indicate that the subtype keyboard layout supports touch - * position correction. - */ - public static final String SUBTYPE_EXTRA_VALUE_SUPPORT_TOUCH_POSITION_CORRECTION = - "SupportTouchPositionCorrection"; - /** * The subtype extra value used to indicate that the subtype keyboard layout should be loaded * from the specified locale. */ @@ -145,6 +141,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; @@ -159,51 +156,55 @@ 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 VoiceProxy mVoiceProxy; + /* package for tests */ final KeyboardSwitcher mKeyboardSwitcher; + private final SubtypeSwitcher mSubtypeSwitcher; + 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 final StringBuilder mComposingStringBuilder = new StringBuilder(); + private UserHistoryDictionary mUserHistoryDictionary; + private boolean mIsUserDictionaryAvailable; + + 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. @@ -211,15 +212,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; @@ -231,29 +224,22 @@ 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; + + private AlertDialog mOptionsDialog; 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); @@ -261,27 +247,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(); @@ -292,25 +269,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar case MSG_SET_BIGRAM_PREDICTIONS: latinIme.updateBigramPredictions(); break; - case MSG_VOICE_RESULTS: - 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); - } - break; } } @@ -327,7 +285,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); } @@ -345,34 +303,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar removeMessages(MSG_SET_BIGRAM_PREDICTIONS); } - public void updateVoiceResults() { - 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); @@ -386,21 +316,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); @@ -418,18 +340,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; @@ -437,30 +359,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) { @@ -470,6 +394,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } else { final LatinIME latinIme = getOuterInstance(); latinIme.onFinishInputViewInternal(finishingInput); + mAppliedEditorInfo = null; } } @@ -485,24 +410,28 @@ 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); mPrefs = prefs; LatinImeLogger.init(this, prefs); - LanguageSwitcherProxy.init(this, prefs); + if (ProductionFlag.IS_EXPERIMENTAL) { + ResearchLogger.init(this, prefs); + } 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; @@ -511,6 +440,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) { @@ -527,10 +460,9 @@ 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); final IntentFilter packageFilter = new IntentFilter(); packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED); @@ -547,50 +479,52 @@ 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()); + final RunInLocale<SettingsValues> job = new RunInLocale<SettingsValues>() { + @Override + protected SettingsValues job(Resources res) { + return new SettingsValues(mPrefs, LatinIME.this); + } + }; + mSettingsValues = job.runInLocale(mResources, mSubtypeSwitcher.getInputLocale()); + mFeedbackManager = new AudioAndHapticFeedbackManager(this, mSettingsValues); resetContactsDictionary(null == mSuggest ? null : mSuggest.getContactsDictionary()); - updateSoundEffectVolume(); - updateKeypressVibrationDuration(); } private void initSuggest() { final String localeStr = mSubtypeSwitcher.getInputLocaleStr(); - final Locale keyboardLocale = LocaleUtils.constructLocaleFromString(localeStr); - - final Resources res = mResources; - final Locale savedLocale = LocaleUtils.setSystemLocale(res, keyboardLocale); - final ContactsDictionary oldContactsDictionary; - if (mSuggest != null) { - oldContactsDictionary = mSuggest.getContactsDictionary(); - mSuggest.close(); - } else { - oldContactsDictionary = null; - } - - int mainDicResId = Utils.getMainDictionaryResourceId(res); - mSuggest = new Suggest(this, mainDicResId, keyboardLocale); - if (mSettingsValues.mAutoCorrectEnabled) { - mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold); - } - - mUserDictionary = new UserDictionary(this, localeStr); - mSuggest.setUserDictionary(mUserDictionary); - mIsUserDictionaryAvaliable = mUserDictionary.isEnabled(); + final Locale keyboardLocale = mSubtypeSwitcher.getInputLocale(); - resetContactsDictionary(oldContactsDictionary); + final Context context = this; + final RunInLocale<Void> job = new RunInLocale<Void>() { + @Override + protected Void job(Resources res) { + final ContactsDictionary oldContactsDictionary; + if (mSuggest != null) { + oldContactsDictionary = mSuggest.getContactsDictionary(); + mSuggest.close(); + } else { + oldContactsDictionary = null; + } - mUserUnigramDictionary - = new UserUnigramDictionary(this, this, localeStr, Suggest.DIC_USER_UNIGRAM); - mSuggest.setUserUnigramDictionary(mUserUnigramDictionary); + int mainDicResId = DictionaryFactory.getMainDictionaryResourceId(res); + mSuggest = new Suggest(context, mainDicResId, keyboardLocale); + if (mSettingsValues.mAutoCorrectEnabled) { + mSuggest.setAutoCorrectionThreshold(mSettingsValues.mAutoCorrectionThreshold); + } - mUserBigramDictionary - = new UserBigramDictionary(this, this, localeStr, Suggest.DIC_USER_BIGRAM); - mSuggest.setUserBigramDictionary(mUserBigramDictionary); + mUserDictionary = new UserDictionary(context, localeStr); + mSuggest.setUserDictionary(mUserDictionary); + mIsUserDictionaryAvailable = mUserDictionary.isEnabled(); - updateCorrectionMode(); + resetContactsDictionary(oldContactsDictionary); - LocaleUtils.setSystemLocale(res, savedLocale); + mUserHistoryDictionary + = new UserHistoryDictionary(context, localeStr, Suggest.DIC_USER_HISTORY); + mSuggest.setUserHistoryDictionary(mUserHistoryDictionary); + return null; + } + }; + job.runInLocale(mResources, keyboardLocale); } /** @@ -626,9 +560,8 @@ 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); + final Locale keyboardLocale = mSubtypeSwitcher.getInputLocale(); + int mainDicResId = DictionaryFactory.getMainDictionaryResourceId(mResources); mSuggest.resetMainDict(this, mainDicResId, keyboardLocale); } @@ -640,7 +573,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } unregisterReceiver(mReceiver); unregisterReceiver(mDictionaryPackInstallReceiver); - mVoiceProxy.destroy(); LatinImeLogger.commit(); LatinImeLogger.onDestroy(); super.onDestroy(); @@ -649,25 +581,17 @@ 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; super.onConfigurationChanged(conf); - mVoiceProxy.onConfigurationChanged(conf); - mConfigurationChanging = false; - - // This will work only when the subtype is not supported. - LanguageSwitcherProxy.onConfigurationChanged(conf); } @Override @@ -697,13 +621,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 @@ -716,20 +640,44 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar mHandler.onFinishInput(); } - private void onStartInputInternal(EditorInfo attribute, boolean restarting) { - super.onStartInput(attribute, restarting); + @Override + public void onCurrentInputMethodSubtypeChanged(InputMethodSubtype subtype) { + SubtypeSwitcher.getInstance().updateSubtype(subtype); } - private void onStartInputViewInternal(EditorInfo attribute, boolean restarting) { - super.onStartInputView(attribute, restarting); + private void onStartInputInternal(EditorInfo editorInfo, boolean restarting) { + super.onStartInput(editorInfo, 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; @@ -738,47 +686,35 @@ 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) - || 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); - // 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) @@ -787,83 +723,15 @@ 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()); - 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(); @@ -876,12 +744,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar LatinImeLogger.commit(); - mVoiceProxy.flushVoiceInputLogs(mConfigurationChanging); - KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); if (inputView != null) inputView.closing(); - if (mUserUnigramDictionary != null) mUserUnigramDictionary.flushPendingWrites(); - if (mUserBigramDictionary != null) mUserBigramDictionary.flushPendingWrites(); + if (mUserHistoryDictionary != null) mUserHistoryDictionary.flushPendingWrites(); } private void onFinishInputViewInternal(boolean finishingInput) { @@ -894,18 +759,25 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } @Override - public void onUpdateExtractedText(int token, ExtractedText text) { - super.onUpdateExtractedText(token, text); - mVoiceProxy.showPunctuationHintIfNecessary(); - } - - @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 (ProductionFlag.IS_EXPERIMENTAL) { + if (ResearchLogger.UnsLogGroup.ON_UPDATE_SELECTION.isEnabled) { + final String s = "onUpdateSelection: oss=" + oldSelStart + + ", ose=" + oldSelEnd + + ", lss=" + mLastSelectionStart + + ", lse=" + mLastSelectionEnd + + ", nss=" + newSelStart + + ", nse=" + newSelEnd + + ", cs=" + composingSpanStart + + ", ce=" + composingSpanEnd; + ResearchLogger.logUnstructured(ResearchLogger.UnsLogGroup.ON_UPDATE_SELECTION, s); + } + } if (DEBUG) { Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart + ", ose=" + oldSelEnd @@ -913,51 +785,56 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar + ", lse=" + mLastSelectionEnd + ", nss=" + newSelStart + ", nse=" + newSelEnd - + ", cs=" + candidatesStart - + ", ce=" + candidatesEnd); - } - - 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; + + ", cs=" + composingSpanStart + + ", ce=" + composingSpanEnd); + } + + // 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 @@ -999,7 +876,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar mOptionsDialog.dismiss(); mOptionsDialog = null; } - mVoiceProxy.hideVoiceWindow(mConfigurationChanging); super.hideWindow(); } @@ -1013,20 +889,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 ArrayList<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); } } @@ -1034,8 +920,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); @@ -1089,7 +977,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; } @@ -1097,11 +986,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar final int touchHeight = inputView.getHeight() + extraHeight // Extend touchable region below the keyboard. + EXTENDED_TOUCHABLE_REGION_HEIGHT; - if (DEBUG) { - Log.d(TAG, "Touchable region: y=" + touchY + " width=" + touchWidth - + " height=" + touchHeight); - } - setTouchableRegionCompat(outInsets, 0, touchY, touchWidth, touchHeight); + outInsets.touchableInsets = InputMethodService.Insets.TOUCHABLE_INSETS_REGION; + outInsets.touchableRegion.set(0, touchY, touchWidth, touchHeight); } outInsets.contentTopInsets = touchY; outInsets.visibleTopInsets = touchY; @@ -1109,8 +995,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 @@ -1148,9 +1036,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(), @@ -1165,17 +1055,35 @@ 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(); + } + } + + 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, - UserUnigramDictionary.FREQUENCY_FOR_TYPED); + addToUserHistoryDictionary(typedWord); } updateSuggestions(); } @@ -1190,60 +1098,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); @@ -1259,38 +1148,32 @@ 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 */)) { - showOptionsMenu(); - } else { - launchSettings(); - } + showSubtypeSelectorAndSettings(); } // 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; } @@ -1299,108 +1182,173 @@ 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 performEditorAction(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 InputMethodSubtype 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; + + if (ProductionFlag.IS_EXPERIMENTAL) { + if (ResearchLogger.sIsLogging) { + ResearchLogger.getInstance().logKeyEvent(primaryCode, x, y); + } + } + 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; - LatinImeLogger.logOnDelete(); + mShouldSwitchToLastSubtype = true; + LatinImeLogger.logOnDelete(x, y); 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_ACTION_ENTER: + performEditorAction(getActionId(switcher.getKeyboard())); break; - case Keyboard.CODE_TAB: - handleTab(); - // There are two cases for tab. Either we send a "next" event, that may change the - // focus but will never move the cursor. Or, we send a real tab keycode, which some - // applications may accept or ignore, and we don't know whether this will move the - // cursor or not. So actually, we don't really know. - // So to go with the safer option, we'd rather behave as if the user moved the - // cursor when they didn't than the opposite. We also expect that most applications - // will actually use tab only for focus movement. - // To sum it up: do not update mExpectingUpdateSelection here. + case Keyboard.CODE_ACTION_NEXT: + performEditorAction(EditorInfo.IME_ACTION_NEXT); + break; + case Keyboard.CODE_ACTION_PREVIOUS: + performEditorAction(EditorInfo.IME_ACTION_PREVIOUS); + 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); + final Keyboard keyboard = mKeyboardSwitcher.getKeyboard(); + if (keyboard != null && keyboard.hasProximityCharsCorrection(primaryCode)) { + handleCharacter(primaryCode, x, y, spaceState); + } else { + handleCharacter(primaryCode, NOT_A_TOUCH_COORDINATE, NOT_A_TOUCH_COORDINATE, + 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 public void onTextInput(CharSequence text) { - mVoiceProxy.commitVoiceInput(); 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 @@ -1409,249 +1357,274 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar mKeyboardSwitcher.onCancelInput(); } - private void handleBackspace(boolean justReplacedDoubleSpace) { - if (mVoiceProxy.logAndRevertVoiceInput()) return; - + private void handleBackspace(final int spaceState) { final InputConnection ic = getCurrentInputConnection(); if (ic == null) return; ic.beginBatchEdit(); + handleBackspaceWhileInBatchEdit(spaceState, ic); + ic.endBatchEdit(); + } - mVoiceProxy.handleBackspace(); + // "ic" may not be null. + private void handleBackspaceWhileInBatchEdit(final int spaceState, final InputConnection ic) { + // In many cases, we may have to put the keyboard in auto-shift state again. + mHandler.postUpdateShiftState(); - final boolean deleteChar = !mHasUncommittedTypedChars; - if (mHasUncommittedTypedChars) { - final int length = mComposingStringBuilder.length(); + 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) { - mVoiceProxy.handleCharacter(); - - if (mJustAddedMagicSpace && mSettingsValues.isMagicSpaceStripper(primaryCode)) { - removeTrailingSpace(); + private void handleCharacter(final int primaryCode, final int x, + final int y, final int spaceState) { + 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); - switcher.updateShiftState(); - if (LatinIME.PERF_DEBUG) measureCps(); - TextEntryState.typedCharacter((char) code, mSettingsValues.isWordSeparator(code), x, y); - } + sendKeyCodePoint(primaryCode); - private void handleSeparator(int primaryCode, int x, int y) { - mVoiceProxy.handleSeparator(); - mComposingStateManager.onFinishComposingText(); + 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); + } + // Returns true if we did an autocorrection, false otherwise. + private boolean handleSeparator(final int primaryCode, final int x, final int y, + final int spaceState) { // Should dismiss the "Touch again to save" message when handling separator if (mSuggestionsView != null && mSuggestionsView.dismissAddToDictionaryHint()) { mHandler.cancelUpdateBigramPredictions(); 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()); - mVoiceProxy.handleClose(); + commitTyped(getCurrentInputConnection(), LastComposedWord.NOT_A_SEPARATOR); requestHideSelf(0); LatinKeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); if (inputView != null) @@ -1659,7 +1632,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } public boolean isSuggestionsRequested() { - return mIsSettingsSuggestionStripOn + return mInputAttributes.mIsSettingsSuggestionStripOn && (mCorrectionMode > 0 || isShowingSuggestionsStrip()); } @@ -1677,11 +1650,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(); } @@ -1705,55 +1678,48 @@ 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); } } public void updateSuggestions() { // Check if we have a suggestion engine attached. - if ((mSuggest == null || !isSuggestionsRequested()) - && !mVoiceProxy.isVoiceInputHighlighted()) { + if ((mSuggest == null || !isSuggestionsRequested())) { + 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; @@ -1762,27 +1728,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 @@ -1790,145 +1740,128 @@ 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); - // Add the word to the user unigram dictionary if it's not a known word - addToUserUnigramAndBigramDictionaries(mBestWord, - UserUnigramDictionary.FREQUENCY_FOR_TYPED); - return true; + commitChosenWord(autoCorrection, LastComposedWord.COMMIT_TYPE_DECIDED_WORD, + separatorCodePoint); + // Add the word to the user history dictionary + addToUserHistoryDictionary(autoCorrection); + 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. + ic.commitCorrection(new CorrectionInfo(mLastSelectionEnd - typedWord.length(), + typedWord, autoCorrection)); + } } - return false; } @Override - public void pickSuggestionManually(int index, CharSequence suggestion) { - mComposingStateManager.onFinishComposingText(); - SuggestedWords suggestions = mSuggestionsView.getSuggestions(); - mVoiceProxy.flushAndLogAllTextModificationCounters(index, suggestion, - mSettingsValues.mWordSeparators); - - final boolean recorrecting = TextEntryState.isRecorrecting(); - final InputConnection ic = getCurrentInputConnection(); - if (ic != null) { - ic.beginBatchEdit(); + public void pickSuggestionManually(final int index, final CharSequence suggestion) { + final SuggestedWords suggestedWords = mSuggestionsView.getSuggestions(); + + 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); - // Add the word to the auto dictionary if it's not a known word - if (index == 0) { - addToUserUnigramAndBigramDictionaries(suggestion, - UserUnigramDictionary.FREQUENCY_FOR_PICKED); - } 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(); - } + commitChosenWord(suggestion, LastComposedWord.COMMIT_TYPE_MANUAL_PICK, + LastComposedWord.NOT_A_SEPARATOR); + // Add the word to the user history dictionary + addToUserHistoryDictionary(suggestion); + 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: @@ -1946,13 +1879,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. @@ -1960,29 +1888,23 @@ 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); if (mSettingsValues.mEnableSuggestionSpanInsertion) { final SuggestedWords suggestedWords = mSuggestionsView.getSuggestions(); ic.commitText(SuggestionSpanUtils.getTextWithSuggestionSpan( @@ -1991,11 +1913,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; @@ -2005,41 +1930,36 @@ 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()); } - private void addToUserUnigramAndBigramDictionaries(CharSequence suggestion, - int frequencyDelta) { - checkAddToDictionary(suggestion, frequencyDelta, false); - } - - private void addToOnlyBigramDictionary(CharSequence suggestion, int frequencyDelta) { - checkAddToDictionary(suggestion, frequencyDelta, true); - } - - /** - * Adds to the UserBigramDictionary and/or UserUnigramDictionary - * @param selectedANotTypedWord true if it should be added to bigram dictionary if possible - */ - private void checkAddToDictionary(CharSequence suggestion, int frequencyDelta, - boolean selectedANotTypedWord) { - if (suggestion == null || suggestion.length() < 1) return; + private void addToUserHistoryDictionary(final CharSequence suggestion) { + if (TextUtils.isEmpty(suggestion)) return; // Only auto-add to dictionary if auto-correct is ON. Otherwise we'll be // adding words in situations where the user or application really didn't @@ -2049,102 +1969,179 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar return; } - if (null != mSuggest && null != mUserUnigramDictionary) { - final boolean selectedATypedWordAndItsInUserUnigramDic = - !selectedANotTypedWord && mUserUnigramDictionary.isValidWord(suggestion); - final boolean isValidWord = AutoCorrection.isValidWord( - mSuggest.getUnigramDictionaries(), suggestion, true); - final boolean needsToAddToUserUnigramDictionary = - selectedATypedWordAndItsInUserUnigramDic || !isValidWord; - if (needsToAddToUserUnigramDictionary) { - mUserUnigramDictionary.addWord(suggestion.toString(), frequencyDelta); - } - } - - if (mUserBigramDictionary != null) { - // We don't want to register as bigrams words separated by a separator. - // For example "I will, and you too" : we don't want the pair ("will" "and") to be - // a bigram. + if (mUserHistoryDictionary != null) { final InputConnection ic = getCurrentInputConnection(); + final CharSequence prevWord; if (null != ic) { - final CharSequence prevWord = - EditingUtils.getPreviousWord(ic, mSettingsValues.mWordSeparators); - if (!TextUtils.isEmpty(prevWord)) { - mUserBigramDictionary.addBigrams(prevWord.toString(), suggestion.toString()); - } + prevWord = EditingUtils.getPreviousWord(ic, mSettingsValues.mWordSeparators); + } else { + prevWord = null; + } + final String secondWord; + if (mWordComposer.isAutoCapitalized() && !mWordComposer.isMostlyCaps()) { + secondWord = suggestion.toString().toLowerCase(mSubtypeSwitcher.getInputLocale()); + } else { + secondWord = suggestion.toString(); } + mUserHistoryDictionary.addToUserHistory(null == prevWord ? null : prevWord.toString(), + secondWord); } } 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; } @@ -2153,12 +2150,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(); } @@ -2166,11 +2157,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // Notify that language or mode have been changed and toggleLanguage will update KeyboardID // according to new language or mode. public void onRefreshKeyboard() { - if (!CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED) { - // Before Honeycomb, Voice IME is in LatinIME and it changes the current input view, - // so that we need to re-create the keyboard input view here. - setInputView(mKeyboardSwitcher.onCreateInputView()); - } // When the device locale is changed in SetupWizard etc., this method may get called via // onConfigurationChanged before SoftInputWindow is shown. if (mKeyboardSwitcher.getKeyboardView() != null) { @@ -2178,142 +2164,68 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar mKeyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), mSettingsValues); } initSuggest(); + updateCorrectionMode(); loadSettings(); - } - - @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(); + // 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 { - switcher.onOtherKeyPressed(); + mHandler.postUpdateBigramPredictions(); } } - @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(); - } - } - - - // 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)) { - mSubtypeSwitcher.onNetworkStateChanged(intent); - } - } - }; - - // update keypress sound volume - private void updateSoundEffectVolume() { - mFxVolume = Utils.getCurrentKeypressSoundVolume(mPrefs, mResources); + public void hapticAndAudioFeedback(final int primaryCode) { + mFeedbackManager.hapticAndAudioFeedback(primaryCode, mKeyboardSwitcher.getKeyboardView()); } - // 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); + @Override + public void onPressKey(int primaryCode) { + mKeyboardSwitcher.onPressKey(primaryCode); } - private void updateKeypressVibrationDuration() { - mKeypressVibrationDuration = Utils.getCurrentVibrationDuration(mPrefs, mResources); - } + @Override + public void onReleaseKey(int primaryCode, boolean withSliding) { + mKeyboardSwitcher.onReleaseKey(primaryCode, withSliding); - 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; + // If accessibility is on, ensure the user receives keyboard state updates. + if (AccessibilityUtils.getInstance().isTouchExplorationEnabled()) { 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; + case Keyboard.CODE_SHIFT: + AccessibleKeyboardViewProxy.getInstance().notifyShiftState(); break; - default: - sound = AudioManager.FX_KEYPRESS_STANDARD; + case Keyboard.CODE_SWITCH_ALPHA_SYMBOL: + AccessibleKeyboardViewProxy.getInstance().notifySymbolsState(); break; } - mAudioManager.playSoundEffect(sound, mFxVolume); } } - 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); + // 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(ConnectivityManager.CONNECTIVITY_ACTION)) { + mSubtypeSwitcher.onNetworkStateChanged(intent); + } else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) { + mFeedbackManager.onRingerModeChanged(); } - } else if (mVibrator != null) { - mVibrator.vibrate(mKeypressVibrationDuration); } - } - - public WordComposer getCurrentWord() { - return mWordComposer; - } - - boolean isSoundOn() { - return mSettingsValues.mSoundOn && !mSilentModeOn; - } + }; 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; @@ -2352,7 +2264,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); @@ -2369,30 +2282,23 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar showOptionDialogInternal(builder.create()); } - private void showOptionsMenu() { - final CharSequence title = getString(R.string.english_ime_input_options); - final CharSequence[] items = new CharSequence[] { - getString(R.string.selectInputMethod), - getString(R.string.english_ime_settings), - }; - final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface di, int position) { - di.dismiss(); - switch (position) { - case 0: - mImm.showInputMethodPicker(); - break; - case 1: - launchSettings(); - break; - } - } - }; - final AlertDialog.Builder builder = new AlertDialog.Builder(this) - .setItems(items, listener) - .setTitle(title); - showOptionDialogInternal(builder.create()); + private void showOptionDialogInternal(AlertDialog dialog) { + final IBinder windowToken = KeyboardSwitcher.getInstance().getKeyboardView() + .getWindowToken(); + if (windowToken == null) return; + + dialog.setCancelable(true); + dialog.setCanceledOnTouchOutside(true); + + final Window window = dialog.getWindow(); + final WindowManager.LayoutParams lp = window.getAttributes(); + lp.token = windowToken; + lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; + window.setAttributes(lp); + window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); + + mOptionsDialog = dialog; + dialog.show(); } @Override @@ -2401,35 +2307,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..dc0868e7c 100644 --- a/java/src/com/android/inputmethod/latin/LatinImeLogger.java +++ b/java/src/com/android/inputmethod/latin/LatinImeLogger.java @@ -16,24 +16,22 @@ 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 java.util.List; +import com.android.inputmethod.keyboard.Keyboard; public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChangeListener { 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 +41,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) { } @@ -52,7 +50,7 @@ public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChang public static void logOnAutoCorrectionCancelled() { } - public static void logOnDelete() { + public static void logOnDelete(int x, int y) { } public static void logOnInputChar() { @@ -67,10 +65,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) { diff --git a/java/src/com/android/inputmethod/latin/LocaleUtils.java b/java/src/com/android/inputmethod/latin/LocaleUtils.java index e05b47cb7..f19c59a6a 100644 --- a/java/src/com/android/inputmethod/latin/LocaleUtils.java +++ b/java/src/com/android/inputmethod/latin/LocaleUtils.java @@ -161,19 +161,36 @@ public class LocaleUtils { return LOCALE_MATCH <= level; } - /** - * Sets the system locale for this process. - * - * @param res the resources to use. Pass current resources. - * @param newLocale the locale to change to. - * @return the old locale. - */ - public static Locale setSystemLocale(final Resources res, final Locale newLocale) { - final Configuration conf = res.getConfiguration(); - final Locale saveLocale = conf.locale; - conf.locale = newLocale; - res.updateConfiguration(conf, res.getDisplayMetrics()); - return saveLocale; + static final Object sLockForRunInLocale = new Object(); + + public abstract static class RunInLocale<T> { + protected abstract T job(Resources res); + + /** + * Execute {@link #job(Resources)} method in specified system locale exclusively. + * + * @param res the resources to use. Pass current resources. + * @param newLocale the locale to change to + * @return the value returned from {@link #job(Resources)}. + */ + public T runInLocale(final Resources res, final Locale newLocale) { + synchronized (sLockForRunInLocale) { + final Configuration conf = res.getConfiguration(); + final Locale oldLocale = conf.locale; + try { + if (newLocale != null && !newLocale.equals(oldLocale)) { + conf.locale = newLocale; + res.updateConfiguration(conf, res.getDisplayMetrics()); + } + return job(res); + } finally { + if (newLocale != null && !newLocale.equals(oldLocale)) { + conf.locale = oldLocale; + res.updateConfiguration(conf, res.getDisplayMetrics()); + } + } + } + } } private static final HashMap<String, Locale> sLocaleCache = new HashMap<String, Locale>(); diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java new file mode 100644 index 000000000..c5fb61f78 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java @@ -0,0 +1,318 @@ +/* + * 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.SharedPreferences; +import android.inputmethodservice.InputMethodService; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Process; +import android.os.SystemClock; +import android.text.TextUtils; +import android.util.Log; +import android.view.MotionEvent; + +import com.android.inputmethod.keyboard.Keyboard; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.PrintWriter; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * Logs the use of the LatinIME keyboard. + * + * This class logs operations on the IME keyboard, including what the user has typed. + * Data is stored locally in a file in app-specific storage. + * + * This functionality is off by default. See {@link ProductionFlag.IS_EXPERIMENTAL}. + */ +public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChangeListener { + private static final String TAG = ResearchLogger.class.getSimpleName(); + private static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode"; + + private static final ResearchLogger sInstance = new ResearchLogger(new LogFileManager()); + public static boolean sIsLogging = false; + /* package */ final Handler mLoggingHandler; + private InputMethodService mIms; + private final Date mDate; + private final SimpleDateFormat mDateFormat; + + /** + * Isolates management of files. This variable should never be null, but can be changed + * to support testing. + */ + private LogFileManager mLogFileManager; + + /** + * Manages the file(s) that stores the logs. + * + * Handles creation, deletion, and provides Readers, Writers, and InputStreams to access + * the logs. + */ + public static class LogFileManager { + private static final String DEFAULT_FILENAME = "log.txt"; + private static final String DEFAULT_LOG_DIRECTORY = "researchLogger"; + + private static final long LOGFILE_PURGE_INTERVAL = 1000 * 60 * 60 * 24; + + private InputMethodService mIms; + private File mFile; + private PrintWriter mPrintWriter; + + /* package */ LogFileManager() { + } + + public void init(InputMethodService ims) { + mIms = ims; + } + + public synchronized void createLogFile() { + try { + createLogFile(DEFAULT_LOG_DIRECTORY, DEFAULT_FILENAME); + } catch (FileNotFoundException e) { + Log.w(TAG, e); + } + } + + public synchronized void createLogFile(String dir, String filename) + throws FileNotFoundException { + if (mIms == null) { + Log.w(TAG, "InputMethodService is not configured. Logging is off."); + return; + } + File filesDir = mIms.getFilesDir(); + if (filesDir == null || !filesDir.exists()) { + Log.w(TAG, "Storage directory does not exist. Logging is off."); + return; + } + File directory = new File(filesDir, dir); + if (!directory.exists()) { + boolean wasCreated = directory.mkdirs(); + if (!wasCreated) { + Log.w(TAG, "Log directory cannot be created. Logging is off."); + return; + } + } + + close(); + mFile = new File(directory, filename); + mFile.setReadable(false, false); + boolean append = true; + if (mFile.exists() && mFile.lastModified() + LOGFILE_PURGE_INTERVAL < + System.currentTimeMillis()) { + append = false; + } + mPrintWriter = new PrintWriter(new FileOutputStream(mFile, append), true); + } + + public synchronized boolean append(String s) { + if (mPrintWriter == null) { + Log.w(TAG, "PrintWriter is null"); + return false; + } else { + mPrintWriter.print(s); + return !mPrintWriter.checkError(); + } + } + + public synchronized void reset() { + if (mPrintWriter != null) { + mPrintWriter.close(); + mPrintWriter = null; + } + if (mFile != null && mFile.exists()) { + mFile.delete(); + mFile = null; + } + } + + public synchronized void close() { + if (mPrintWriter != null) { + mPrintWriter.close(); + mPrintWriter = null; + mFile = null; + } + } + } + + private ResearchLogger(LogFileManager logFileManager) { + mDate = new Date(); + mDateFormat = new SimpleDateFormat("yyyyMMdd-HHmmss.SSSZ"); + + HandlerThread handlerThread = new HandlerThread("ResearchLogger logging task", + Process.THREAD_PRIORITY_BACKGROUND); + handlerThread.start(); + mLoggingHandler = new Handler(handlerThread.getLooper()); + mLogFileManager = logFileManager; + } + + public static ResearchLogger getInstance() { + return sInstance; + } + + public static void init(InputMethodService ims, SharedPreferences prefs) { + sInstance.initInternal(ims, prefs); + } + + public void initInternal(InputMethodService ims, SharedPreferences prefs) { + mIms = ims; + if (mLogFileManager != null) { + mLogFileManager.init(ims); + mLogFileManager.createLogFile(); + } + if (prefs != null) { + sIsLogging = prefs.getBoolean(PREF_USABILITY_STUDY_MODE, false); + prefs.registerOnSharedPreferenceChangeListener(this); + } + } + + /** + * Change to a different logFileManager. + * + * @throws IllegalArgumentException if logFileManager is null + */ + void setLogFileManager(LogFileManager manager) { + if (manager == null) { + throw new IllegalArgumentException("warning: trying to set null logFileManager"); + } else { + mLogFileManager = manager; + } + } + + /** + * Represents a category of logging events that share the same subfield structure. + */ + private static enum LogGroup { + MOTION_EVENT("m"), + KEY("k"), + CORRECTION("c"), + STATE_CHANGE("s"); + + private final String mLogString; + + private LogGroup(String logString) { + mLogString = logString; + } + } + + public void logMotionEvent(final int action, final long eventTime, final int id, + final int x, final int y, final float size, final float pressure) { + final String eventTag; + switch (action) { + case MotionEvent.ACTION_CANCEL: eventTag = "[Cancel]"; break; + 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: eventTag = "[Move]"; break; + case MotionEvent.ACTION_OUTSIDE: eventTag = "[Outside]"; break; + default: eventTag = "[Action" + action + "]"; break; + } + if (!TextUtils.isEmpty(eventTag)) { + StringBuilder sb = new StringBuilder(); + sb.append(eventTag); + sb.append('\t'); sb.append(eventTime); + sb.append('\t'); sb.append(id); + sb.append('\t'); sb.append(x); + sb.append('\t'); sb.append(y); + sb.append('\t'); sb.append(size); + sb.append('\t'); sb.append(pressure); + write(LogGroup.MOTION_EVENT, sb.toString()); + } + } + + public void logKeyEvent(int code, int x, int y) { + final StringBuilder sb = new StringBuilder(); + sb.append(Keyboard.printableCode(code)); + sb.append('\t'); sb.append(x); + sb.append('\t'); sb.append(y); + write(LogGroup.KEY, sb.toString()); + } + + public void logCorrection(String subgroup, String before, String after, int position) { + final StringBuilder sb = new StringBuilder(); + sb.append(subgroup); + sb.append('\t'); sb.append(before); + sb.append('\t'); sb.append(after); + sb.append('\t'); sb.append(position); + write(LogGroup.CORRECTION, sb.toString()); + } + + public void logStateChange(String subgroup, String details) { + write(LogGroup.STATE_CHANGE, subgroup + "\t" + details); + } + + public static enum UnsLogGroup { + // TODO: expand to include one flag per log point + // TODO: support selective enabling of flags + ON_UPDATE_SELECTION; + + public boolean isEnabled = true; + } + + public static void logUnstructured(UnsLogGroup logGroup, String details) { + } + + private void write(final LogGroup logGroup, final String log) { + // TODO: rewrite in native for better performance + mLoggingHandler.post(new Runnable() { + @Override + public void run() { + final long currentTime = System.currentTimeMillis(); + final long upTime = SystemClock.uptimeMillis(); + final StringBuilder builder = new StringBuilder(); + builder.append(currentTime); + builder.append('\t'); builder.append(upTime); + builder.append('\t'); builder.append(logGroup.mLogString); + builder.append('\t'); builder.append(log); + if (LatinImeLogger.sDBG) { + Log.d(TAG, "Write: " + '[' + logGroup.mLogString + ']' + log); + } + if (mLogFileManager.append(builder.toString())) { + // success + } else { + if (LatinImeLogger.sDBG) { + Log.w(TAG, "Unable to write to log."); + } + } + } + }); + } + + public void clearAll() { + mLoggingHandler.post(new Runnable() { + @Override + public void run() { + if (LatinImeLogger.sDBG) { + Log.d(TAG, "Delete log file."); + } + mLogFileManager.reset(); + } + }); + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { + if (key == null || prefs == null) { + return; + } + sIsLogging = prefs.getBoolean(PREF_USABILITY_STUDY_MODE, false); + } +} diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java index 773efe709..7b98a7188 100644 --- a/java/src/com/android/inputmethod/latin/Settings.java +++ b/java/src/com/android/inputmethod/latin/Settings.java @@ -18,7 +18,6 @@ package com.android.inputmethod.latin; import android.app.Activity; import android.app.AlertDialog; -import android.app.Dialog; import android.app.Fragment; import android.app.backup.BackupManager; import android.content.Context; @@ -34,288 +33,54 @@ import android.preference.Preference; import android.preference.Preference.OnPreferenceClickListener; import android.preference.PreferenceGroup; import android.preference.PreferenceScreen; -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.inputmethod.latin.define.ProductionFlag; import com.android.inputmethodcommon.InputMethodSettingsActivity; -import java.util.Arrays; -import java.util.Locale; - public class Settings extends InputMethodSettingsActivity - implements SharedPreferences.OnSharedPreferenceChangeListener, - DialogInterface.OnDismissListener, OnPreferenceClickListener { - private static final String TAG = Settings.class.getSimpleName(); - + implements SharedPreferences.OnSharedPreferenceChangeListener { 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_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 boolean isVoiceKeyOnMain() { - return mVoiceKeyOnMain; - } - } + 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"; - private PreferenceScreen mInputLanguageSelection; private PreferenceScreen mKeypressVibrationDurationSettingsPref; private PreferenceScreen mKeypressSoundVolumeSettingsPref; private ListPreference mVoicePreference; - private CheckBoxPreference mShowSettingsKeyPreference; private ListPreference mShowCorrectionSuggestionsPreference; private ListPreference mAutoCorrectionThresholdPreference; private ListPreference mKeyPreviewPopupDismissDelay; @@ -324,15 +89,10 @@ public class Settings extends InputMethodSettingsActivity // Prediction: use bigrams to predict the next word when there is no input for it yet private CheckBoxPreference mBigramPrediction; private Preference mDebugSettingsPreference; - private boolean mVoiceOn; - private AlertDialog mDialog; private TextView mKeypressVibrationDurationSettingsTextView; private TextView mKeypressSoundVolumeSettingsTextView; - private boolean mOkClicked = false; - private String mVoiceModeOff; - private void ensureConsistencyOfAutoCorrectionSettings() { final String autoCorrectionOff = getResources().getString( R.string.auto_correction_threshold_mode_index_off); @@ -363,22 +123,15 @@ public class Settings extends InputMethodSettingsActivity final Context context = getActivityInternal(); addPreferencesFromResource(R.xml.prefs); - mInputLanguageSelection = (PreferenceScreen) findPreference(PREF_SUBTYPES); - 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) - .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 +144,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); @@ -407,18 +156,14 @@ public class Settings extends InputMethodSettingsActivity generalSettings.removePreference(mVoicePreference); } - if (!VibratorCompatWrapper.getInstance(context).hasVibrator()) { + if (!VibratorUtils.getInstance(context).hasVibrator()) { generalSettings.removePreference(findPreference(PREF_VIBRATE_ON)); } - if (InputMethodServiceCompatWrapper.CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED) { - generalSettings.removePreference(findPreference(PREF_SUBTYPES)); - } - 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 +175,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 +187,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 +206,25 @@ 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 showUsabilityStudyModeOption = + res.getBoolean(R.bool.config_enable_usability_study_mode_option) + || ProductionFlag.IS_EXPERIMENTAL || ENABLE_EXPERIMENTAL_SETTINGS; + final Preference usabilityStudyPref = findPreference(PREF_USABILITY_STUDY_MODE); + if (!showUsabilityStudyModeOption) { + if (usabilityStudyPref != null) { + miscSettings.removePreference(usabilityStudyPref); + } + } + if (ProductionFlag.IS_EXPERIMENTAL) { + 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() { @@ -499,9 +258,7 @@ public class Settings extends InputMethodSettingsActivity public void onResume() { super.onResume(); final boolean isShortcutImeEnabled = SubtypeSwitcher.getInstance().isShortcutImeEnabled(); - if (isShortcutImeEnabled - || (VoiceProxy.VOICE_INSTALLED - && VoiceProxy.isRecognitionAvailable(getActivityInternal()))) { + if (isShortcutImeEnabled) { updateVoiceModeSummary(); } else { getPreferenceScreen().removePreference(mVoicePreference); @@ -520,40 +277,26 @@ public class Settings extends InputMethodSettingsActivity @Override 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) - .equals(mVoiceModeOff)) { - showVoiceConfirmation(); - } - } else if (key.equals(PREF_KEY_PREVIEW_POPUP_ON)) { + 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) - .equals(mVoiceModeOff)); updateVoiceModeSummary(); updateShowCorrectionSuggestionsSummary(); updateKeyPreviewPopupDelaySummary(); refreshEnablingsOfKeypressSoundAndVibrationSettings(prefs, getResources()); } - @Override - public boolean onPreferenceClick(Preference pref) { - if (pref == mInputLanguageSelection) { - startActivity(CompatUtils.getInputLanguageSelectionIntent( - Utils.getInputMethodId( - InputMethodManagerCompatWrapper.getInstance(), - getActivityInternal().getApplicationInfo().packageName), 0)); - return true; - } - return false; - } - private void updateShowCorrectionSuggestionsSummary() { mShowCorrectionSuggestionsPreference.setSummary( getResources().getStringArray(R.array.prefs_suggestion_visibilities) @@ -566,84 +309,16 @@ public class Settings extends InputMethodSettingsActivity lp.setSummary(lp.getEntries()[lp.findIndexOfValue(lp.getValue())]); } - private void showVoiceConfirmation() { - mOkClicked = false; - getActivityInternal().showDialog(VOICE_INPUT_CONFIRM_DIALOG); - // Make URL in the dialog message clickable - if (mDialog != null) { - TextView textView = (TextView) mDialog.findViewById(android.R.id.message); - if (textView != null) { - textView.setMovementMethod(LinkMovementMethod.getInstance()); - } - } - } - private void updateVoiceModeSummary() { mVoicePreference.setSummary( getResources().getStringArray(R.array.voice_input_modes_summary) [mVoicePreference.findIndexOfValue(mVoicePreference.getValue())]); } - @Override - protected Dialog onCreateDialog(int id) { - switch (id) { - case VOICE_INPUT_CONFIRM_DIALOG: - DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int whichButton) { - if (whichButton == DialogInterface.BUTTON_NEGATIVE) { - mVoicePreference.setValue(mVoiceModeOff); - } else if (whichButton == DialogInterface.BUTTON_POSITIVE) { - mOkClicked = true; - } - } - }; - AlertDialog.Builder builder = new AlertDialog.Builder(getActivityInternal()) - .setTitle(R.string.voice_warning_title) - .setPositiveButton(android.R.string.ok, listener) - .setNegativeButton(android.R.string.cancel, listener); - - // Get the current list of supported locales and check the current locale against - // that list, to decide whether to put a warning that voice input will not work in - // the current language as part of the pop-up confirmation dialog. - boolean localeSupported = SubtypeSwitcher.isVoiceSupported( - this, Locale.getDefault().toString()); - - final CharSequence message; - if (localeSupported) { - message = TextUtils.concat( - getText(R.string.voice_warning_may_not_understand), "\n\n", - getText(R.string.voice_hint_dialog_message)); - } else { - message = TextUtils.concat( - getText(R.string.voice_warning_locale_not_supported), "\n\n", - getText(R.string.voice_warning_may_not_understand), "\n\n", - getText(R.string.voice_hint_dialog_message)); - } - builder.setMessage(message); - AlertDialog dialog = builder.create(); - mDialog = dialog; - dialog.setOnDismissListener(this); - return dialog; - default: - Log.e(TAG, "unknown dialog " + id); - return null; - } - } - - @Override - public void onDismiss(DialogInterface dialog) { - if (!mOkClicked) { - // This assumes that onPreferenceClick gets called first, and this if the user - // agreed after the warning, we set the mOkClicked value to true. - mVoicePreference.setValue(mVoiceModeOff); - } - } - private void refreshEnablingsOfKeypressSoundAndVibrationSettings( SharedPreferences sp, Resources res) { if (mKeypressVibrationDurationSettingsPref != null) { - final boolean hasVibrator = VibratorCompatWrapper.getInstance(this).hasVibrator(); + final boolean hasVibrator = VibratorUtils.getInstance(this).hasVibrator(); final boolean vibrateOn = hasVibrator && sp.getBoolean(Settings.PREF_VIBRATE_ON, res.getBoolean(R.bool.config_default_vibration_enabled)); mKeypressVibrationDurationSettingsPref.setEnabled(vibrateOn); @@ -660,7 +335,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 +351,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 +363,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); @@ -706,7 +381,7 @@ public class Settings extends InputMethodSettingsActivity @Override public void onStopTrackingTouch(SeekBar arg0) { final int tempMs = arg0.getProgress(); - VibratorCompatWrapper.getInstance(context).vibrate(tempMs); + VibratorUtils.getInstance(context).vibrate(tempMs); } }); sb.setProgress(currentMs); @@ -717,8 +392,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 +422,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 +449,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..103678403 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/SettingsValues.java @@ -0,0 +1,338 @@ +/* + * 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.util.Log; +import android.view.inputmethod.EditorInfo; + +import com.android.inputmethod.keyboard.internal.KeySpecParser; +import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; + +import java.util.ArrayList; +import java.util.Arrays; + +/** + * When you call the constructor of this class, you may want to change the current system locale by + * using {@link LocaleUtils.RunInLocale}. + */ +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 Resources res = context.getResources(); + + // 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); + } + + // 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), SuggestedWordInfo.MAX_SCORE)); + } + } + 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 = VibratorUtils.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 + && !InputTypeUtils.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; + } + + return Float.parseFloat( + Utils.getDeviceOverrideValue(res, R.array.keypress_volumes, "-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; + } + + return Integer.parseInt( + Utils.getDeviceOverrideValue(res, R.array.keypress_vibration_durations, "-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/SubtypeLocale.java b/java/src/com/android/inputmethod/latin/SubtypeLocale.java index 917521c40..66c13bd2e 100644 --- a/java/src/com/android/inputmethod/latin/SubtypeLocale.java +++ b/java/src/com/android/inputmethod/latin/SubtypeLocale.java @@ -36,10 +36,16 @@ public class SubtypeLocale { } public static String getFullDisplayName(Locale locale) { - String localeCode = locale.toString(); + final String localeCode = locale.toString(); for (int index = 0; index < sExceptionKeys.length; index++) { - if (sExceptionKeys[index].equals(localeCode)) - return sExceptionValues[index]; + if (sExceptionKeys[index].equals(localeCode)) { + final String value = sExceptionValues[index]; + if (value.indexOf("%s") >= 0) { + final String languageName = locale.getDisplayLanguage(locale); + return String.format(value, languageName); + } + return value; + } } return locale.getDisplayName(locale); } diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java index 8a4862094..e35364420 100644 --- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java +++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java @@ -29,16 +29,13 @@ import android.os.AsyncTask; import android.os.IBinder; import android.text.TextUtils; import android.util.Log; +import android.view.inputmethod.InputMethodInfo; +import android.view.inputmethod.InputMethodSubtype; -import com.android.inputmethod.compat.InputMethodInfoCompatWrapper; 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; import java.util.List; import java.util.Locale; import java.util.Map; @@ -47,37 +44,35 @@ public class SubtypeSwitcher { private static boolean DBG = LatinImeLogger.sDBG; private static final String TAG = SubtypeSwitcher.class.getSimpleName(); - private static final char LOCALE_SEPARATER = '_'; - private static final String KEYBOARD_MODE = "keyboard"; - private static final String VOICE_MODE = "voice"; + public static final String KEYBOARD_MODE = "keyboard"; + private static final char LOCALE_SEPARATOR = '_'; private static final String SUBTYPE_EXTRAVALUE_REQUIRE_NETWORK_CONNECTIVITY = "requireNetworkConnectivity"; private final TextUtils.SimpleStringSplitter mLocaleSplitter = - new TextUtils.SimpleStringSplitter(LOCALE_SEPARATER); + new TextUtils.SimpleStringSplitter(LOCALE_SEPARATOR); private static final SubtypeSwitcher sInstance = new SubtypeSwitcher(); private /* final */ LatinIME mService; private /* final */ InputMethodManagerCompatWrapper mImm; private /* final */ Resources mResources; private /* final */ ConnectivityManager mConnectivityManager; - private final ArrayList<InputMethodSubtypeCompatWrapper> - mEnabledKeyboardSubtypesOfCurrentInputMethod = - new ArrayList<InputMethodSubtypeCompatWrapper>(); + private final ArrayList<InputMethodSubtype> mEnabledKeyboardSubtypesOfCurrentInputMethod = + new ArrayList<InputMethodSubtype>(); private final ArrayList<String> mEnabledLanguagesOfCurrentInputMethod = new ArrayList<String>(); /*-----------------------------------------------------------*/ // Variants which should be changed only by reload functions. private boolean mNeedsToDisplayLanguage; private boolean mIsSystemLanguageSameAsInputLanguage; - private InputMethodInfoCompatWrapper mShortcutInputMethodInfo; - private InputMethodSubtypeCompatWrapper mShortcutSubtype; - private List<InputMethodSubtypeCompatWrapper> mAllEnabledSubtypesOfCurrentInputMethod; - private InputMethodSubtypeCompatWrapper mCurrentSubtype; + private InputMethodInfo mShortcutInputMethodInfo; + private InputMethodSubtype mShortcutSubtype; + private List<InputMethodSubtype> mAllEnabledSubtypesOfCurrentInputMethod; + // Note: This variable is always non-null after {@link #initialize(LatinIME)}. + private InputMethodSubtype mCurrentSubtype; private Locale mSystemLocale; private Locale mInputLocale; private String mInputLocaleStr; - private VoiceProxy.VoiceInputWrapper mVoiceInputWrapper; /*-----------------------------------------------------------*/ private boolean mIsNetworkConnected; @@ -107,9 +102,8 @@ public class SubtypeSwitcher { mSystemLocale = null; mInputLocale = null; mInputLocaleStr = null; - mCurrentSubtype = null; + mCurrentSubtype = mImm.getCurrentInputMethodSubtype(); mAllEnabledSubtypesOfCurrentInputMethod = null; - mVoiceInputWrapper = null; final NetworkInfo info = mConnectivityManager.getActiveNetworkInfo(); mIsNetworkConnected = (info != null && info.isConnected()); @@ -138,7 +132,7 @@ public class SubtypeSwitcher { null, true); mEnabledLanguagesOfCurrentInputMethod.clear(); mEnabledKeyboardSubtypesOfCurrentInputMethod.clear(); - for (InputMethodSubtypeCompatWrapper ims : mAllEnabledSubtypesOfCurrentInputMethod) { + for (InputMethodSubtype ims : mAllEnabledSubtypesOfCurrentInputMethod) { final String locale = getSubtypeLocale(ims); final String mode = ims.getMode(); mLocaleSplitter.setString(locale); @@ -172,12 +166,12 @@ public class SubtypeSwitcher { + ", " + mShortcutSubtype.getMode()))); } // TODO: Update an icon for shortcut IME - final Map<InputMethodInfoCompatWrapper, List<InputMethodSubtypeCompatWrapper>> shortcuts = + final Map<InputMethodInfo, List<InputMethodSubtype>> shortcuts = mImm.getShortcutInputMethodsAndSubtypes(); mShortcutInputMethodInfo = null; mShortcutSubtype = null; - for (InputMethodInfoCompatWrapper imi : shortcuts.keySet()) { - List<InputMethodSubtypeCompatWrapper> subtypes = shortcuts.get(imi); + for (InputMethodInfo imi : shortcuts.keySet()) { + List<InputMethodSubtype> subtypes = shortcuts.get(imi); // TODO: Returns the first found IMI for now. Should handle all shortcuts as // appropriate. mShortcutInputMethodInfo = imi; @@ -195,27 +189,17 @@ public class SubtypeSwitcher { } } - private static String getSubtypeLocale(InputMethodSubtypeCompatWrapper subtype) { + private static String getSubtypeLocale(InputMethodSubtype subtype) { final String keyboardLocale = subtype.getExtraValueOf( LatinIME.SUBTYPE_EXTRA_VALUE_KEYBOARD_LOCALE); return keyboardLocale != null ? keyboardLocale : subtype.getLocale(); } // Update the current subtype. LatinIME.onCurrentInputMethodSubtypeChanged calls this function. - public void updateSubtype(InputMethodSubtypeCompatWrapper newSubtype) { - final String newLocale; - final String newMode; + public void updateSubtype(InputMethodSubtype newSubtype) { + final String newLocale = getSubtypeLocale(newSubtype); + final String newMode = newSubtype.getMode(); final String oldMode = getCurrentSubtypeMode(); - if (newSubtype == null) { - // Normally, newSubtype shouldn't be null. But just in case newSubtype was null, - // fallback to the default locale. - Log.w(TAG, "Couldn't get the current subtype."); - newLocale = "en_US"; - newMode = KEYBOARD_MODE; - } else { - newLocale = getSubtypeLocale(newSubtype); - newMode = newSubtype.getMode(); - } if (DBG) { Log.w(TAG, "Update subtype to:" + newLocale + "," + newMode + ", from: " + mInputLocaleStr + ", " + oldMode); @@ -235,34 +219,12 @@ public class SubtypeSwitcher { } mCurrentSubtype = newSubtype; - // If the old mode is voice input, we need to reset or cancel its status. - // We cancel its status when we change mode, while we reset otherwise. if (isKeyboardMode()) { - if (modeChanged) { - if (VOICE_MODE.equals(oldMode) && mVoiceInputWrapper != null) { - mVoiceInputWrapper.cancel(); - } - } if (modeChanged || languageChanged) { updateShortcutIME(); mService.onRefreshKeyboard(); } - } else if (isVoiceMode() && mVoiceInputWrapper != null) { - if (VOICE_MODE.equals(oldMode)) { - mVoiceInputWrapper.reset(); - } - // If needsToShowWarningDialog is true, voice input need to show warning before - // show recognition view. - if (languageChanged || modeChanged - || VoiceProxy.getInstance().needsToShowWarningDialog()) { - triggerVoiceIME(); - } } else { - if (VOICE_MODE.equals(oldMode) && mVoiceInputWrapper != null) { - // We need to reset the voice input to release the resources and to reset its status - // as it is not the current input mode. - mVoiceInputWrapper.reset(); - } final String packageName = mService.getPackageName(); int version = -1; try { @@ -271,7 +233,7 @@ public class SubtypeSwitcher { } catch (NameNotFoundException e) { } Log.w(TAG, "Unknown subtype mode: " + newMode + "," + version + ", " + packageName - + ", " + mVoiceInputWrapper + ". IME is already changed to other IME."); + + ". IME is already changed to other IME."); if (newSubtype != null) { Log.w(TAG, "Subtype mode:" + newSubtype.getMode()); Log.w(TAG, "Subtype locale:" + newSubtype.getLocale()); @@ -312,12 +274,10 @@ public class SubtypeSwitcher { } final String imiId = mShortcutInputMethodInfo.getId(); - final InputMethodSubtypeCompatWrapper subtype = mShortcutSubtype; - switchToTargetIME(imiId, subtype); + switchToTargetIME(imiId, mShortcutSubtype); } - private void switchToTargetIME( - final String imiId, final InputMethodSubtypeCompatWrapper subtype) { + private void switchToTargetIME(final String imiId, final InputMethodSubtype subtype) { final IBinder token = mService.getWindow().getWindow().getAttributes().token; if (token == null) { return; @@ -328,17 +288,6 @@ public class SubtypeSwitcher { mImm.setInputMethodAndSubtype(token, imiId, subtype); return null; } - - @Override - protected void onPostExecute(Void result) { - // Calls in this method need to be done in the same thread as the thread which - // called switchToShortcutIME(). - - // Notify an event that the current subtype was changed. This event will be - // handled if "onCurrentInputMethodSubtypeChanged" can't be implemented - // when the API level is 10 or previous. - mService.notifyOnCurrentInputMethodSubtypeChanged(subtype); - } }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } @@ -346,8 +295,7 @@ public class SubtypeSwitcher { return getSubtypeIcon(mShortcutInputMethodInfo, mShortcutSubtype); } - private Drawable getSubtypeIcon( - InputMethodInfoCompatWrapper imi, InputMethodSubtypeCompatWrapper subtype) { + private Drawable getSubtypeIcon(InputMethodInfo imi, InputMethodSubtype subtype) { final PackageManager pm = mService.getPackageManager(); if (imi != null) { final String imiPackageName = imi.getPackageName(); @@ -388,15 +336,9 @@ public class SubtypeSwitcher { if (mShortcutSubtype == null) { return true; } - // For compatibility, if the shortcut subtype is dummy, we assume the shortcut IME - // (built-in voice dummy subtype) is available. - if (!mShortcutSubtype.hasOriginalObject()) { - return true; - } final boolean allowsImplicitlySelectedSubtypes = true; - for (final InputMethodSubtypeCompatWrapper enabledSubtype : - mImm.getEnabledInputMethodSubtypeList( - mShortcutInputMethodInfo, allowsImplicitlySelectedSubtypes)) { + for (final InputMethodSubtype enabledSubtype : mImm.getEnabledInputMethodSubtypeList( + mShortcutInputMethodInfo, allowsImplicitlySelectedSubtypes)) { if (enabledSubtype.equals(mShortcutSubtype)) { return true; } @@ -421,11 +363,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(); } ////////////////////////////////// @@ -482,42 +420,8 @@ public class SubtypeSwitcher { return KEYBOARD_MODE.equals(getCurrentSubtypeMode()); } - - /////////////////////////// - // Voice Input functions // - /////////////////////////// - - public boolean setVoiceInputWrapper(VoiceProxy.VoiceInputWrapper vi) { - if (mVoiceInputWrapper == null && vi != null) { - mVoiceInputWrapper = vi; - if (isVoiceMode()) { - if (DBG) { - Log.d(TAG, "Set and call voice input.: " + getInputLocaleStr()); - } - triggerVoiceIME(); - return true; - } - } - return false; - } - - public boolean isVoiceMode() { - return null == mCurrentSubtype ? false : VOICE_MODE.equals(getCurrentSubtypeMode()); - } - - public boolean isDummyVoiceMode() { - return mCurrentSubtype != null && mCurrentSubtype.getOriginalObject() == null - && VOICE_MODE.equals(getCurrentSubtypeMode()); - } - - private void triggerVoiceIME() { - if (!mService.isInputViewShown()) return; - VoiceProxy.getInstance().startListening(false, - KeyboardSwitcher.getInstance().getKeyboardView().getWindowToken()); - } - public String getInputLanguageName() { - return Utils.getDisplayLanguage(getInputLocale()); + return StringUtils.getDisplayLanguage(getInputLocale()); } ///////////////////////////// @@ -526,34 +430,20 @@ public class SubtypeSwitcher { public String getCurrentSubtypeExtraValue() { // If null, return what an empty ExtraValue would return : the empty string. - return null != mCurrentSubtype ? mCurrentSubtype.getExtraValue() : ""; + return mCurrentSubtype.getExtraValue(); } public boolean currentSubtypeContainsExtraValueKey(String key) { // If null, return what an empty ExtraValue would return : false. - return null != mCurrentSubtype ? mCurrentSubtype.containsExtraValueKey(key) : false; + return mCurrentSubtype.containsExtraValueKey(key); } public String getCurrentSubtypeExtraValueOf(String key) { // If null, return what an empty ExtraValue would return : null. - return null != mCurrentSubtype ? mCurrentSubtype.getExtraValueOf(key) : null; + return mCurrentSubtype.getExtraValueOf(key); } public String getCurrentSubtypeMode() { - return null != mCurrentSubtype ? mCurrentSubtype.getMode() : KEYBOARD_MODE; - } - - - public static boolean isVoiceSupported(Context context, String locale) { - // Get the current list of supported locales and check the current locale against that - // list. We cache this value so as not to check it every time the user starts a voice - // input. Because this method is called by onStartInputView, this should mean that as - // long as the locale doesn't change while the user is keeping the IME open, the - // value should never be stale. - String supportedLocalesString = VoiceProxy.getSupportedLocalesString( - context.getContentResolver()); - List<String> voiceInputSupportedLocales = Arrays.asList( - supportedLocalesString.split("\\s+")); - return voiceInputSupportedLocales.contains(locale); + return mCurrentSubtype.getMode(); } } 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..2c5d58200 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/SubtypeUtils.java @@ -0,0 +1,132 @@ +/* + * 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.view.inputmethod.InputMethodInfo; +import android.view.inputmethod.InputMethodSubtype; + +import com.android.inputmethod.compat.InputMethodManagerCompatWrapper; + +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, InputMethodSubtype ims) { + final InputMethodManagerCompatWrapper imm = InputMethodManagerCompatWrapper.getInstance(); + if (imm == null) return false; + + final InputMethodInfo myImi = getInputMethodInfo(context.getPackageName()); + final List<InputMethodSubtype> subtypes = imm.getEnabledInputMethodSubtypeList(myImi, true); + for (final InputMethodSubtype 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<InputMethodInfo> enabledImis = imm.getEnabledInputMethodList(); + return hasMultipleEnabledSubtypes(shouldIncludeAuxiliarySubtypes, enabledImis); + } + + public static boolean hasMultipleEnabledSubtypesInThisIme(Context context, + final boolean shouldIncludeAuxiliarySubtypes) { + final InputMethodInfo myImi = getInputMethodInfo(context.getPackageName()); + final List<InputMethodInfo> imiList = Collections.singletonList(myImi); + return hasMultipleEnabledSubtypes(shouldIncludeAuxiliarySubtypes, imiList); + } + + private static boolean hasMultipleEnabledSubtypes(final boolean shouldIncludeAuxiliarySubtypes, + List<InputMethodInfo> imiList) { + final InputMethodManagerCompatWrapper imm = InputMethodManagerCompatWrapper.getInstance(); + if (imm == null) return false; + + // Number of the filtered IMEs + int filteredImisCount = 0; + + for (InputMethodInfo imi : imiList) { + // We can return true immediately after we find two or more filtered IMEs. + if (filteredImisCount > 1) return true; + final List<InputMethodSubtype> subtypes = + imm.getEnabledInputMethodSubtypeList(imi, true); + // IMEs that have no subtypes should be counted. + if (subtypes.isEmpty()) { + ++filteredImisCount; + continue; + } + + int auxCount = 0; + for (InputMethodSubtype 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<InputMethodSubtype> 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 (InputMethodSubtype 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 InputMethodInfo getInputMethodInfo(String packageName) { + final InputMethodManagerCompatWrapper imm = InputMethodManagerCompatWrapper.getInstance(); + if (imm == null) { + throw new RuntimeException("Input method manager not found"); + } + + for (final InputMethodInfo 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..b31f3019c 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -20,31 +20,28 @@ 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; -import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Locale; -import java.util.Map; -import java.util.Set; /** * This class loads a dictionary and provides a list of suggestions for a given sequence of * characters. This includes corrections and completions. */ public class Suggest implements Dictionary.WordCallback { - public static final String TAG = Suggest.class.getSimpleName(); 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 @@ -64,9 +61,8 @@ public class Suggest implements Dictionary.WordCallback { public static final int DIC_USER_TYPED = 0; public static final int DIC_MAIN = 1; public static final int DIC_USER = 2; - public static final int DIC_USER_UNIGRAM = 3; + public static final int DIC_USER_HISTORY = 3; public static final int DIC_CONTACTS = 4; - public static final int DIC_USER_BIGRAM = 5; public static final int DIC_WHITELIST = 6; // If you add a type of dictionary, increment DIC_TYPE_LAST_ID // TODO: this value seems unused. Remove it? @@ -75,39 +71,38 @@ public class Suggest implements Dictionary.WordCallback { public static final String DICT_KEY_CONTACTS = "contacts"; // User dictionary, the system-managed one. public static final String DICT_KEY_USER = "user"; - // User unigram dictionary, internal to LatinIME - public static final String DICT_KEY_USER_UNIGRAM = "user_unigram"; - // User bigram dictionary, internal to LatinIME - public static final String DICT_KEY_USER_BIGRAM = "user_bigram"; + // User history dictionary for the unigram map, internal to LatinIME + public static final String DICT_KEY_USER_HISTORY_UNIGRAM = "history_unigram"; + // User history dictionary for the bigram map, internal to LatinIME + public static final String DICT_KEY_USER_HISTORY_BIGRAM = "history_bigram"; public static final String DICT_KEY_WHITELIST ="whitelist"; private static final boolean DBG = LatinImeLogger.sDBG; - private AutoCorrection mAutoCorrection; - private Dictionary mMainDict; private ContactsDictionary mContactsDict; private WhitelistDictionary mWhiteListDictionary; - private final Map<String, Dictionary> mUnigramDictionaries = new HashMap<String, Dictionary>(); - private final Map<String, Dictionary> mBigramDictionaries = new HashMap<String, Dictionary>(); + private final HashMap<String, Dictionary> mUnigramDictionaries = + new HashMap<String, Dictionary>(); + private final HashMap<String, Dictionary> mBigramDictionaries = + new HashMap<String, Dictionary>(); private int mPrefMaxSuggestions = 18; private static final int PREF_MAX_BIGRAMS = 60; private double mAutoCorrectionThreshold; - private int[] mScores = new int[mPrefMaxSuggestions]; - 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<SuggestedWordInfo> mSuggestions = new ArrayList<SuggestedWordInfo>(); + private ArrayList<SuggestedWordInfo> mBigramSuggestions = new ArrayList<SuggestedWordInfo>(); + 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 +111,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 +137,7 @@ public class Suggest implements Dictionary.WordCallback { initWhitelistAndAutocorrectAndPool(context, locale); } - private void addOrReplaceDictionary(Map<String, Dictionary> dictionaries, String key, + private static void addOrReplaceDictionary(HashMap<String, Dictionary> dictionaries, String key, Dictionary dict) { final Dictionary oldDict = (dict == null) ? dictionaries.remove(key) @@ -169,14 +162,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() { @@ -187,11 +172,11 @@ public class Suggest implements Dictionary.WordCallback { return mContactsDict; } - public Map<String, Dictionary> getUnigramDictionaries() { + public HashMap<String, Dictionary> getUnigramDictionaries() { return mUnigramDictionaries; } - public int getApproxMaxWordLength() { + public static int getApproxMaxWordLength() { return APPROX_MAX_WORD_LENGTH; } @@ -214,56 +199,22 @@ public class Suggest implements Dictionary.WordCallback { addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_CONTACTS, contactsDictionary); } - public void setUserUnigramDictionary(Dictionary userUnigramDictionary) { - addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_USER_UNIGRAM, userUnigramDictionary); - } - - public void setUserBigramDictionary(Dictionary userBigramDictionary) { - addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_USER_BIGRAM, userBigramDictionary); + public void setUserHistoryDictionary(Dictionary userHistoryDictionary) { + addOrReplaceDictionary(mUnigramDictionaries, DICT_KEY_USER_HISTORY_UNIGRAM, + userHistoryDictionary); + addOrReplaceDictionary(mBigramDictionaries, DICT_KEY_USER_HISTORY_BIGRAM, + userHistoryDictionary); } public void setAutoCorrectionThreshold(double threshold) { 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()); @@ -276,42 +227,68 @@ public class Suggest implements Dictionary.WordCallback { return sb; } - 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()); - sb.append(bigram); - mSuggestions.add(sb); + protected void addBigramToSuggestions(SuggestedWordInfo bigram) { + mSuggestions.add(bigram); + } + + private static final WordComposer sEmptyWordComposer = new WordComposer(); + public SuggestedWords getBigramPredictions(CharSequence prevWordForBigram) { + LatinImeLogger.onStartSuggestion(prevWordForBigram); + mIsFirstCharCapitalized = false; + mIsAllUpperCase = false; + mTrailingSingleQuotesCount = 0; + mSuggestions = new ArrayList<SuggestedWordInfo>(mPrefMaxSuggestions); + + // Treating USER_TYPED as UNIGRAM suggestion for logging now. + LatinImeLogger.onAddSuggestedWord("", Suggest.DIC_USER_TYPED, Dictionary.UNIGRAM); + mConsideredWord = ""; + + mBigramSuggestions = new ArrayList<SuggestedWordInfo>(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)); + } + + SuggestedWordInfo.removeDups(mSuggestions); + + return new SuggestedWords(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); - 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; - - if (wordComposer.size() <= 1 && (mCorrectionMode == CORRECTION_FULL_BIGRAM - || mCorrectionMode == CORRECTION_BASIC)) { + mTrailingSingleQuotesCount = wordComposer.trailingSingleQuotesCount(); + mSuggestions = new ArrayList<SuggestedWordInfo>(mPrefMaxSuggestions); + + 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 && (correctionMode == CORRECTION_FULL_BIGRAM)) { // At first character typed, search only the bigrams - Arrays.fill(mBigramScores, 0); - collectGarbage(mBigramSuggestions, PREF_MAX_BIGRAMS); + mBigramSuggestions = new ArrayList<SuggestedWordInfo>(PREF_MAX_BIGRAMS); if (!TextUtils.isEmpty(prevWordForBigram)) { CharSequence lowerPrevWord = prevWordForBigram.toString().toLowerCase(); @@ -321,7 +298,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,15 +306,16 @@ 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. + // TODO: Use codepoint instead of char final char currentCharUpper = Character.toUpperCase(currentChar); int count = 0; final int bigramSuggestionSize = mBigramSuggestions.size(); for (int i = 0; i < bigramSuggestionSize; i++) { - final CharSequence bigramSuggestion = mBigramSuggestions.get(i); - final char bigramSuggestionFirstChar = bigramSuggestion.charAt(0); + final SuggestedWordInfo bigramSuggestion = mBigramSuggestions.get(i); + final char bigramSuggestionFirstChar = + (char)bigramSuggestion.codePointAt(0); if (bigramSuggestionFirstChar == currentChar || bigramSuggestionFirstChar == currentCharUpper) { addBigramToSuggestions(bigramSuggestion); @@ -348,104 +326,157 @@ 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)) + if (key.equals(DICT_KEY_USER_HISTORY_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, 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, new SuggestedWordInfo( + sb.toString(), SuggestedWordInfo.MAX_SCORE)); + } else { + mSuggestions.add(0, new SuggestedWordInfo( + whitelistedWord, SuggestedWordInfo.MAX_SCORE)); + } } - if (typedWord != null) { - mSuggestions.add(0, typedWordString); - } - Utils.removeDupes(mSuggestions); + mSuggestions.add(0, new SuggestedWordInfo(typedWord, SuggestedWordInfo.MAX_SCORE)); + SuggestedWordInfo.removeDups(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); + } else { + suggestionsList = 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(); + private static ArrayList<SuggestedWordInfo> getSuggestionsInfoListWithDebugInfo( + final String typedWord, final ArrayList<SuggestedWordInfo> suggestions) { + final SuggestedWordInfo typedWordInfo = suggestions.get(0); + typedWordInfo.setDebugString("+"); + double normalizedScore = BinaryDictionary.calcNormalizedScore( + typedWord, typedWordInfo.toString(), typedWordInfo.mScore); + final int suggestionsSize = suggestions.size(); + final ArrayList<SuggestedWordInfo> suggestionsList = + new ArrayList<SuggestedWordInfo>(suggestionsSize); + suggestionsList.add(typedWordInfo); + // 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 < suggestionsSize - 1; ++i) { + final SuggestedWordInfo cur = suggestions.get(i + 1); + final String scoreInfoString; + if (normalizedScore > 0) { + scoreInfoString = String.format("%d (%4.2f)", cur.mScore, normalizedScore); + normalizedScore = 0.0; + } else { + scoreInfoString = Integer.toString(cur.mScore); + } + cur.setDebugString(scoreInfoString); + suggestionsList.add(cur); + } + return suggestionsList; } + // TODO: Use codepoint instead of char @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 ArrayList<CharSequence> suggestions; - final int[] sortedScores; + final int dicTypeId, final int dataType) { + int dataTypeForLog = dataType; + final ArrayList<SuggestedWordInfo> suggestions; final int prefMaxSuggestions; - if(dataType == Dictionary.DataType.BIGRAM) { + if (dataType == Dictionary.BIGRAM) { suggestions = mBigramSuggestions; - sortedScores = mBigramScores; prefMaxSuggestions = PREF_MAX_BIGRAMS; } else { suggestions = mSuggestions; - sortedScores = mScores; prefMaxSuggestions = mPrefMaxSuggestions; } 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) { - final String currentHighestWord = suggestions.get(0).toString(); + final SuggestedWordInfo currentHighestWord = suggestions.get(0); // If the current highest word is also equal to typed word, we need to compare // 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) - && score <= sortedScores[0]) { + if (StringUtils.equalsIgnoreCase(currentHighestWord.mWord, word, offset, length) + && score <= currentHighestWord.mScore) { 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]) + double multiplier = (((double) mBigramSuggestions.get(bigramSuggestion).mScore) / MAXIMUM_BIGRAM_FREQUENCY) * (BIGRAM_MULTIPLIER_MAX - BIGRAM_MULTIPLIER_MIN) + BIGRAM_MULTIPLIER_MIN; @@ -459,10 +490,12 @@ public class Suggest implements Dictionary.WordCallback { } // Check the last one's score and bail - if (sortedScores[prefMaxSuggestions - 1] >= score) return true; - while (pos < prefMaxSuggestions) { - if (sortedScores[pos] < score - || (sortedScores[pos] == score && length < suggestions.get(pos).length())) { + if (suggestions.size() >= prefMaxSuggestions + && suggestions.get(prefMaxSuggestions - 1).mScore >= score) return true; + while (pos < suggestions.size()) { + final int curScore = suggestions.get(pos).mScore; + if (curScore < score + || (curScore == score && length < suggestions.get(pos).codePointCount())) { break; } pos++; @@ -472,9 +505,7 @@ public class Suggest implements Dictionary.WordCallback { return true; } - 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,57 +517,41 @@ public class Suggest implements Dictionary.WordCallback { } else { sb.append(word, offset, length); } - suggestions.add(pos, sb); + for (int i = mTrailingSingleQuotesCount - 1; i >= 0; --i) { + sb.appendCodePoint(Keyboard.CODE_SINGLE_QUOTE); + } + suggestions.add(pos, new SuggestedWordInfo(sb, score)); 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); } return true; } + // TODO: Use codepoint instead of char private int searchBigramSuggestion(final char[] word, final int offset, final int length) { // 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).codePointCount() == 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).codePointAt(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>(); + final HashSet<Dictionary> dictionaries = new HashSet<Dictionary>(); dictionaries.addAll(mUnigramDictionaries.values()); dictionaries.addAll(mBigramDictionaries.values()); for (final Dictionary dictionary : dictionaries) { @@ -544,4 +559,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..0c0ce182f 100644 --- a/java/src/com/android/inputmethod/latin/SuggestedWords.java +++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java @@ -20,211 +20,160 @@ import android.text.TextUtils; import android.view.inputmethod.CompletionInfo; import java.util.ArrayList; -import java.util.Collections; +import java.util.Arrays; 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( + new ArrayList<SuggestedWordInfo>(0), false, false, false, false, false); - public final List<CharSequence> mWords; public final boolean mTypedWordValid; public final boolean mHasAutoCorrectionCandidate; public final boolean mIsPunctuationSuggestions; - 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 final boolean mAllowsToBeAutoCorrected; + public final boolean mIsObsoleteSuggestions; + private final ArrayList<SuggestedWordInfo> mSuggestedWordInfoList; + + public SuggestedWords(final ArrayList<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 getWordInfo(int pos) { + return mSuggestedWordInfoList.get(pos); } 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 willAutoCorrect() { + return !mTypedWordValid && mHasAutoCorrectionCandidate; } - public boolean isPunctuationSuggestions() { - return mIsPunctuationSuggestions; + @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 void setShouldBlockAutoCorrection() { - mShouldBlockAutoCorrection = true; - } - - 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 static ArrayList<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(), + SuggestedWordInfo.MAX_SCORE)); } + return result; + } - public Builder setApplicationSpecifiedCompletions(CompletionInfo[] infos) { - for (CompletionInfo info : infos) { - if (null != info) addWord(info.getText()); + // 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, SuggestedWordInfo.MAX_SCORE)); + alreadySeen.add(typedWord.toString()); + final int previousSize = previousSuggestions.size(); + for (int pos = 1; pos < previousSize; pos++) { + final SuggestedWordInfo prevWordInfo = previousSuggestions.getWordInfo(pos); + final String prevWord = prevWordInfo.mWord.toString(); + // Filter out duplicate suggestion. + if (!alreadySeen.contains(prevWord)) { + suggestionsList.add(prevWordInfo); + alreadySeen.add(prevWord); } - return this; } + return suggestionsList; + } - public Builder setTypedWordValid(boolean typedWordValid) { - mTypedWordValid = typedWordValid; - return this; - } + public static class SuggestedWordInfo { + public static final int MAX_SCORE = Integer.MAX_VALUE; + private final String mWordStr; + public final CharSequence mWord; + public final int mScore; + public final int mCodePointCount; + private String mDebugString = ""; - public Builder setHasMinimalSuggestion(boolean hasMinimalSuggestion) { - mHasMinimalSuggestion = hasMinimalSuggestion; - return this; + public SuggestedWordInfo(final CharSequence word, final int score) { + mWordStr = word.toString(); + mWord = word; + mScore = score; + mCodePointCount = mWordStr.codePointCount(0, mWordStr.length()); } - 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 void setDebugString(String str) { + if (null == str) throw new NullPointerException("Debug info is null"); + mDebugString = str; } - public SuggestedWords build() { - return new SuggestedWords(mWords, mTypedWordValid, mHasMinimalSuggestion, - mIsPunctuationSuggestions, mSuggestedWordInfoList); + public String getDebugString() { + return mDebugString; } - public int size() { - return mWords.size(); + public int codePointCount() { + return mCodePointCount; } - public CharSequence getWord(int pos) { - return mWords.get(pos); + public int codePointAt(int i) { + return mWordStr.codePointAt(i); } @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(" ; "); - } - return sb.toString(); - } - } - - public static class SuggestedWordInfo { - private final CharSequence mDebugString; - private final boolean mPreviousSuggestedWord; - - public SuggestedWordInfo() { - mDebugString = ""; - mPreviousSuggestedWord = false; - } - - public SuggestedWordInfo(CharSequence debugString, boolean previousSuggestedWord) { - mDebugString = debugString; - mPreviousSuggestedWord = previousSuggestedWord; - } - - public String getDebugString() { - if (mDebugString == null) { - return ""; + if (TextUtils.isEmpty(mDebugString)) { + return mWordStr; } else { - return mDebugString.toString(); + return mWordStr + " (" + mDebugString.toString() + ")"; } } - public boolean isObsoleteSuggestedWord () { - return mPreviousSuggestedWord; + // TODO: Consolidate this method and StringUtils.removeDupes() in the future. + public static void removeDups(ArrayList<SuggestedWordInfo> candidates) { + if (candidates.size() <= 1) { + return; + } + int i = 1; + while(i < candidates.size()) { + final SuggestedWordInfo cur = candidates.get(i); + for (int j = 0; j < i; ++j) { + final SuggestedWordInfo previous = candidates.get(j); + if (TextUtils.equals(cur.mWord, previous.mWord)) { + candidates.remove(cur.mScore < previous.mScore ? i : j); + --i; + break; + } + } + ++i; + } } } } 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/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/UserBigramDictionary.java b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java index 9e656675e..62525c205 100644 --- a/java/src/com/android/inputmethod/latin/UserBigramDictionary.java +++ b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java @@ -31,12 +31,11 @@ import java.util.HashSet; import java.util.Iterator; /** - * Stores all the pairs user types in databases. Prune the database if the size - * gets too big. Unlike AutoDictionary, it even stores the pairs that are already - * in the dictionary. + * Locally gathers stats about the words user types and various other signals like auto-correction + * cancellation or manual picks. This allows the keyboard to adapt to the typist over time. */ -public class UserBigramDictionary extends ExpandableDictionary { - private static final String TAG = "UserBigramDictionary"; +public class UserHistoryDictionary extends ExpandableDictionary { + private static final String TAG = "UserHistoryDictionary"; /** Any pair being typed or picked */ private static final int FREQUENCY_FOR_TYPED = 2; @@ -45,14 +44,14 @@ public class UserBigramDictionary extends ExpandableDictionary { private static final int FREQUENCY_MAX = 127; /** Maximum number of pairs. Pruning will start when databases goes above this number. */ - private static int sMaxUserBigrams = 10000; + private static int sMaxHistoryBigrams = 10000; /** * When it hits maximum bigram pair, it will delete until you are left with - * only (sMaxUserBigrams - sDeleteUserBigrams) pairs. + * only (sMaxHistoryBigrams - sDeleteHistoryBigrams) pairs. * Do not keep this number small to avoid deleting too often. */ - private static int sDeleteUserBigrams = 1000; + private static int sDeleteHistoryBigrams = 1000; /** * Database version should increase if the database structure changes @@ -64,7 +63,7 @@ public class UserBigramDictionary extends ExpandableDictionary { /** Name of the words table in the database */ private static final String MAIN_TABLE_NAME = "main"; // TODO: Consume less space by using a unique id for locale instead of the whole - // 2-5 character string. (Same TODO from AutoDictionary) + // 2-5 character string. private static final String MAIN_COLUMN_ID = BaseColumns._ID; private static final String MAIN_COLUMN_WORD1 = "word1"; private static final String MAIN_COLUMN_WORD2 = "word2"; @@ -76,8 +75,6 @@ public class UserBigramDictionary extends ExpandableDictionary { private static final String FREQ_COLUMN_PAIR_ID = "pair_id"; private static final String FREQ_COLUMN_FREQUENCY = "freq"; - private final LatinIME mIme; - /** Locale for which this auto dictionary is storing words */ private String mLocale; @@ -114,8 +111,16 @@ public class UserBigramDictionary extends ExpandableDictionary { @Override public boolean equals(Object bigram) { - Bigram bigram2 = (Bigram) bigram; - return (mWord1.equals(bigram2.mWord1) && mWord2.equals(bigram2.mWord2)); + if (!(bigram instanceof Bigram)) { + return false; + } + final Bigram bigram2 = (Bigram) bigram; + final boolean eq1 = + mWord1 == null ? bigram2.mWord1 == null : mWord1.equals(bigram2.mWord1); + if (!eq1) { + return false; + } + return mWord2 == null ? bigram2.mWord2 == null : mWord2.equals(bigram2.mWord2); } @Override @@ -124,17 +129,16 @@ public class UserBigramDictionary extends ExpandableDictionary { } } - public void setDatabaseMax(int maxUserBigram) { - sMaxUserBigrams = maxUserBigram; + public void setDatabaseMax(int maxHistoryBigram) { + sMaxHistoryBigrams = maxHistoryBigram; } - public void setDatabaseDelete(int deleteUserBigram) { - sDeleteUserBigrams = deleteUserBigram; + public void setDatabaseDelete(int deleteHistoryBigram) { + sDeleteHistoryBigrams = deleteHistoryBigram; } - public UserBigramDictionary(Context context, LatinIME ime, String locale, int dicTypeId) { + public UserHistoryDictionary(final Context context, final String locale, final int dicTypeId) { super(context, dicTypeId); - mIme = ime; mLocale = locale; if (sOpenHelper == null) { sOpenHelper = new DatabaseHelper(getContext()); @@ -155,19 +159,35 @@ public class UserBigramDictionary extends ExpandableDictionary { } /** - * Pair will be added to the userbigram database. + * Return whether the passed charsequence is in the dictionary. */ - public int addBigrams(String word1, String word2) { - // remove caps if second word is autocapitalized - if (mIme != null && mIme.getCurrentWord().isAutoCapitalized()) { - word2 = Character.toLowerCase(word2.charAt(0)) + word2.substring(1); - } + @Override + public boolean isValidWord(final CharSequence word) { + // TODO: figure out what is the correct thing to do here. + return false; + } + + /** + * Pair will be added to the user history dictionary. + * + * The first word may be null. That means we don't know the context, in other words, + * it's only a unigram. The first word may also be an empty string : this means start + * context, as in beginning of a sentence for example. + * The second word may not be null (a NullPointerException would be thrown). + */ + public int addToUserHistory(final String word1, String word2) { + super.addWord(word2, FREQUENCY_FOR_TYPED); // Do not insert a word as a bigram of itself - if (word1.equals(word2)) { + if (word2.equals(word1)) { return 0; } - int freq = super.addBigram(word1, word2, FREQUENCY_FOR_TYPED); + int freq; + if (null == word1) { + freq = FREQUENCY_FOR_TYPED; + } else { + freq = super.addBigram(word1, word2, FREQUENCY_FOR_TYPED); + } if (freq > FREQUENCY_MAX) freq = FREQUENCY_MAX; synchronized (mPendingWritesLock) { if (freq == FREQUENCY_FOR_TYPED || mPendingWrites.isEmpty()) { @@ -212,7 +232,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); @@ -224,7 +245,10 @@ public class UserBigramDictionary extends ExpandableDictionary { int frequency = cursor.getInt(frequencyIndex); // Safeguard against adding really long words. Stack may overflow due // to recursive lookup - if (word1.length() < MAX_WORD_LENGTH && word2.length() < MAX_WORD_LENGTH) { + if (null == word1) { + super.addWord(word2, frequency); + } else if (word1.length() < BinaryDictionary.MAX_WORD_LENGTH + && word2.length() < BinaryDictionary.MAX_WORD_LENGTH) { super.setBigram(word1, word2, frequency); } cursor.moveToNext(); @@ -238,7 +262,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 +273,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,15 +340,15 @@ 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); try { int totalRowCount = c.getCount(); // prune out old data if we have too much data - if (totalRowCount > sMaxUserBigrams) { - int numDeleteRows = (totalRowCount - sMaxUserBigrams) + sDeleteUserBigrams; + if (totalRowCount > sMaxHistoryBigrams) { + int numDeleteRows = (totalRowCount - sMaxHistoryBigrams) + sDeleteHistoryBigrams; int pairIdColumnId = c.getColumnIndex(FREQ_COLUMN_PAIR_ID); c.moveToFirst(); int count = 0; @@ -344,18 +374,39 @@ 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(); while (iterator.hasNext()) { + // TODO: this process of making a text search for each pair each time + // is terribly inefficient. Optimize this. Bigram bi = iterator.next(); // find pair id - Cursor c = db.query(MAIN_TABLE_NAME, new String[] { MAIN_COLUMN_ID }, - MAIN_COLUMN_WORD1 + "=? AND " + MAIN_COLUMN_WORD2 + "=? AND " - + MAIN_COLUMN_LOCALE + "=?", - new String[] { bi.mWord1, bi.mWord2, mLocale }, null, null, null); + final Cursor c; + if (null != bi.mWord1) { + c = db.query(MAIN_TABLE_NAME, new String[] { MAIN_COLUMN_ID }, + MAIN_COLUMN_WORD1 + "=? AND " + MAIN_COLUMN_WORD2 + "=? AND " + + MAIN_COLUMN_LOCALE + "=?", + new String[] { bi.mWord1, bi.mWord2, mLocale }, null, null, null); + } else { + c = db.query(MAIN_TABLE_NAME, new String[] { MAIN_COLUMN_ID }, + MAIN_COLUMN_WORD1 + " IS NULL AND " + MAIN_COLUMN_WORD2 + "=? AND " + + MAIN_COLUMN_LOCALE + "=?", + new String[] { bi.mWord2, mLocale }, null, null, null); + } int pairId; if (c.moveToFirst()) { @@ -380,7 +431,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 +439,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/UserUnigramDictionary.java b/java/src/com/android/inputmethod/latin/UserUnigramDictionary.java deleted file mode 100644 index e41230b3c..000000000 --- a/java/src/com/android/inputmethod/latin/UserUnigramDictionary.java +++ /dev/null @@ -1,262 +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.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; -import android.database.sqlite.SQLiteQueryBuilder; -import android.os.AsyncTask; -import android.provider.BaseColumns; -import android.util.Log; - -import java.util.HashMap; -import java.util.Map.Entry; -import java.util.Set; - -/** - * This class (inherited from the old AutoDictionary) is used for user history - * based dictionary. It stores words that the user typed to supply a provision - * for suggesting and re-ordering of candidates. - */ -public class UserUnigramDictionary extends ExpandableDictionary { - static final boolean ENABLE_USER_UNIGRAM_DICTIONARY = false; - - // Weight added to a user picking a new word from the suggestion strip - static final int FREQUENCY_FOR_PICKED = 3; - // Weight added to a user typing a new word that doesn't get corrected (or is reverted) - static final int FREQUENCY_FOR_TYPED = 1; - // If the user touches a typed word 2 times or more, it will become valid. - private static final int VALIDITY_THRESHOLD = 2 * FREQUENCY_FOR_PICKED; - - private LatinIME mIme; - // Locale for which this user unigram dictionary is storing words - private String mLocale; - - private HashMap<String,Integer> mPendingWrites = new HashMap<String,Integer>(); - private final Object mPendingWritesLock = new Object(); - - // TODO: we should probably change the database name - private static final String DATABASE_NAME = "auto_dict.db"; - private static final int DATABASE_VERSION = 1; - - // These are the columns in the dictionary - // TODO: Consume less space by using a unique id for locale instead of the whole - // 2-5 character string. - private static final String COLUMN_ID = BaseColumns._ID; - private static final String COLUMN_WORD = "word"; - private static final String COLUMN_FREQUENCY = "freq"; - private static final String COLUMN_LOCALE = "locale"; - - /** Sort by descending order of frequency. */ - public static final String DEFAULT_SORT_ORDER = COLUMN_FREQUENCY + " DESC"; - - /** Name of the words table in the database */ - private static final String USER_UNIGRAM_DICT_TABLE_NAME = "words"; - - private static HashMap<String, String> sDictProjectionMap; - - static { - if (ENABLE_USER_UNIGRAM_DICTIONARY) { - sDictProjectionMap = new HashMap<String, String>(); - sDictProjectionMap.put(COLUMN_ID, COLUMN_ID); - sDictProjectionMap.put(COLUMN_WORD, COLUMN_WORD); - sDictProjectionMap.put(COLUMN_FREQUENCY, COLUMN_FREQUENCY); - sDictProjectionMap.put(COLUMN_LOCALE, COLUMN_LOCALE); - } - } - - private static DatabaseHelper sOpenHelper = null; - - public UserUnigramDictionary(Context context, LatinIME ime, String locale, int dicTypeId) { - super(context, dicTypeId); - // Super must be first statement of the constructor... I'd like not to do it if the - // user unigram dictionary is not enabled, but Java won't let me. - if (!ENABLE_USER_UNIGRAM_DICTIONARY) return; - mIme = ime; - mLocale = locale; - if (sOpenHelper == null) { - sOpenHelper = new DatabaseHelper(getContext()); - } - if (mLocale != null && mLocale.length() > 1) { - loadDictionary(); - } - } - - @Override - public synchronized boolean isValidWord(CharSequence word) { - if (!ENABLE_USER_UNIGRAM_DICTIONARY) return false; - final int frequency = getWordFrequency(word); - return frequency >= VALIDITY_THRESHOLD; - } - - @Override - public void close() { - super.close(); - if (!ENABLE_USER_UNIGRAM_DICTIONARY) return; - flushPendingWrites(); - // Don't close the database as locale changes will require it to be reopened anyway - // Also, the database is written to somewhat frequently, so it needs to be kept alive - // throughout the life of the process. - // mOpenHelper.close(); - } - - @Override - 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 }); - try { - if (cursor.moveToFirst()) { - int wordIndex = cursor.getColumnIndex(COLUMN_WORD); - int frequencyIndex = cursor.getColumnIndex(COLUMN_FREQUENCY); - while (!cursor.isAfterLast()) { - String word = cursor.getString(wordIndex); - int frequency = cursor.getInt(frequencyIndex); - // Safeguard against adding really long words. Stack may overflow due - // to recursive lookup - if (word.length() < getMaxWordLength()) { - super.addWord(word, frequency); - } - cursor.moveToNext(); - } - } - } finally { - cursor.close(); - } - } - - @Override - public void addWord(String newWord, int addFrequency) { - if (!ENABLE_USER_UNIGRAM_DICTIONARY) return; - String word = newWord; - final int length = word.length(); - // Don't add very short or very long words. - if (length < 2 || length > getMaxWordLength()) return; - if (mIme.getCurrentWord().isAutoCapitalized()) { - // Remove caps before adding - word = Character.toLowerCase(word.charAt(0)) + word.substring(1); - } - int freq = getWordFrequency(word); - freq = freq < 0 ? addFrequency : freq + addFrequency; - super.addWord(word, freq); - - synchronized (mPendingWritesLock) { - // Write a null frequency if it is to be deleted from the db - mPendingWrites.put(word, freq == 0 ? null : new Integer(freq)); - } - } - - /** - * Schedules a background thread to write any pending words to the database. - */ - public void flushPendingWrites() { - if (!ENABLE_USER_UNIGRAM_DICTIONARY) return; - synchronized (mPendingWritesLock) { - // Nothing pending? Return - if (mPendingWrites.isEmpty()) return; - // Create a background thread to write the pending entries - new UpdateDbTask(getContext(), 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>(); - } - } - - /** - * This class helps open, create, and upgrade the database file. - */ - private static class DatabaseHelper extends SQLiteOpenHelper { - - DatabaseHelper(Context context) { - super(context, DATABASE_NAME, null, DATABASE_VERSION); - } - - @Override - public void onCreate(SQLiteDatabase db) { - db.execSQL("CREATE TABLE " + USER_UNIGRAM_DICT_TABLE_NAME + " (" - + COLUMN_ID + " INTEGER PRIMARY KEY," - + COLUMN_WORD + " TEXT," - + COLUMN_FREQUENCY + " INTEGER," - + COLUMN_LOCALE + " TEXT" - + ");"); - } - - @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - Log.w("UserUnigramDictionary", "Upgrading database from version " + oldVersion + " to " - + newVersion + ", which will destroy all old data"); - db.execSQL("DROP TABLE IF EXISTS " + USER_UNIGRAM_DICT_TABLE_NAME); - onCreate(db); - } - } - - private 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; - } - - /** - * Async task to write pending words to the database so that it stays in sync with - * the in-memory trie. - */ - private static class UpdateDbTask extends AsyncTask<Void, Void, Void> { - private final HashMap<String, Integer> mMap; - private final DatabaseHelper mDbHelper; - private final String mLocale; - - public UpdateDbTask(@SuppressWarnings("unused") Context context, DatabaseHelper openHelper, - HashMap<String, Integer> pendingWrites, String locale) { - mMap = pendingWrites; - mLocale = locale; - mDbHelper = openHelper; - } - - @Override - protected Void doInBackground(Void... v) { - SQLiteDatabase db = mDbHelper.getWritableDatabase(); - // Write all the entries to the db - Set<Entry<String,Integer>> mEntries = mMap.entrySet(); - for (Entry<String,Integer> entry : mEntries) { - Integer freq = entry.getValue(); - db.delete(USER_UNIGRAM_DICT_TABLE_NAME, COLUMN_WORD + "=? AND " + COLUMN_LOCALE - + "=?", new String[] { entry.getKey(), mLocale }); - if (freq != null) { - db.insert(USER_UNIGRAM_DICT_TABLE_NAME, null, - getContentValues(entry.getKey(), freq, mLocale)); - } - } - return null; - } - - private ContentValues getContentValues(String word, int frequency, String locale) { - ContentValues values = new ContentValues(4); - values.put(COLUMN_WORD, word); - values.put(COLUMN_FREQUENCY, frequency); - values.put(COLUMN_LOCALE, locale); - return values; - } - } -} diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java index b29ff1975..0485c881b 100644 --- a/java/src/com/android/inputmethod/latin/Utils.java +++ b/java/src/com/android/inputmethod/latin/Utils.java @@ -17,48 +17,39 @@ package com.android.inputmethod.latin; import android.content.Context; -import android.content.SharedPreferences; +import android.content.Intent; +import android.content.pm.PackageManager; import android.content.res.Resources; 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; +import java.util.HashMap; 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 +103,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'; @@ -221,7 +110,6 @@ public class Utils { /* package */ static final int BUFSIZE = 20; private InputMethodService mContext; private boolean mEnabled = false; - private boolean mUsabilityStudy = false; private int mEnd = 0; /* package */ int mLength = 0; private char[] mCharBuf = new char[BUFSIZE]; @@ -238,19 +126,16 @@ public class Utils { boolean usabilityStudy) { sRingCharBuffer.mContext = context; sRingCharBuffer.mEnabled = enabled || usabilityStudy; - sRingCharBuffer.mUsabilityStudy = usabilityStudy; 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) { - UsabilityStudyLogUtils.getInstance().writeChar(c, x, y); - } mCharBuf[mEnd] = c; mXBuf[mEnd] = x; mYBuf[mEnd] = y; @@ -317,49 +202,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,56 +215,8 @@ 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 { + // TODO: remove code duplication with ResearchLog class private static final String USABILITY_TAG = UsabilityStudyLogUtils.class.getSimpleName(); private static final String FILENAME = "log.txt"; private static final UsabilityStudyLogUtils sInstance = @@ -437,7 +231,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,8 +259,8 @@ public class Utils { } } - public void writeBackSpace() { - UsabilityStudyLogUtils.getInstance().write("<backspace>\t0\t0"); + public static void writeBackSpace(int x, int y) { + UsabilityStudyLogUtils.getInstance().write("<backspace>\t" + x + "\t" + y); } public void writeChar(char c, int x, int y) { @@ -504,32 +298,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 +421,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 +431,56 @@ 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++; + 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(); } - } - 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 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 getFullDisplayName(Locale locale, boolean returnsNameInThisLocale) { - if (returnsNameInThisLocale) { - return toTitleCase(SubtypeLocale.getFullDisplayName(locale), locale); - } else { - return toTitleCase(locale.getDisplayName(), locale); + public static void onAutoCorrection(final String typedWord, final String correctedWord, + final int separatorCode) { + if (TextUtils.isEmpty(typedWord)) return; + LatinImeLogger.logOnAutoCorrection(typedWord, correctedWord, separatorCode); } - } - - 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 void onAutoCorrectionCancellation() { + LatinImeLogger.logOnAutoCorrectionCancelled(); + } } - public static String getShortDisplayLanguage(Locale locale) { - return toTitleCase(locale.getLanguage(), locale); + 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; } - 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); - } + private static final String HARDWARE_PREFIX = Build.HARDWARE + ","; + private static final HashMap<Integer, String> sDeviceOverrideValueMap = + new HashMap<Integer, String>(); - 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)); - } - } - 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 String getDeviceOverrideValue(Resources res, int overrideResId, String defValue) { + final Integer key = overrideResId; + if (!sDeviceOverrideValueMap.containsKey(key)) { + String overrideValue = defValue; + for (final String element : res.getStringArray(overrideResId)) { + if (element.startsWith(HARDWARE_PREFIX)) { + overrideValue = element.substring(HARDWARE_PREFIX.length()); + break; + } } + sDeviceOverrideValueMap.put(key, overrideValue); } - return -1.0f; - } - - public static boolean willAutoCorrect(SuggestedWords suggestions) { - return !suggestions.mTypedWordValid && suggestions.mHasAutoCorrectionCandidate - && !suggestions.shouldBlockAutoCorrection(); + return sDeviceOverrideValueMap.get(key); } } diff --git a/java/src/com/android/inputmethod/compat/VibratorCompatWrapper.java b/java/src/com/android/inputmethod/latin/VibratorUtils.java index 2fb8b8710..33ffdd9c9 100644 --- a/java/src/com/android/inputmethod/compat/VibratorCompatWrapper.java +++ b/java/src/com/android/inputmethod/latin/VibratorUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 The Android Open Source Project + * 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. @@ -14,38 +14,37 @@ * limitations under the License. */ -package com.android.inputmethod.compat; +package com.android.inputmethod.latin; import android.content.Context; import android.os.Vibrator; -import java.lang.reflect.Method; - -public class VibratorCompatWrapper { - private static final Method METHOD_hasVibrator = CompatUtils.getMethod(Vibrator.class, - "hasVibrator"); - - private static final VibratorCompatWrapper sInstance = new VibratorCompatWrapper(); +public class VibratorUtils { + private static final VibratorUtils sInstance = new VibratorUtils(); private Vibrator mVibrator; - private VibratorCompatWrapper() { + private VibratorUtils() { + // This utility class is not publicly instantiable. } - public static VibratorCompatWrapper getInstance(Context context) { + public static VibratorUtils getInstance(Context context) { if (sInstance.mVibrator == null) { - sInstance.mVibrator = - (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); + sInstance.mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); } return sInstance; } public boolean hasVibrator() { - if (mVibrator == null) + if (mVibrator == null) { return false; - return (Boolean) CompatUtils.invoke(mVibrator, true, METHOD_hasVibrator); + } + return mVibrator.hasVibrator(); } public void vibrate(long milliseconds) { + if (mVibrator == null) { + return; + } mVibrator.vibrate(milliseconds); } } diff --git a/java/src/com/android/inputmethod/latin/WhitelistDictionary.java b/java/src/com/android/inputmethod/latin/WhitelistDictionary.java index a90ef290b..7bb307662 100644 --- a/java/src/com/android/inputmethod/latin/WhitelistDictionary.java +++ b/java/src/com/android/inputmethod/latin/WhitelistDictionary.java @@ -22,6 +22,8 @@ import android.text.TextUtils; import android.util.Log; import android.util.Pair; +import com.android.inputmethod.latin.LocaleUtils.RunInLocale; + import java.util.HashMap; import java.util.Locale; @@ -36,10 +38,14 @@ public class WhitelistDictionary extends ExpandableDictionary { // TODO: Conform to the async load contact of ExpandableDictionary public WhitelistDictionary(final Context context, final Locale locale) { super(context, Suggest.DIC_WHITELIST); - final Resources res = context.getResources(); - final Locale previousLocale = LocaleUtils.setSystemLocale(res, locale); - initWordlist(res.getStringArray(R.array.wordlist_whitelist)); - LocaleUtils.setSystemLocale(res, previousLocale); + final RunInLocale<Void> job = new RunInLocale<Void>() { + @Override + protected Void job(Resources res) { + initWordlist(res.getStringArray(R.array.wordlist_whitelist)); + return null; + } + }; + job.runInLocale(context.getResources(), locale); } private void initWordlist(String[] wordlist) { diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java index adc5637f6..bd8532ebd 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,12 @@ 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 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 +31,33 @@ 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; + private static final int N = BinaryDictionary.MAX_WORD_LENGTH; + private int[] mPrimaryKeyCodes; 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; + private int mCodePointSize; + /** * 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); + mPrimaryKeyCodes = new int[N]; mTypedWord = new StringBuilder(N); mXCoordinates = new int[N]; mYCoordinates = new int[N]; + mAutoCorrection = null; + mTrailingSingleQuotesCount = 0; + refreshSize(); } public WordComposer(WordComposer source) { @@ -60,23 +65,31 @@ public class WordComposer { } public void init(WordComposer source) { - mCodes = new ArrayList<int[]>(source.mCodes); + mPrimaryKeyCodes = Arrays.copyOf(source.mPrimaryKeyCodes, source.mPrimaryKeyCodes.length); 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; + refreshSize(); } /** * Clear out the keys registered so far. */ public void reset() { - mCodes.clear(); mTypedWord.setLength(0); + mAutoCorrection = null; mCapsCount = 0; mIsFirstCharCapitalized = false; + mTrailingSingleQuotesCount = 0; + refreshSize(); + } + + public final void refreshSize() { + mCodePointSize = mTypedWord.codePointCount(0, mTypedWord.length()); } /** @@ -84,16 +97,19 @@ public class WordComposer { * @return the number of keystrokes */ public final int size() { - return mTypedWord.length(); + return mCodePointSize; } - /** - * Returns the codes at a particular position in the word. - * @param index the position in the word - * @return the unicode for the pressed and surrounding keys - */ - public int[] getCodesAt(int index) { - return mCodes.get(index); + public final boolean isComposingWord() { + return size() > 0; + } + + // TODO: make sure that the index should not exceed MAX_WORD_LENGTH + public int getCodeAt(int index) { + if (index >= BinaryDictionary.MAX_WORD_LENGTH) { + return -1; + } + return mPrimaryKeyCodes[index]; } public int[] getXCoordinates() { @@ -109,37 +125,73 @@ 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 keyX; + final int keyY; + if (null == keyDetector + || x == KeyboardActionListener.SUGGESTION_STRIP_COORDINATE + || y == KeyboardActionListener.SUGGESTION_STRIP_COORDINATE + || x == KeyboardActionListener.NOT_A_TOUCH_COORDINATE + || y == KeyboardActionListener.NOT_A_TOUCH_COORDINATE) { + keyX = x; + keyY = y; + } else { + keyX = keyDetector.getTouchX(x); + keyY = keyDetector.getTouchY(y); + } + add(primaryCode, keyX, keyY); + } + /** - * 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 + * Add a new keystroke, with the pressed key's code point with the touch point coordinates. */ - public void add(int primaryCode, int[] codes, int x, int y) { + private void add(int primaryCode, int keyX, int keyY) { final int newIndex = size(); - mTypedWord.append((char) primaryCode); - correctPrimaryJuxtapos(primaryCode, codes); - mCodes.add(codes); + mTypedWord.appendCodePoint(primaryCode); + refreshSize(); if (newIndex < BinaryDictionary.MAX_WORD_LENGTH) { - mXCoordinates[newIndex] = x; - mYCoordinates[newIndex] = y; + mPrimaryKeyCodes[newIndex] = primaryCode >= Keyboard.CODE_SPACE + ? Character.toLowerCase(primaryCode) : primaryCode; + 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; } /** - * Swaps the first and second values in the codes array if the primary code is not the first - * value in the array but the second. This happens when the preferred key is not the key that - * the user released the finger on. - * @param primaryCode the preferred character - * @param codes array of codes based on distance from touch point + * Internal method to retrieve reasonable proximity info for a character. */ - private 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]; - codes[0] = primaryCode; + private void addKeyInfo(final int codePoint, final Keyboard keyboard) { + 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; + add(codePoint, x, y); + return; + } + } + add(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) { + 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); } } @@ -149,25 +201,43 @@ public class WordComposer { public void deleteLast() { final int size = size(); if (size > 0) { - final int lastPos = size - 1; - char lastChar = mTypedWord.charAt(lastPos); - mCodes.remove(lastPos); - mTypedWord.deleteCharAt(lastPos); + // 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--; + refreshSize(); } - if (size() == 0) { + // We may have deleted the last one. + if (0 == 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 +249,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 +268,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 +284,52 @@ 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 int[] primaryKeyCodes = mPrimaryKeyCodes; + final int[] xCoordinates = mXCoordinates; + final int[] yCoordinates = mYCoordinates; + mPrimaryKeyCodes = new int[N]; + mXCoordinates = new int[N]; + mYCoordinates = new int[N]; + final LastComposedWord lastComposedWord = new LastComposedWord(primaryKeyCodes, + xCoordinates, yCoordinates, mTypedWord.toString(), committedWord, separatorCode); + if (type != LastComposedWord.COMMIT_TYPE_DECIDED_WORD + && type != LastComposedWord.COMMIT_TYPE_MANUAL_PICK) { + lastComposedWord.deactivate(); + } + mTypedWord.setLength(0); + refreshSize(); + mAutoCorrection = null; + return lastComposedWord; + } + + public void resumeSuggestionOnLastComposedWord(final LastComposedWord lastComposedWord) { + mPrimaryKeyCodes = lastComposedWord.mPrimaryKeyCodes; + mXCoordinates = lastComposedWord.mXCoordinates; + mYCoordinates = lastComposedWord.mYCoordinates; + mTypedWord.setLength(0); + mTypedWord.append(lastComposedWord.mTypedWord); + refreshSize(); + 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..481cdfa47 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/XmlParseUtils.java @@ -0,0 +1,80 @@ +/* + * 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 { + private XmlParseUtils() { + // This utility class is not publicly instantiable. + } + + @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..e23e1a968 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/define/JniLibName.java @@ -0,0 +1,25 @@ +/* + * 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 final class JniLibName { + private JniLibName() { + // This class is not publicly instantiable. + } + + public static final String JNI_LIB_NAME = "jni_latinime"; +} diff --git a/java/src/com/android/inputmethod/latin/define/ProductionFlag.java b/java/src/com/android/inputmethod/latin/define/ProductionFlag.java new file mode 100644 index 000000000..de2057669 --- /dev/null +++ b/java/src/com/android/inputmethod/latin/define/ProductionFlag.java @@ -0,0 +1,25 @@ +/* + * 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.define; + +public final class ProductionFlag { + private ProductionFlag() { + // This class is not publicly instantiable. + } + + public static final boolean IS_EXPERIMENTAL = false; +} diff --git a/tools/makedict/src/com/android/inputmethod/latin/BinaryDictInputOutput.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java index 92f402d3e..010ea6813 100644 --- a/tools/makedict/src/com/android/inputmethod/latin/BinaryDictInputOutput.java +++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictInputOutput.java @@ -14,11 +14,11 @@ * the License. */ -package com.android.inputmethod.latin; +package com.android.inputmethod.latin.makedict; -import com.android.inputmethod.latin.FusionDictionary.CharGroup; -import com.android.inputmethod.latin.FusionDictionary.Node; -import com.android.inputmethod.latin.FusionDictionary.WeightedString; +import com.android.inputmethod.latin.makedict.FusionDictionary.CharGroup; +import com.android.inputmethod.latin.makedict.FusionDictionary.Node; +import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString; import java.io.FileNotFoundException; import java.io.IOException; @@ -26,6 +26,8 @@ import java.io.OutputStream; import java.io.RandomAccessFile; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; import java.util.Map; import java.util.TreeMap; @@ -44,7 +46,7 @@ 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 * * c | IF FLAG_HAS_MULTIPLE_CHARS @@ -71,6 +73,8 @@ public class BinaryDictInputOutput { * d * dress * + * | IF FLAG_IS_TERMINAL && FLAG_HAS_SHORTCUT_TARGETS + * | shortcut string list * | IF FLAG_IS_TERMINAL && FLAG_HAS_BIGRAMS * | bigrams address list * @@ -85,7 +89,7 @@ public class BinaryDictInputOutput { * the BMP. Also everything in the iso-latin-1 charset is only 1 byte, except control * characters which should never happen anyway (and still work, but take 3 bytes). * - * bigram and shortcut address list is: + * bigram address list is: * <flags> = | hasNext = 1 bit, 1 = yes, 0 = no : FLAG_ATTRIBUTE_HAS_NEXT * | addressSign = 1 bit, : FLAG_ATTRIBUTE_OFFSET_NEGATIVE * | 1 = must take -address, 0 = must take +address @@ -103,13 +107,25 @@ public class BinaryDictInputOutput { * | read 3 bytes, add top 4 bits * | END * | if (FLAG_ATTRIBUTE_OFFSET_NEGATIVE) then address = -address - * if (FLAG_ATTRIBUTE_HAS_NET) goto bigram_and_shortcut_address_list_is + * if (FLAG_ATTRIBUTE_HAS_NEXT) goto bigram_and_shortcut_address_list_is * + * shortcut string list is: + * <byte size> = GROUP_SHORTCUT_LIST_SIZE_SIZE bytes, big-endian: size of the list, in bytes. + * <flags> = | hasNext = 1 bit, 1 = yes, 0 = no : FLAG_ATTRIBUTE_HAS_NEXT + * | reserved = 3 bits, must be 0 + * | 4 bits : frequency : mask with FLAG_ATTRIBUTE_FREQUENCY + * <shortcut> = | string of characters at the char format described above, with the terminator + * | used to signal the end of the string. + * if (FLAG_ATTRIBUTE_HAS_NEXT goto flags */ - 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,6 +142,7 @@ 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_ATTRIBUTE_HAS_NEXT = 0x80; @@ -138,20 +155,19 @@ 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; private static final int GROUP_MAX_ADDRESS_SIZE = 3; private static final int GROUP_ATTRIBUTE_FLAGS_SIZE = 1; private static final int GROUP_ATTRIBUTE_MAX_ADDRESS_SIZE = 3; + private static final int GROUP_SHORTCUT_LIST_SIZE_SIZE = 2; 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; @@ -207,25 +223,66 @@ public class BinaryDictInputOutput { /** * Writes a char array to a byte buffer. * - * @param characters the character array to write. + * @param codePoints the code point array to write. * @param buffer the byte buffer to write to. * @param index the index in buffer to write the character array to. * @return the index after the last character. */ - private static int writeCharArray(int[] characters, byte[] buffer, int index) { - for (int character : characters) { - if (1 == getCharSize(character)) { - buffer[index++] = (byte)character; + private static int writeCharArray(final int[] codePoints, final byte[] buffer, int index) { + for (int codePoint : codePoints) { + if (1 == getCharSize(codePoint)) { + buffer[index++] = (byte)codePoint; } else { - buffer[index++] = (byte)(0xFF & (character >> 16)); - buffer[index++] = (byte)(0xFF & (character >> 8)); - buffer[index++] = (byte)(0xFF & character); + buffer[index++] = (byte)(0xFF & (codePoint >> 16)); + buffer[index++] = (byte)(0xFF & (codePoint >> 8)); + buffer[index++] = (byte)(0xFF & codePoint); } } return index; } /** + * Writes a string with our character format to a byte buffer. + * + * This will also write the terminator byte. + * + * @param buffer the byte buffer to write to. + * @param origin the offset to write from. + * @param word the string to write. + * @return the size written, in bytes. + */ + private static int writeString(final byte[] buffer, final int origin, + final String word) { + final int length = word.length(); + int index = origin; + for (int i = 0; i < length; i = word.offsetByCodePoints(i, 1)) { + final int codePoint = word.codePointAt(i); + if (1 == getCharSize(codePoint)) { + buffer[index++] = (byte)codePoint; + } else { + buffer[index++] = (byte)(0xFF & (codePoint >> 16)); + buffer[index++] = (byte)(0xFF & (codePoint >> 8)); + buffer[index++] = (byte)(0xFF & codePoint); + } + } + buffer[index++] = GROUP_CHARACTERS_TERMINATOR; + return index - origin; + } + + /** + * Reads a string from a RandomAccessFile. This is the converse of the above method. + */ + private static String readString(final RandomAccessFile source) throws IOException { + final StringBuilder s = new StringBuilder(); + int character = readChar(source); + while (character != INVALID_CHARACTER) { + s.appendCodePoint(character); + character = readChar(source); + } + return s.toString(); + } + + /** * Reads a character from the file. * * This follows the character format documented earlier in this source file. @@ -261,6 +318,61 @@ 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 size of a shortcut in bytes. + */ + private static int getShortcutSize(final WeightedString shortcut) { + int size = GROUP_ATTRIBUTE_FLAGS_SIZE; + final String word = shortcut.mWord; + final int length = word.length(); + for (int i = 0; i < length; i = word.offsetByCodePoints(i, 1)) { + final int codePoint = word.codePointAt(i); + size += CharEncoding.getCharSize(codePoint); + } + size += GROUP_TERMINATOR_SIZE; + return size; + } + + /** + * Compute the size of a shortcut list in bytes. + * + * This is known in advance and does not change according to position in the file + * like address lists do. + */ + private static int getShortcutListSize(final ArrayList<WeightedString> shortcutList) { + if (null == shortcutList) return 0; + int size = GROUP_SHORTCUT_LIST_SIZE_SIZE; + for (final WeightedString shortcut : shortcutList) { + size += getShortcutSize(shortcut); + } + return 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 +383,10 @@ 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 + size += getShortcutListSize(group.mShortcutTargets); 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 +398,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; @@ -378,7 +490,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 +499,7 @@ public class BinaryDictInputOutput { final int offset = group.mChildren.mCachedAddress - offsetBasePoint; groupSize += getByteSize(offset); } + groupSize += getShortcutListSize(group.mShortcutTargets); if (null != group.mBigrams) { for (WeightedString bigram : group.mBigrams) { final int offsetBasePoint = groupSize + node.mCachedAddress + size @@ -412,12 +525,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; @@ -502,7 +616,7 @@ public class BinaryDictInputOutput { * @param address the address to write. * @return the size in bytes the address actually took. */ - private static int writeVariableAddress(byte[] buffer, int index, int address) { + private static int writeVariableAddress(final byte[] buffer, int index, final int address) { switch (getByteSize(address)) { case 1: buffer[index++] = (byte)address; @@ -545,7 +659,18 @@ 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; + } return flags; } @@ -579,6 +704,17 @@ public class BinaryDictInputOutput { } /** + * Makes the flag value for a shortcut. + * + * @param more whether there are more attributes after this one. + * @param frequency the frequency of the attribute, 0..15 + * @return the flags + */ + private static final int makeShortcutFlags(final boolean more, final int frequency) { + return (more ? FLAG_ATTRIBUTE_HAS_NEXT : 0) + (frequency & FLAG_ATTRIBUTE_FREQUENCY); + } + + /** * Write a node to memory. The node is expected to have its final position cached. * * This can be an empty map, but the more is inside the faster the lookups will be. It can @@ -592,16 +728,24 @@ 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"); + + "the same as the cached address of the group : " + + index + " <> " + group.mCachedAddress); groupAddress += GROUP_FLAGS_SIZE + getGroupCharactersSize(group); // Sanity checks. if (group.mFrequency > MAX_TERMINAL_FREQUENCY) { @@ -624,20 +768,43 @@ public class BinaryDictInputOutput { index += shift; groupAddress += shift; + // Write shortcuts + if (null != group.mShortcutTargets) { + final int indexOfShortcutByteSize = index; + index += GROUP_SHORTCUT_LIST_SIZE_SIZE; + groupAddress += GROUP_SHORTCUT_LIST_SIZE_SIZE; + final Iterator shortcutIterator = group.mShortcutTargets.iterator(); + while (shortcutIterator.hasNext()) { + final WeightedString target = (WeightedString)shortcutIterator.next(); + ++groupAddress; + int shortcutFlags = makeShortcutFlags(shortcutIterator.hasNext(), + target.mFrequency); + buffer[index++] = (byte)shortcutFlags; + final int shortcutShift = CharEncoding.writeString(buffer, index, target.mWord); + index += shortcutShift; + groupAddress += shortcutShift; + } + final int shortcutByteSize = index - indexOfShortcutByteSize; + if (shortcutByteSize > 0xFFFF) { + throw new RuntimeException("Shortcut list too large"); + } + buffer[indexOfShortcutByteSize] = (byte)(shortcutByteSize >> 8); + buffer[indexOfShortcutByteSize + 1] = (byte)(shortcutByteSize & 0xFF); + } // 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 +878,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 +894,49 @@ 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); + if (version >= FIRST_VERSION_WITH_HEADER_SIZE) { + final int headerSizeOffset = index; + index += 4; // Size of the header size + + // Write out the options. + for (final String key : dict.mOptions.mAttributes.keySet()) { + final String value = dict.mOptions.mAttributes.get(key); + index += CharEncoding.writeString(buffer, index, key); + index += CharEncoding.writeString(buffer, index, value); + } - // Should we include the locale and title of the dictionary ? + // 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 +1016,26 @@ public class BinaryDictInputOutput { childrenAddress = NO_CHILDREN_ADDRESS; break; } + ArrayList<WeightedString> shortcutTargets = null; + if (0 != (flags & FLAG_HAS_SHORTCUT_TARGETS)) { + final long pointerBefore = source.getFilePointer(); + shortcutTargets = new ArrayList<WeightedString>(); + source.readUnsignedShort(); // Skip the size + while (true) { + final int targetFlags = source.readUnsignedByte(); + final String word = CharEncoding.readString(source); + shortcutTargets.add(new WeightedString(word, + targetFlags & FLAG_ATTRIBUTE_FREQUENCY)); + if (0 == (targetFlags & FLAG_ATTRIBUTE_HAS_NEXT)) break; + } + addressPointer += (source.getFilePointer() - pointerBefore); + } 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 +1054,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 +1091,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 +1148,12 @@ 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 = info.mShortcutTargets; ArrayList<WeightedString> bigrams = null; if (null != info.mBigrams) { bigrams = new ArrayList<WeightedString>(); @@ -942,11 +1171,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, false)); } else { nodeContents.add( - new CharGroup(info.mCharacters, bigrams, info.mFrequency)); + new CharGroup(info.mCharacters, shortcutTargets, bigrams, info.mFrequency, + false)); } groupOffset = info.mEndAddress; } @@ -957,6 +1187,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 +1208,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,16 +1221,30 @@ public class BinaryDictInputOutput { // Read options source.readUnsignedShort(); - long headerSize = source.getFilePointer(); + final long headerSize; + final HashMap<String, String> options = new HashMap<String, String>(); + if (version < FIRST_VERSION_WITH_HEADER_SIZE) { + headerSize = source.getFilePointer(); + } else { + headerSize = (source.readUnsignedByte() << 24) + (source.readUnsignedByte() << 16) + + (source.readUnsignedByte() << 8) + source.readUnsignedByte(); + while (source.getFilePointer() < headerSize) { + final String key = CharEncoding.readString(source); + final String value = CharEncoding.readString(source); + options.put(key, value); + } + 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); FusionDictionary newDict = new FusionDictionary(root, - new FusionDictionary.DictionaryOptions()); + new FusionDictionary.DictionaryOptions(options)); 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 +1259,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/java/src/com/android/inputmethod/latin/makedict/CharGroupInfo.java index 6badfd13a..ef7dbb251 100644 --- a/tools/makedict/src/com/android/inputmethod/latin/CharGroupInfo.java +++ b/java/src/com/android/inputmethod/latin/makedict/CharGroupInfo.java @@ -14,7 +14,9 @@ * the License. */ -package com.android.inputmethod.latin; +package com.android.inputmethod.latin.makedict; + +import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString; import java.util.ArrayList; @@ -29,10 +31,12 @@ public class CharGroupInfo { public final int[] mCharacters; public final int mFrequency; public final int mChildrenAddress; + public final ArrayList<WeightedString> 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<WeightedString> shortcutTargets, final ArrayList<PendingAttribute> bigrams) { mOriginalAddress = originalAddress; mEndAddress = endAddress; @@ -40,6 +44,7 @@ public class CharGroupInfo { mCharacters = characters; mFrequency = frequency; mChildrenAddress = childrenAddress; + mShortcutTargets = shortcutTargets; mBigrams = bigrams; } } diff --git a/tools/makedict/src/com/android/inputmethod/latin/FusionDictionary.java b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java index f6220eea2..99b17048d 100644 --- a/tools/makedict/src/com/android/inputmethod/latin/FusionDictionary.java +++ b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java @@ -14,14 +14,14 @@ * the License. */ -package com.android.inputmethod.latin; +package com.android.inputmethod.latin.makedict; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; -import java.util.List; /** * A dictionary that can fusion heads and tails of words for more compression. @@ -60,15 +60,28 @@ public class FusionDictionary implements Iterable<Word> { */ public static class WeightedString { final String mWord; - final int mFrequency; + int mFrequency; public WeightedString(String word, int frequency) { mWord = word; mFrequency = frequency; } + + @Override + public int hashCode() { + return Arrays.hashCode(new Object[] { mWord, mFrequency }); + } + + @Override + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof WeightedString)) return false; + WeightedString w = (WeightedString)o; + return mWord.equals(w.mWord) && mFrequency == w.mFrequency; + } } /** - * 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 +95,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> mBigrams; - final int mFrequency; // NOT_A_TERMINAL == mFrequency indicates this is not a terminal. + ArrayList<WeightedString> mShortcutTargets; + ArrayList<WeightedString> mBigrams; + int mFrequency; // NOT_A_TERMINAL == mFrequency indicates this is not a terminal. + 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; } @@ -120,6 +147,102 @@ public class FusionDictionary implements Iterable<Word> { assert(mChars.length > 0); return 1 < mChars.length; } + + /** + * Adds a word to the bigram list. Updates the frequency if the word already + * exists. + */ + public void addBigram(final String word, final int frequency) { + if (mBigrams == null) { + mBigrams = new ArrayList<WeightedString>(); + } + WeightedString bigram = getBigram(word); + if (bigram != null) { + bigram.mFrequency = frequency; + } else { + bigram = new WeightedString(word, frequency); + mBigrams.add(bigram); + } + } + + /** + * Gets the shortcut target for the given word. Returns null if the word is not in the + * shortcut list. + */ + public WeightedString getShortcut(final String word) { + if (mShortcutTargets != null) { + final int size = mShortcutTargets.size(); + for (int i = 0; i < size; ++i) { + WeightedString shortcut = mShortcutTargets.get(i); + if (shortcut.mWord.equals(word)) { + return shortcut; + } + } + } + return null; + } + + /** + * Gets the bigram for the given word. + * Returns null if the word is not in the bigrams list. + */ + public WeightedString getBigram(final String word) { + if (mBigrams != null) { + final int size = mBigrams.size(); + for (int i = 0; i < size; ++i) { + WeightedString bigram = mBigrams.get(i); + if (bigram.mWord.equals(word)) { + return bigram; + } + } + } + return null; + } + + /** + * Updates the CharGroup with the given properties. Adds the shortcut and bigram lists to + * the existing ones if any. Note: unigram, bigram, and shortcut frequencies are only + * updated if they are higher than the existing ones. + */ + public void update(int frequency, ArrayList<WeightedString> shortcutTargets, + ArrayList<WeightedString> bigrams, boolean isShortcutOnly) { + if (frequency > mFrequency) { + mFrequency = frequency; + } + if (shortcutTargets != null) { + if (mShortcutTargets == null) { + mShortcutTargets = shortcutTargets; + } else { + final int size = shortcutTargets.size(); + for (int i = 0; i < size; ++i) { + final WeightedString shortcut = shortcutTargets.get(i); + final WeightedString existingShortcut = getShortcut(shortcut.mWord); + if (existingShortcut == null) { + mShortcutTargets.add(shortcut); + } else if (existingShortcut.mFrequency < shortcut.mFrequency) { + existingShortcut.mFrequency = shortcut.mFrequency; + } + } + } + } + if (bigrams != null) { + if (mBigrams == null) { + mBigrams = bigrams; + } else { + final int size = bigrams.size(); + for (int i = 0; i < size; ++i) { + final WeightedString bigram = bigrams.get(i); + final WeightedString existingBigram = getBigram(bigram.mWord); + if (existingBigram == null) { + mBigrams.add(bigram); + } else if (existingBigram.mFrequency < bigram.mFrequency) { + existingBigram.mFrequency = bigram.mFrequency; + } + } + } + } + mIsShortcutOnly = isShortcutOnly; + } } /** @@ -128,6 +251,10 @@ public class FusionDictionary implements Iterable<Word> { * There are no options at the moment, so this class is empty. */ public static class DictionaryOptions { + final HashMap<String, String> mAttributes; + public DictionaryOptions(final HashMap<String, String> attributes) { + mAttributes = attributes; + } } @@ -135,8 +262,13 @@ public class FusionDictionary implements Iterable<Word> { public final Node mRoot; public FusionDictionary() { - mOptions = new DictionaryOptions(); mRoot = new Node(); + mOptions = new DictionaryOptions(new HashMap<String, String>()); + } + + public FusionDictionary(final HashMap<String, String> attributes) { + mRoot = new Node(); + mOptions = new DictionaryOptions(attributes); } public FusionDictionary(final Node root, final DictionaryOptions options) { @@ -144,19 +276,41 @@ public class FusionDictionary implements Iterable<Word> { mOptions = options; } + public void addOptionAttribute(final String key, final String value) { + mOptions.mAttributes.put(key, value); + } + /** * Helper method to convert a String to an int array. */ 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 +319,16 @@ 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 != 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 +350,57 @@ 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"); + } + add(getCodePoints(word), frequency, shortcutTargets, null, true /* isShortcutOnly */); + } + + /** + * Helper method to add a new bigram to the dictionary. + * + * @param word1 the previous word of the context + * @param word2 the next word of the context + * @param frequency the bigram frequency + */ + public void setBigram(final String word1, final String word2, final int frequency) { + CharGroup charGroup = findWordInTree(mRoot, word1); + if (charGroup != null) { + final CharGroup charGroup2 = findWordInTree(mRoot, word2); + if (charGroup2 == null) { + // TODO: refactor with the identical code in addNeutralWords + add(getCodePoints(word2), 0, null, null, false /* isShortcutOnly */); + } + charGroup.addBigram(word2, frequency); + } else { + throw new RuntimeException("First word of bigram not found"); + } + } + + /** * 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 +424,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 { @@ -239,60 +433,50 @@ public class FusionDictionary implements Iterable<Word> { if (differentCharIndex == currentGroup.mChars.length) { if (charIndex + differentCharIndex >= word.length) { // The new word is a prefix of an existing word, but the node on which it - // should end already exists as is. - if (currentGroup.mFrequency > 0) { - throw new RuntimeException("Such a word already exists in the dictionary : " - + new String(word, 0, word.length)); - } else { - final CharGroup newNode = new CharGroup(currentGroup.mChars, - bigrams, frequency, currentGroup.mChildren); - currentNode.mData.set(nodeIndex, newNode); - checkStack(currentNode); - } + // should end already exists as is. Since the old CharNode was not a terminal, + // make it one by filling in its frequency and other attributes + currentGroup.update(frequency, shortcutTargets, bigrams, isShortcutOnly); } else { // The new word matches the full old word and extends past it. // 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. - if (0 != frequency) { - if (0 < currentGroup.mFrequency) { - throw new RuntimeException("This word already exists with frequency " - + currentGroup.mFrequency + " : " - + new String(word, 0, word.length)); - } - final CharGroup newGroup = new CharGroup(word, - currentGroup.mBigrams, frequency, currentGroup.mChildren); - currentNode.mData.set(nodeIndex, newGroup); - } + // Exact same word. Update the frequency if higher. This will also add the + // new bigrams to the existing bigram list if it already exists. + currentGroup.update(frequency, shortcutTargets, bigrams, isShortcutOnly); } else { // Partial prefix match only. We have to replace the current node with a node // containing the current prefix and create two new ones for the tails. 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); @@ -337,16 +521,11 @@ public class FusionDictionary implements Iterable<Word> { * is ignored. * This comparator imposes orderings that are inconsistent with equals. */ - static private class CharGroupComparator implements java.util.Comparator { - public int compare(Object o1, Object o2) { - final CharGroup c1 = (CharGroup)o1; - final CharGroup c2 = (CharGroup)o2; + static private class CharGroupComparator implements java.util.Comparator<CharGroup> { + public int compare(CharGroup c1, CharGroup c2) { if (c1.mChars[0] == c2.mChars[0]) return 0; return c1.mChars[0] < c2.mChars[0] ? -1 : 1; } - public boolean equals(Object o) { - return o instanceof CharGroupComparator; - } } final static private CharGroupComparator CHARGROUP_COMPARATOR = new CharGroupComparator(); @@ -354,8 +533,9 @@ public class FusionDictionary implements Iterable<Word> { * Finds the insertion index of a character within a node. */ 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 ArrayList<CharGroup> data = node.mData; + 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 +579,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 +763,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/MakedictLog.java b/java/src/com/android/inputmethod/latin/makedict/MakedictLog.java index badb2ff3d..cff8d6fd0 100644 --- a/tools/makedict/src/com/android/inputmethod/latin/MakedictLog.java +++ b/java/src/com/android/inputmethod/latin/makedict/MakedictLog.java @@ -14,7 +14,7 @@ * the License. */ -package com.android.inputmethod.latin; +package com.android.inputmethod.latin.makedict; /** * Wrapper to redirect log events to the right output medium. diff --git a/tools/makedict/src/com/android/inputmethod/latin/PendingAttribute.java b/java/src/com/android/inputmethod/latin/makedict/PendingAttribute.java index e50202184..5b41d27f2 100644 --- a/tools/makedict/src/com/android/inputmethod/latin/PendingAttribute.java +++ b/java/src/com/android/inputmethod/latin/makedict/PendingAttribute.java @@ -14,12 +14,12 @@ * the License. */ -package com.android.inputmethod.latin; +package com.android.inputmethod.latin.makedict; /** * 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/UnsupportedFormatException.java b/java/src/com/android/inputmethod/latin/makedict/UnsupportedFormatException.java index 511ad5675..bd42fb8fa 100644 --- a/tools/makedict/src/com/android/inputmethod/latin/UnsupportedFormatException.java +++ b/java/src/com/android/inputmethod/latin/makedict/UnsupportedFormatException.java @@ -14,7 +14,7 @@ * the License. */ -package com.android.inputmethod.latin; +package com.android.inputmethod.latin.makedict; /** * Simple exception thrown when a file format is not recognized. diff --git a/tools/makedict/src/com/android/inputmethod/latin/Word.java b/java/src/com/android/inputmethod/latin/makedict/Word.java index 916165a41..4e0ab1049 100644 --- a/tools/makedict/src/com/android/inputmethod/latin/Word.java +++ b/java/src/com/android/inputmethod/latin/makedict/Word.java @@ -14,11 +14,12 @@ * the License. */ -package com.android.inputmethod.latin; +package com.android.inputmethod.latin.makedict; -import com.android.inputmethod.latin.FusionDictionary.WeightedString; +import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString; import java.util.ArrayList; +import java.util.Arrays; /** * Utility class for a word with a frequency. @@ -28,12 +29,30 @@ 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) { + private int mHashCode = 0; + + 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; + } + + private static int computeHashCode(Word word) { + return Arrays.hashCode(new Object[] { + word.mWord, + word.mFrequency, + word.mIsShortcutOnly, + word.mShortcutTargets.hashCode(), + word.mBigrams.hashCode() + }); } /** @@ -57,9 +76,20 @@ public class Word implements Comparable<Word> { */ @Override public boolean equals(Object o) { + if (o == this) return true; if (!(o instanceof Word)) return false; Word w = (Word)o; return mFrequency == w.mFrequency && mWord.equals(w.mWord) + && mIsShortcutOnly == w.mIsShortcutOnly + && mShortcutTargets.equals(w.mShortcutTargets) && mBigrams.equals(w.mBigrams); } + + @Override + public int hashCode() { + if (mHashCode == 0) { + mHashCode = computeHashCode(this); + } + return mHashCode; + } } diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java index 095c2c51c..7b13e40c2 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java @@ -17,33 +17,37 @@ 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; 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 +55,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 +89,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 +202,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 +214,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 +224,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,8 +235,8 @@ public class AndroidSpellCheckerService extends SpellCheckerService { @Override synchronized public boolean addWord(char[] word, int wordOffset, int wordLength, int score, - int dicTypeId, DataType dataType) { - final int positionIndex = ArraysCompatUtils.binarySearch(mScores, 0, mLength, score); + int dicTypeId, int dataType) { + final int positionIndex = Arrays.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. final int insertIndex = positionIndex >= 0 ? positionIndex : -positionIndex - 1; @@ -175,7 +268,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 +291,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 +315,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 +325,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,21 +336,27 @@ 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); } } @Override public boolean onUnbind(final Intent intent) { + closeAllDictionaries(); + return false; + } + + private void closeAllDictionaries() { final Map<String, DictionaryPool> oldPools = mDictionaryPools; mDictionaryPools = Collections.synchronizedMap(new TreeMap<String, DictionaryPool>()); final Map<String, Dictionary> oldUserDictionaries = mUserDictionaries; @@ -273,15 +372,16 @@ 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; } private DictionaryPool getDictionaryPool(final String locale) { @@ -295,9 +395,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 +416,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 +434,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 +453,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 +467,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 +519,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 +550,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 +568,21 @@ 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 }; + for (int i = 0; i < length; i = text.offsetByCodePoints(i, 1)) { + final int codePoint = text.codePointAt(i); + // The getXYForCodePointAndScript method returns (Y << 16) + X + final int xy = SpellCheckerProximityInfo.getXYForCodePointAndScript( + codePoint, mScript); + if (SpellCheckerProximityInfo.NOT_A_COORDINATE_PAIR == xy) { + composer.add(codePoint, WordComposer.NOT_A_COORDINATE, + WordComposer.NOT_A_COORDINATE, null); } else { - proximities = Arrays.copyOfRange(SpellCheckerProximityInfo.PROXIMITY, - proximityIndex, - proximityIndex + SpellCheckerProximityInfo.ROW_SIZE); + composer.add(codePoint, xy & 0xFFFF, xy >> 16, null); } - composer.add(character, proximities, - WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE); } final int capitalizeType = getCapitalizationType(text); @@ -475,7 +616,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 +624,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..0103e8423 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java @@ -22,72 +22,193 @@ 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>(); - - // 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, - - '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, - - '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); + // The number of keys in a row of the grid used by the spell checker. + final public static int PROXIMITY_GRID_WIDTH = 11; + // The number of rows in the grid used by the spell checker. + final public static int PROXIMITY_GRID_HEIGHT = 3; + + final private static int NOT_AN_INDEX = -1; + final public static int NOT_A_COORDINATE_PAIR = -1; + + // 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 / ROW_SIZE); } } - public static int getIndexOf(int characterCode) { - final Integer result = INDICES.get(characterCode); - if (null == result) return -1; + final protected static int computeIndex(final int characterCode, + final TreeMap<Integer, Integer> indices) { + final Integer result = indices.get(characterCode); + if (null == result) return NOT_AN_INDEX; return result; } + + 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>(); + + // 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 = { + // Proximity for row 1. This must have exactly ROW_SIZE entries for each letter, + // and exactly PROXIMITY_GRID_WIDTH letters for a row. Pad with NUL's. + // The number of rows must be exactly PROXIMITY_GRID_HEIGHT. + '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, + + // Proximity for row 2. See comment above about size. + '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', NUL, 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, + + // Proximity for row 3. See comment above about size. + '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); + } + } + + private static class Cyrillic { + final private static TreeMap<Integer, Integer> INDICES = new TreeMap<Integer, Integer>(); + // TODO: The following table is solely based on the keyboard layout. Consult with Russian + // speakers on commonly misspelled words/letters. + final static int[] PROXIMITY = { + // Proximity for row 1. This must have exactly ROW_SIZE entries for each letter, + // and exactly PROXIMITY_GRID_WIDTH letters for a row. Pad with NUL's. + // The number of rows must be exactly PROXIMITY_GRID_HEIGHT. + 'й', 'ц', 'ф', 'ы', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'ц', 'й', 'ф', 'ы', 'в', 'у', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'у', 'ц', 'ы', 'в', 'а', 'к', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'к', 'у', 'в', 'а', 'п', 'е', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'е', 'к', 'а', 'п', 'р', 'н', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'н', 'е', 'п', 'р', 'о', 'г', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'г', 'н', 'р', 'о', 'л', 'ш', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'ш', 'г', 'о', 'л', 'д', 'щ', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'щ', 'ш', 'л', 'д', 'ж', 'з', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'з', 'щ', 'д', 'ж', 'э', 'х', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'х', 'з', 'ж', 'э', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + + // Proximity for row 2. See comment above about size. + 'ф', 'й', 'ц', 'ы', 'я', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'ы', 'й', 'ц', 'у', 'ф', 'в', 'я', 'ч', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'в', 'ц', 'у', 'к', 'ы', 'а', 'я', 'ч', 'с', NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'а', 'у', 'к', 'е', 'в', 'п', 'ч', 'с', 'м', NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'п', 'к', 'е', 'н', 'а', 'р', 'с', 'м', 'и', NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'р', 'е', 'н', 'г', 'п', 'о', 'м', 'и', 'т', NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'о', 'н', 'г', 'ш', 'р', 'л', 'и', 'т', 'ь', NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'л', 'г', 'ш', 'щ', 'о', 'д', 'т', 'ь', 'б', NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'д', 'ш', 'щ', 'з', 'л', 'ж', 'ь', 'б', 'ю', NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'ж', 'щ', 'з', 'х', 'д', 'э', 'б', 'ю', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'э', 'з', 'х', 'ю', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + + // Proximity for row 3. See comment above about size. + 'я', 'ф', 'ы', 'в', 'ч', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'ч', 'ы', 'в', 'а', 'я', 'с', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'с', 'в', 'а', 'п', 'ч', 'м', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'м', 'а', 'п', 'р', 'с', 'и', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'и', 'п', 'р', 'о', 'м', 'т', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'т', 'р', 'о', 'л', 'и', 'ь', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'ь', 'о', 'л', 'д', 'т', 'б', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'б', 'л', 'д', 'ж', 'ь', 'ю', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + 'ю', 'д', 'ж', 'э', 'б', NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, + NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, 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); + } + } + + private static int getIndexOfCodeForScript(final int codePoint, final int script) { + switch (script) { + case AndroidSpellCheckerService.SCRIPT_LATIN: + return Latin.getIndexOf(codePoint); + case AndroidSpellCheckerService.SCRIPT_CYRILLIC: + return Cyrillic.getIndexOf(codePoint); + default: + throw new RuntimeException("Wrong script supplied: " + script); + } + } + + // Returns (Y << 16) + X to avoid creating a temporary object. This is okay because + // X and Y are limited to PROXIMITY_GRID_WIDTH resp. PROXIMITY_GRID_HEIGHT which is very + // inferior to 1 << 16 + // As an exception, this returns NOT_A_COORDINATE_PAIR if the key is not on the grid + public static int getXYForCodePointAndScript(final int codePoint, final int script) { + final int index = getIndexOfCodeForScript(codePoint, script); + if (NOT_AN_INDEX == index) return NOT_A_COORDINATE_PAIR; + final int y = index / PROXIMITY_GRID_WIDTH; + final int x = index % PROXIMITY_GRID_WIDTH; + if (y > PROXIMITY_GRID_HEIGHT) { + // Safety check, should be entirely useless + throw new RuntimeException("Wrong y coordinate in spell checker proximity"); + } + return (y << 16) + x; + } } diff --git a/java/src/com/android/inputmethod/latin/MoreSuggestions.java b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java index 9a59ef2e0..dd83a0c4e 100644 --- a/java/src/com/android/inputmethod/latin/MoreSuggestions.java +++ b/java/src/com/android/inputmethod/latin/suggestions/MoreSuggestions.java @@ -14,37 +14,34 @@ * 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.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 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]; @@ -55,25 +52,24 @@ public class MoreSuggestions extends Keyboard { public int mDividerWidth; public int layout(SuggestedWords suggestions, int fromPos, int maxWidth, int minWidth, - int maxRow, KeyboardView view) { + int maxRow, MoreSuggestionsView view) { clearKeys(); - final Paint paint = new Paint(); - 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( R.dimen.more_suggestions_key_horizontal_padding); + final Paint paint = view.newDefaultLabelPaint(); int row = 0; 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; + mWidths[pos] = (int)view.getLabelWidth(word, paint) + padding; final int numColumn = pos - rowStartPos + 1; final int columnWidth = (maxWidth - mDividerWidth * (numColumn - 1)) / numColumn; @@ -176,9 +172,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 +185,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 +208,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 c61dd6313..e64e7a685 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 @@ -42,30 +43,30 @@ import com.android.inputmethod.keyboard.PointerTracker.TimerProxy; public class MoreSuggestionsView extends KeyboardView implements MoreKeysPanel { private final int[] mCoordinates = new int[2]; - private final KeyDetector mModalPanelKeyDetector; + final KeyDetector mModalPanelKeyDetector; private final KeyDetector mSlidingPanelKeyDetector; private Controller mController; - private KeyboardActionListener mListener; + KeyboardActionListener mListener; private int mOriginX; private int mOriginY; - private static final TimerProxy EMPTY_TIMER_PROXY = new TimerProxy.Adapter(); + static final TimerProxy EMPTY_TIMER_PROXY = new TimerProxy.Adapter(); - private final KeyboardActionListener mSuggestionsPaneListener = + 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,43 +141,28 @@ 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; mListener = listener; final View container = (View)getParent(); final MoreSuggestions pane = (MoreSuggestions)getKeyboard(); - - parentView.getLocationInWindow(mCoordinates); - final int paneLeft = pointX - (pane.mOccupiedWidth / 2) + parentView.getPaddingLeft(); - final int x = wrapUp(Math.max(0, Math.min(paneLeft, - parentView.getWidth() - pane.mOccupiedWidth)) - - container.getPaddingLeft() + mCoordinates[0], - container.getMeasuredWidth(), 0, parentView.getWidth()); - final int y = pointY - - (container.getMeasuredHeight() - container.getPaddingBottom()) - + parentView.getPaddingTop() + mCoordinates[1]; + final int defaultCoordX = pane.mOccupiedWidth / 2; + // The coordinates of panel's left-top corner in parentView's coordinate system. + final int x = pointX - defaultCoordX - container.getPaddingLeft() + + parentView.getPaddingLeft(); + final int y = pointY - container.getMeasuredHeight() + container.getPaddingBottom() + + parentView.getPaddingTop(); window.setContentView(container); window.setWidth(container.getMeasuredWidth()); window.setHeight(container.getMeasuredHeight()); - window.showAtLocation(parentView, Gravity.NO_GRAVITY, x, y); - - mOriginX = x + container.getPaddingLeft() - mCoordinates[0]; - mOriginY = y + container.getPaddingTop() - mCoordinates[1]; - } + parentView.getLocationInWindow(mCoordinates); + window.showAtLocation(parentView, Gravity.NO_GRAVITY, + x + mCoordinates[0], y + mCoordinates[1]); - private static int wrapUp(int x, int width, int left, int right) { - if (x < left) - return left; - if (x + width > right) - return right - width; - return x; + mOriginX = x + container.getPaddingLeft(); + mOriginY = y + container.getPaddingTop(); } private boolean mIsDismissing; diff --git a/java/src/com/android/inputmethod/latin/SuggestionsView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionsView.java index 0986a0b27..1ad37b933 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; @@ -53,15 +52,19 @@ import android.widget.PopupWindow; import android.widget.RelativeLayout; import android.widget.TextView; -import com.android.inputmethod.compat.FrameLayoutCompatUtils; 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.SuggestedWords.SuggestedWordInfo; +import com.android.inputmethod.keyboard.ViewLayoutUtils; +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.Utils; import java.util.ArrayList; -import java.util.List; public class SuggestionsView extends RelativeLayout implements OnClickListener, OnLongClickListener { @@ -73,7 +76,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 +94,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 +104,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 +118,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); } @@ -146,10 +142,11 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, public final float mMinMoreSuggestionsWidth; public final int mMoreSuggestionsBottomGap; - private final List<TextView> mWords; - private final List<View> mDividers; - private final List<TextView> mInfos; + private final ArrayList<TextView> mWords; + private final ArrayList<View> mDividers; + private final ArrayList<TextView> mInfos; + private final int mColorValidTypedWord; private final int mColorTypedWord; private final int mColorAutoCorrect; private final int mColorSuggested; @@ -158,6 +155,7 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, private final int mCenterSuggestionIndex; private final Drawable mMoreSuggestionsHint; private static final String MORE_SUGGESTIONS_HINT = "\u2026"; + private static final String LEFTWARDS_ARROW = "\u2190"; private static final CharacterStyle BOLD_SPAN = new StyleSpan(Typeface.BOLD); private static final CharacterStyle UNDERLINE_SPAN = new UnderlineSpan(); @@ -172,11 +170,11 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, public boolean mMoreSuggestionsAvailable; public final TextView mWordToSaveView; + private final TextView mLeftwardsArrowView; 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) { + ArrayList<TextView> words, ArrayList<View> dividers, ArrayList<TextView> infos) { mWords = words; mDividers = dividers; mInfos = infos; @@ -194,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, @@ -201,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( @@ -230,8 +233,8 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, 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); + mLeftwardsArrowView = (TextView)inflater.inflate(R.layout.hint_add_to_dictionary, null); + mHintToSaveView = (TextView)inflater.inflate(R.layout.hint_add_to_dictionary, null); } public int getMaxMoreSuggestionsRow() { @@ -281,10 +284,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; @@ -301,10 +304,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) { @@ -314,28 +317,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; @@ -354,19 +360,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); @@ -389,7 +395,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(); @@ -400,8 +406,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,7 +416,7 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, ViewGroup.LayoutParams.WRAP_CONTENT); final int infoWidth = info.getMeasuredWidth(); final int y = info.getMeasuredHeight(); - FrameLayoutCompatUtils.placeViewAt( + ViewLayoutUtils.placeViewAt( info, x - infoWidth, y, infoWidth, info.getMeasuredHeight()); } } @@ -433,11 +439,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++) { @@ -446,8 +452,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. @@ -456,8 +463,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); @@ -468,7 +475,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; @@ -484,16 +491,94 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, stripView.addView(mDividers.get(0)); + final TextView leftArrowView = mLeftwardsArrowView; + leftArrowView.setTextColor(mColorAutoCorrect); + leftArrowView.setText(LEFTWARDS_ARROW); + stripView.addView(leftArrowView); + final TextView hintView = mHintToSaveView; + hintView.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); hintView.setTextColor(mColorAutoCorrect); - final int hintWidth = width - wordWidth; - final float hintScaleX = getTextScaleX(mHintToSaveText, hintWidth, hintView.getPaint()); - hintView.setText(mHintToSaveText); + final int hintWidth = width - wordWidth - leftArrowView.getWidth(); + 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; + } + } } /** @@ -571,98 +656,13 @@ 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; - } - - 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; - } + mSuggestedWords = suggestedWords; + mParams.layout(mSuggestedWords, mSuggestionsStrip, this, getWidth()); } public int setMoreSuggestionsHeight(int remainingHeight) { @@ -674,9 +674,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() { @@ -688,7 +688,7 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener, } public SuggestedWords getSuggestions() { - return mSuggestions; + return mSuggestedWords; } public void clear() { @@ -702,34 +702,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 = @@ -737,7 +711,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; @@ -782,7 +756,7 @@ 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.getMaxMoreSuggestionsRow()); mMoreSuggestionsView.setKeyboard(builder.build()); @@ -859,8 +833,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; @@ -885,10 +858,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 f07be6abe..5053e7d64 100644 --- a/native/Android.mk +++ b/native/Android.mk @@ -1,60 +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 ($(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 := user - -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..5e0d3518d --- /dev/null +++ b/native/jni/Android.mk @@ -0,0 +1,138 @@ +# 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) + +############ some local flags +# If you change any of those flags, you need to rebuild both libjni_latinime_static +# and the shared library. +#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 + +###################################### +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)) + +ifeq ($(TARGETING_UNBUNDLED_FROYO), true) + LOCAL_NDK_VERSION := 4 + LOCAL_SDK_VERSION := 8 +endif + +ifeq ($(FLAG_DO_PROFILE), true) + $(warning Making profiling version of native library) + LOCAL_CFLAGS += -DFLAG_DO_PROFILE +else # FLAG_DO_PROFILE +ifeq ($(FLAG_DBG), true) + $(warning Making debug version of native library) + LOCAL_CFLAGS += -DFLAG_DBG +endif # FLAG_DBG +endif # FLAG_DO_PROFILE + +LOCAL_MODULE := libjni_latinime_static +LOCAL_MODULE_TAGS := optional + +ifdef HISTORICAL_NDK_VERSIONS_ROOT # In the platform build system +include external/stlport/libstlport.mk +else # In the NDK build system +LOCAL_C_INCLUDES += external/stlport/stlport bionic +endif + +include $(BUILD_STATIC_LIBRARY) + +###################################### +include $(CLEAR_VARS) + +# All code in LOCAL_WHOLE_STATIC_LIBRARIES will be built into this shared library. +LOCAL_WHOLE_STATIC_LIBRARIES := libjni_latinime_static + +ifdef HISTORICAL_NDK_VERSIONS_ROOT # In the platform build system +LOCAL_SHARED_LIBRARIES := libstlport +else # In the NDK build system +LOCAL_SHARED_LIBRARIES := libstlport_static +endif + +ifeq ($(FLAG_DO_PROFILE), true) + $(warning Making profiling version of native library) + LOCAL_SHARED_LIBRARIES += libcutils libutils +else # FLAG_DO_PROFILE +ifeq ($(FLAG_DBG), true) + $(warning Making debug version of native library) + LOCAL_SHARED_LIBRARIES += libcutils libutils +endif # FLAG_DBG +endif # FLAG_DO_PROFILE + +ifeq ($(TARGETING_UNBUNDLED_FROYO), true) + LOCAL_NDK_VERSION := 4 + LOCAL_SDK_VERSION := 8 +endif + +LOCAL_MODULE := libjni_latinime +LOCAL_MODULE_TAGS := optional + +ifdef HISTORICAL_NDK_VERSIONS_ROOT # In the platform build system +include external/stlport/libstlport.mk +endif + +include $(BUILD_SHARED_LIBRARY) + +#################### Clean up the tmp vars +LATIN_IME_CORE_SRC_FILES := +LATIN_IME_JNI_SRC_FILES := +LATIN_IME_SRC_DIR := +TARGETING_UNBUNDLED_FROYO := 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..20e44c2b0 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,74 @@ 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) { + jint typedLetterMultiplier, jint fullWordMultiplier, jint maxWordLength, jint maxWords) { 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 @@ -117,27 +118,27 @@ static jint latinime_BinaryDictionary_open(JNIEnv *env, jobject object, #endif // USE_MMAP_FOR_DICTIONARY } else { dictionary = new Dictionary(dictBuf, dictSize, fd, adjust, typedLetterMultiplier, - fullWordMultiplier, maxWordLength, maxWords, maxAlternatives); + fullWordMultiplier, maxWordLength, maxWords); } 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,21 +152,19 @@ 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) { + jcharArray outputArray, jintArray frequencyArray, jint maxWordLength, jint maxBigrams) { 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, - maxAlternatives); + inputArraySize, (unsigned short*) outputChars, frequencies, maxWordLength, maxBigrams); env->ReleaseCharArrayElements(prevWordArray, prevWord, JNI_ABORT); env->ReleaseIntArrayElements(inputArray, inputCodes, JNI_ABORT); @@ -175,19 +174,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 +227,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 +239,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;JJIIII)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[III)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/jni/src/additional_proximity_chars.cpp b/native/jni/src/additional_proximity_chars.cpp new file mode 100644 index 000000000..224f020f2 --- /dev/null +++ b/native/jni/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/jni/src/additional_proximity_chars.h b/native/jni/src/additional_proximity_chars.h new file mode 100644 index 000000000..e0ecc0e1d --- /dev/null +++ b/native/jni/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/jni/src/basechars.cpp index 3843e11c5..31f1e18a8 100644 --- a/native/src/basechars.h +++ b/native/jni/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/jni/src/bigram_dictionary.cpp index c340c6c1a..f7a3d3e60 100644 --- a/native/src/bigram_dictionary.cpp +++ b/native/jni/src/bigram_dictionary.cpp @@ -26,14 +26,14 @@ namespace latinime { BigramDictionary::BigramDictionary(const unsigned char *dict, int maxWordLength, - int maxAlternatives, const bool isLatestDictVersion, const bool hasBigram, + const bool isLatestDictVersion, const bool hasBigram, Dictionary *parentDictionary) - : DICT(dict + NEW_DICTIONARY_HEADER_SIZE), MAX_WORD_LENGTH(maxWordLength), - MAX_ALTERNATIVES(maxAlternatives), IS_LATEST_DICT_VERSION(isLatestDictVersion), + : DICT(dict), MAX_WORD_LENGTH(maxWordLength), + 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; } @@ -92,7 +92,6 @@ bool BigramDictionary::addWordBigram(unsigned short *word, int length, int frequ * bigramFreq: an array to output frequencies. * maxWordLength: the maximum size of a word. * maxBigrams: the maximum number of bigrams fitting in the bigramChars array. - * maxAlteratives: unused. * This method returns the number of bigrams this word has, for backward compatibility. * Note: this is not the number of bigrams output in the array, which is the number of * bigrams this word has WHOSE first letter also matches the letter the user typed. @@ -103,7 +102,7 @@ bool BigramDictionary::addWordBigram(unsigned short *word, int length, int frequ */ int BigramDictionary::getBigrams(unsigned short *prevWord, int prevWordLength, int *codes, int codesSize, unsigned short *bigramChars, int *bigramFreq, int maxWordLength, - int maxBigrams, int maxAlternatives) { + int maxBigrams) { // TODO: remove unused arguments, and refrain from storing stuff in members of this class // TODO: have "in" arguments before "out" ones, and make out args explicit in the name mBigramFreq = bigramFreq; @@ -134,11 +133,13 @@ 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); + if (addWordBigram(bigramBuffer, length, frequency)) { + ++bigramCount; + } } - ++bigramCount; } while (0 != (UnigramDictionary::FLAG_ATTRIBUTE_HAS_NEXT & bigramFlags)); return bigramCount; } @@ -149,8 +150,9 @@ bool BigramDictionary::checkFirstCharacter(unsigned short *word) { int *inputCodes = mInputCodes; int maxAlt = MAX_ALTERNATIVES; + const unsigned short firstBaseChar = toBaseLowerCase(*word); while (maxAlt > 0) { - if ((unsigned int) *inputCodes == (unsigned int) *word) { + if (toBaseLowerCase(*inputCodes) == firstBaseChar) { return true; } inputCodes++; diff --git a/native/src/bigram_dictionary.h b/native/jni/src/bigram_dictionary.h index c07458a38..8132fbc59 100644 --- a/native/src/bigram_dictionary.h +++ b/native/jni/src/bigram_dictionary.h @@ -21,14 +21,13 @@ namespace latinime { class Dictionary; class BigramDictionary { -public: - BigramDictionary(const unsigned char *dict, int maxWordLength, int maxAlternatives, + public: + BigramDictionary(const unsigned char *dict, int maxWordLength, 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); + unsigned short *outWords, int *frequencies, int maxWordLength, int maxBigrams); ~BigramDictionary(); -private: + private: bool addWordBigram(unsigned short *word, int length, int frequency); int getBigramAddress(int *pos, bool advance); int getBigramFreq(int *pos); @@ -39,7 +38,8 @@ private: const unsigned char *DICT; const int MAX_WORD_LENGTH; - const int MAX_ALTERNATIVES; + // TODO: Re-implement proximity correction for bigram correction + static const int MAX_ALTERNATIVES = 1; const bool IS_LATEST_DICT_VERSION; const bool HAS_BIGRAM; diff --git a/native/src/binary_format.h b/native/jni/src/binary_format.h index 6f65088db..ab033ad90 100644 --- a/native/src/binary_format.h +++ b/native/jni/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.cpp b/native/jni/src/char_utils.cpp index a31a0632c..a31a0632c 100644 --- a/native/src/char_utils.cpp +++ b/native/jni/src/char_utils.cpp diff --git a/native/jni/src/char_utils.h b/native/jni/src/char_utils.h new file mode 100644 index 000000000..607dc5195 --- /dev/null +++ b/native/jni/src/char_utils.h @@ -0,0 +1,65 @@ +/* + * 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. + */ + +#ifndef LATINIME_CHAR_UTILS_H +#define LATINIME_CHAR_UTILS_H + +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/jni/src/correction.cpp index 27dc40745..087219ed4 100644 --- a/native/src/correction.cpp +++ b/native/jni/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/jni/src/correction.h index d4e99f0ce..ee55c9604 100644 --- a/native/src/correction.h +++ b/native/jni/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/jni/src/correction_state.h index c04146e54..5b2cbd3a2 100644 --- a/native/src/correction_state.h +++ b/native/jni/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/jni/src/debug.h index 38b2f107a..b13052c95 100644 --- a/native/src/debug.h +++ b/native/jni/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/jni/src/defines.h index ef1beb92f..e882c3714 100644 --- a/native/src/defines.h +++ b/native/jni/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 NOT_A_INDEX -1 +#define ADDITIONAL_PROXIMITY_CHAR_DISTANCE_INFO -4 +#define NOT_AN_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 -// 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 +#define FIRST_WORD_INDEX 0 + +// TODO: Reduce this constant if possible; check the maximum number of digraphs in the same +// word in the dictionary for languages with digraphs, like German and French +#define DEFAULT_MAX_DIGRAPH_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/jni/src/dictionary.cpp index a49769bdb..981a983ee 100644 --- a/native/src/dictionary.cpp +++ b/native/jni/src/dictionary.cpp @@ -19,6 +19,7 @@ #define LOG_TAG "LatinIME: dictionary.cpp" +#include "binary_format.h" #include "dictionary.h" namespace latinime { @@ -26,33 +27,35 @@ namespace latinime { // TODO: Change the type of all keyCodes to uint32_t Dictionary::Dictionary(void *dict, int dictSize, int mmapFd, int dictBufAdjust, int typedLetterMultiplier, int fullWordMultiplier, - int maxWordLength, int maxWords, int maxAlternatives) + int maxWordLength, int maxWords) : mDict((unsigned char*) dict), mDictSize(dictSize), mMmapFd(mmapFd), mDictBufAdjust(dictBufAdjust), // Checks whether it has the latest dictionary or the old dictionary 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, IS_LATEST_DICT_VERSION); + mBigramDictionary = new BigramDictionary(mDict + headerSize, maxWordLength, + 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/jni/src/dictionary.h b/native/jni/src/dictionary.h new file mode 100644 index 000000000..139d3f0d7 --- /dev/null +++ b/native/jni/src/dictionary.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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_DICTIONARY_H +#define LATINIME_DICTIONARY_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: + Dictionary(void *dict, int dictSize, int mmapFd, int dictBufAdjust, int typedLetterMultipler, + int fullWordMultiplier, int maxWordLength, int maxWords); + + int getSuggestions(ProximityInfo *proximityInfo, int *xcoordinates, int *ycoordinates, + int *codes, int codesSize, int flags, unsigned short *outWords, int *frequencies) { + return mUnigramDictionary->getSuggestions(proximityInfo, mWordsPriorityQueuePool, + mCorrection, xcoordinates, ycoordinates, codes, + codesSize, flags, outWords, frequencies); + } + + // TODO: Call mBigramDictionary instead of mUnigramDictionary + int getBigrams(unsigned short *word, int length, int *codes, int codesSize, + unsigned short *outWords, int *frequencies, int maxWordLength, int maxBigrams) { + return mBigramDictionary->getBigrams(word, length, codes, codesSize, outWords, frequencies, + maxWordLength, maxBigrams); + } + + bool isValidWord(unsigned short *word, int length); + void *getDict() { return (void *)mDict; } + int getDictSize() { return mDictSize; } + int getMmapFd() { return mMmapFd; } + int getDictBufAdjust() { return mDictBufAdjust; } + ~Dictionary(); + + // public static utility methods + // static inline methods should be defined in the header file + static int wideStrLen(unsigned short *str); + + private: + bool hasBigram(); + + const unsigned char *mDict; + + // Used only for the mmap version of dictionary loading, but we use these as dummy variables + // also for the malloc version. + const int mDictSize; + const int mMmapFd; + const int mDictBufAdjust; + + 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 int Dictionary::wideStrLen(unsigned short *str) { + if (!str) return 0; + unsigned short *end = str; + while (*end) + end++; + return end - str; +} +} // namespace latinime + +#endif // LATINIME_DICTIONARY_H diff --git a/native/src/proximity_info.cpp b/native/jni/src/proximity_info.cpp index 763a3a174..c00c4c20f 100644 --- a/native/src/proximity_info.cpp +++ b/native/jni/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,30 @@ 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]; + mInputCodes = new int32_t[MAX_PROXIMITY_CHARS_SIZE * MAX_WORD_LENGTH_INTERNAL]; 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])); @@ -92,6 +97,7 @@ void ProximityInfo::initializeCodeToKeyIndex() { ProximityInfo::~ProximityInfo() { delete[] mNormalizedSquaredDistances; delete[] mProximityCharsArray; + delete[] mInputCodes; } inline int ProximityInfo::getStartIndexFromCoordinates(const int x, const int y) const { @@ -100,13 +106,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,10 +129,126 @@ bool ProximityInfo::hasSpaceProximity(const int x, const int y) const { return false; } -// TODO: Calculate nearby codes here. -void ProximityInfo::setInputParams(const int* inputCodes, const int inputLength, +bool ProximityInfo::isOnKey(const int keyId, const int x, const int y) const { + if (keyId < 0) return true; // NOT_A_ID is -1, but return whenever < 0 just in case + 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 { + if (keyId < 0) return true; // NOT_A_ID is -1, but return whenever < 0 just in case + const int left = mKeyXCoordinates[keyId]; + const int top = mKeyYCoordinates[keyId]; + const int right = left + mKeyWidths[keyId]; + 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) const { + int insertPos = 0; + inputCodes[insertPos++] = primaryKey; + const int startIndex = getStartIndexFromCoordinates(x, y); + if (startIndex >= 0) { + for (int i = 0; i < MAX_PROXIMITY_CHARS_SIZE; ++i) { + const int32_t c = mProximityCharsArray[startIndex + i]; + if (c < KEYCODE_SPACE || c == primaryKey) { + continue; + } + const 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; + } + } + } + const int additionalProximitySize = + AdditionalProximityChars::getAdditionalCharsSize(&mLocaleStr, primaryKey); + if (additionalProximitySize > 0) { + inputCodes[insertPos++] = ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE; + if (insertPos >= MAX_PROXIMITY_CHARS_SIZE) { + if (DEBUG_DICT) { + assert(false); + } + return; + } + + 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 + for (int i = insertPos; i < MAX_PROXIMITY_CHARS_SIZE; ++i) { + inputCodes[i] = NOT_A_CODE; + } +} + +void ProximityInfo::setInputParams(const int32_t* inputCodes, const int inputLength, const int* xCoordinates, const int* yCoordinates) { - mInputCodes = inputCodes; + memset(mInputCodes, 0, + MAX_WORD_LENGTH_INTERNAL * MAX_PROXIMITY_CHARS_SIZE * sizeof(mInputCodes[0])); + + for (int i = 0; i < inputLength; ++i) { + const int32_t primaryKey = inputCodes[i]; + const int x = xCoordinates[i]; + const int y = yCoordinates[i]; + int *proximities = &mInputCodes[i * MAX_PROXIMITY_CHARS_SIZE]; + calculateNearbyKeyCodes(x, y, primaryKey, proximities); + } + + if (DEBUG_PROXIMITY_CHARS) { + for (int i = 0; i < inputLength; ++i) { + AKLOGI("---"); + for (int j = 0; j < MAX_PROXIMITY_CHARS_SIZE; ++j) { + int icc = mInputCodes[i * MAX_PROXIMITY_CHARS_SIZE + j]; + int icfjc = inputCodes[i * MAX_PROXIMITY_CHARS_SIZE + j]; + icc+= 0; + icfjc += 0; + AKLOGI("--- (%d)%c,%c", i, icc, icfjc); + AKLOGI("--- A<%d>,B<%d>", icc, icfjc); + } + } + } + //Keep for debug, sorry + //for (int i = 0; i < MAX_WORD_LENGTH_INTERNAL * MAX_PROXIMITY_CHARS_SIZE; ++i) { + //if (i < inputLength * MAX_PROXIMITY_CHARS_SIZE) { + //mInputCodes[i] = mInputCodesFromJava[i]; + //} else { + // mInputCodes[i] = 0; + // } + //} mInputXCoordinates = xCoordinates; mInputYCoordinates = yCoordinates; mTouchPositionCorrectionEnabled = @@ -128,12 +258,35 @@ 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); - const float squaredDistance = calculateNormalizedSquaredDistance(keyIndex, i); + const float squaredDistance = hasInputCoordinates() + ? calculateNormalizedSquaredDistance(getKeyIndex(currentChar), i) + : NOT_A_DISTANCE_FLOAT; if (squaredDistance >= 0.0f) { mNormalizedSquaredDistances[i * MAX_PROXIMITY_CHARS_SIZE + j] = (int)(squaredDistance * NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR); @@ -142,6 +295,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); + } } } } @@ -150,26 +306,32 @@ inline float square(const float x) { return x * x; } float ProximityInfo::calculateNormalizedSquaredDistance( const int keyIndex, const int inputIndex) const { - static const float NOT_A_DISTANCE_FLOAT = -1.0f; - if (keyIndex == NOT_A_INDEX) { + if (keyIndex == NOT_AN_INDEX) { return NOT_A_DISTANCE_FLOAT; } 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; } +bool ProximityInfo::hasInputCoordinates() const { + return mInputXCoordinates && mInputYCoordinates; +} + int ProximityInfo::getKeyIndex(const int c) const { - if (KEY_COUNT == 0 || !mInputXCoordinates || !mInputYCoordinates) { + if (KEY_COUNT == 0) { // We do not have the coordinate data - return NOT_A_INDEX; + return NOT_AN_INDEX; } - const unsigned short baseLowerC = Dictionary::toBaseLowerCase(c); + const unsigned short baseLowerC = toBaseLowerCase(c); if (baseLowerC > MAX_CHAR_CODE) { - return NOT_A_INDEX; + return NOT_AN_INDEX; } return mCodeToKeyIndex[baseLowerC]; } @@ -232,7 +394,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 +407,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 +423,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/jni/src/proximity_info.h index 35e354c6e..c1eefeacc 100644 --- a/native/src/proximity_info.h +++ b/native/jni/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 int32_t *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,38 +72,49 @@ 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 static const int MAX_CHAR_CODE = 127; + static const float NOT_A_DISTANCE_FLOAT = -1.0f; + static const int NOT_A_CODE = -1; int getStartIndexFromCoordinates(const int x, const int y) const; void initializeCodeToKeyIndex(); float calculateNormalizedSquaredDistance(const int keyIndex, const int inputIndex) const; float calculateSquaredDistanceFromSweetSpotCenter( const int keyIndex, const int inputIndex) const; + bool hasInputCoordinates() const; int getKeyIndex(const int c) const; bool hasSweetSpotData(const int keyIndex) const { // When there are no calibration data for a key, // 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) const; + int squaredDistanceToEdge(const int keyId, const int x, const int y) const; + void calculateNearbyKeyCodes( + const int x, const int y, const int32_t primaryKey, int *inputCodes) const; 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 int *mInputCodes; + const std::string mLocaleStr; + // TODO: remove this + const int *mInputCodesFromJava; + int32_t *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/jni/src/terminal_attributes.h b/native/jni/src/terminal_attributes.h new file mode 100644 index 000000000..1f9815936 --- /dev/null +++ b/native/jni/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/jni/src/unigram_dictionary.cpp b/native/jni/src/unigram_dictionary.cpp new file mode 100644 index 000000000..ed4c066f3 --- /dev/null +++ b/native/jni/src/unigram_dictionary.cpp @@ -0,0 +1,894 @@ +/* +** +** 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. +*/ + +#include <assert.h> +#include <string.h> + +#define LOG_TAG "LatinIME: unigram_dictionary.cpp" + +#include "char_utils.h" +#include "dictionary.h" +#include "unigram_dictionary.h" + +#include "binary_format.h" +#include "terminal_attributes.h" + +namespace latinime { + +const UnigramDictionary::digraph_t UnigramDictionary::GERMAN_UMLAUT_DIGRAPHS[] = + { { 'a', 'e', 0x00E4 }, // U+00E4 : LATIN SMALL LETTER A WITH DIAERESIS + { 'o', 'e', 0x00F6 }, // U+00F6 : LATIN SMALL LETTER O WITH DIAERESIS + { 'u', 'e', 0x00FC } }; // U+00FC : LATIN SMALL LETTER U WITH DIAERESIS + +const UnigramDictionary::digraph_t UnigramDictionary::FRENCH_LIGATURES_DIGRAPHS[] = + { { 'a', 'e', 0x00E6 }, // U+00E6 : LATIN SMALL LETTER AE + { 'o', 'e', 0x0153 } }; // U+0153 : LATIN SMALL LIGATURE OE + +// TODO: check the header +UnigramDictionary::UnigramDictionary(const uint8_t* const streamStart, int typedLetterMultiplier, + int fullWordMultiplier, int maxWordLength, int maxWords, + const bool isLatestDictVersion) + : DICT_ROOT(streamStart), MAX_WORD_LENGTH(maxWordLength), MAX_WORDS(maxWords), + IS_LATEST_DICT_VERSION(isLatestDictVersion), + TYPED_LETTER_MULTIPLIER(typedLetterMultiplier), FULL_WORD_MULTIPLIER(fullWordMultiplier), + // TODO : remove this variable. + ROOT_POS(0), + BYTES_IN_ONE_CHAR(sizeof(int)), + MAX_DIGRAPH_SEARCH_DEPTH(DEFAULT_MAX_DIGRAPH_SEARCH_DEPTH) { + if (DEBUG_DICT) { + AKLOGI("UnigramDictionary - constructor"); + } +} + +UnigramDictionary::~UnigramDictionary() { +} + +static inline unsigned int getCodesBufferSize(const int *codes, const int codesSize) { + return sizeof(*codes) * codesSize; +} + +// 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); +} + +// Return the replacement code point for a digraph, or 0 if none. +int UnigramDictionary::getDigraphReplacement(const int *codes, const int i, const int codesSize, + const digraph_t* const digraphs, const unsigned int digraphsSize) const { + + // There can't be a digraph if we don't have at least 2 characters to examine + if (i + 2 > codesSize) return false; + + // Search for the first char of some digraph + int lastDigraphIndex = -1; + const int thisChar = codes[i]; + for (lastDigraphIndex = digraphsSize - 1; lastDigraphIndex >= 0; --lastDigraphIndex) { + if (thisChar == digraphs[lastDigraphIndex].first) break; + } + // No match: return early + if (lastDigraphIndex < 0) return 0; + + // It's an interesting digraph if the second char matches too. + if (digraphs[lastDigraphIndex].second == codes[i + 1]) { + return digraphs[lastDigraphIndex].replacement; + } else { + return 0; + } +} + +// Mostly the same arguments as the non-recursive version, except: +// codes is the original value. It points to the start of the work buffer, and gets passed as is. +// codesSize is the size of the user input (thus, it is the size of codesSrc). +// codesDest is the current point in the work buffer. +// 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, + 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 digraph_t* const digraphs, const unsigned int digraphsSize) { + + const int startIndex = codesDest - codesBuffer; + if (currentDepth < MAX_DIGRAPH_SEARCH_DEPTH) { + for (int i = 0; i < codesRemain; ++i) { + xCoordinatesBuffer[startIndex + i] = xcoordinates[codesBufferSize - codesRemain + i]; + yCoordinatesBuffer[startIndex + i] = ycoordinates[codesBufferSize - codesRemain + i]; + const int replacementCodePoint = + getDigraphReplacement(codesSrc, i, codesRemain, digraphs, digraphsSize); + if (0 != replacementCodePoint) { + // Found a digraph. We will try both spellings. eg. the word is "pruefen" + + // Copy the word up to the first char of the digraph, including proximity chars, + // and overwrite the primary code with the replacement code point. Then, continue + // processing on the remaining part of the word, skipping the second char of the + // digraph. + // In our example, copy "pru", replace "u" with the version with the diaeresis and + // continue running on "fen". + // Make i the index of the second char of the digraph for simplicity. Forgetting + // to do that results in an infinite recursion so take care! + ++i; + memcpy(codesDest, codesSrc, i * BYTES_IN_ONE_CHAR); + codesDest[(i - 1) * (BYTES_IN_ONE_CHAR / sizeof(codesDest[0]))] = + replacementCodePoint; + getWordWithDigraphSuggestionsRec(proximityInfo, xcoordinates, ycoordinates, + codesBuffer, xCoordinatesBuffer, yCoordinatesBuffer, codesBufferSize, flags, + codesSrc + i + 1, codesRemain - i - 1, + currentDepth + 1, codesDest + i, correction, + queuePool, digraphs, digraphsSize); + + // Copy the second char of the digraph in place, then continue processing on + // the remaining part of the word. + // In our example, after "pru" in the buffer copy the "e", and continue on "fen" + memcpy(codesDest + i, codesSrc + i, BYTES_IN_ONE_CHAR); + getWordWithDigraphSuggestionsRec(proximityInfo, xcoordinates, ycoordinates, + codesBuffer, xCoordinatesBuffer, yCoordinatesBuffer, codesBufferSize, flags, + codesSrc + i, codesRemain - i, currentDepth + 1, + codesDest + i, correction, queuePool, + digraphs, digraphsSize); + return; + } + } + } + + // If we come here, we hit the end of the word: let's check it against the dictionary. + // In our example, we'll come here once for "prufen" and then once for "pruefen". + // If the word contains several digraphs, we'll come it for the product of them. + // 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) { + memcpy(codesDest, codesSrc, remainingBytes); + memcpy(&xCoordinatesBuffer[startIndex], &xcoordinates[codesBufferSize - codesRemain], + sizeof(int) * codesRemain); + memcpy(&yCoordinatesBuffer[startIndex], &ycoordinates[codesBufferSize - codesRemain], + sizeof(int) * codesRemain); + } + + getWordSuggestions(proximityInfo, xCoordinatesBuffer, yCoordinatesBuffer, codesBuffer, + startIndex + codesRemain, flags, correction, + queuePool); +} + +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)]; + int xCoordinatesBuffer[codesSize]; + int yCoordinatesBuffer[codesSize]; + getWordWithDigraphSuggestionsRec(proximityInfo, xcoordinates, ycoordinates, codesBuffer, + xCoordinatesBuffer, yCoordinatesBuffer, + codesSize, flags, codes, codesSize, 0, codesBuffer, masterCorrection, queuePool, + GERMAN_UMLAUT_DIGRAPHS, + sizeof(GERMAN_UMLAUT_DIGRAPHS) / sizeof(GERMAN_UMLAUT_DIGRAPHS[0])); + } else if (REQUIRES_FRENCH_LIGATURES_PROCESSING & flags) { + int codesBuffer[getCodesBufferSize(codes, codesSize)]; + int xCoordinatesBuffer[codesSize]; + int yCoordinatesBuffer[codesSize]; + getWordWithDigraphSuggestionsRec(proximityInfo, xcoordinates, ycoordinates, codesBuffer, + xCoordinatesBuffer, yCoordinatesBuffer, + codesSize, flags, codes, codesSize, 0, codesBuffer, masterCorrection, queuePool, + FRENCH_LIGATURES_DIGRAPHS, + sizeof(FRENCH_LIGATURES_DIGRAPHS) / sizeof(FRENCH_LIGATURES_DIGRAPHS[0])); + } else { // Normal processing + getWordSuggestions(proximityInfo, xcoordinates, ycoordinates, codes, codesSize, flags, + masterCorrection, queuePool); + } + + PROF_START(20); + 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) { + 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) { + 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]; + AKLOGI("%s %i", s, frequencies[j]); + } + } + PROF_END(20); + PROF_CLOSE; + return suggestedWordsCount; +} + +void UnigramDictionary::getWordSuggestions(ProximityInfo *proximityInfo, + const int *xcoordinates, const int *ycoordinates, const int *codes, + const int inputLength, const int flags, Correction *correction, + WordsPriorityQueuePool *queuePool) { + + PROF_OPEN; + PROF_START(0); + PROF_END(0); + + PROF_START(1); + const bool useFullEditDistance = USE_FULL_EDIT_DISTANCE & flags; + getOneWordSuggestions(proximityInfo, xcoordinates, ycoordinates, codes, useFullEditDistance, + inputLength, correction, queuePool); + PROF_END(1); + + PROF_START(2); + // Note: This line is intentionally left blank + PROF_END(2); + + PROF_START(3); + // Note: This line is intentionally left blank + PROF_END(3); + + PROF_START(4); + 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); + // 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); + // 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); + } + } + } +} + +void UnigramDictionary::initSuggestions(ProximityInfo *proximityInfo, const int *xCoordinates, + const int *yCoordinates, const int *codes, const int inputLength, Correction *correction) { + if (DEBUG_DICT) { + AKLOGI("initSuggest"); + } + 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::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 + 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 = BinaryFormat::getGroupCountAndForwardPointer(DICT_ROOT, &rootPosition); + int outputIndex = 0; + + correction->initCorrectionState(rootPosition, childCount, (inputLength <= 0)); + + // Depth first search + while (outputIndex >= 0) { + if (correction->initProcessState(outputIndex)) { + int siblingPos = correction->getTreeSiblingPos(outputIndex); + int firstChildPos; + + const bool needsToTraverseChildrenNodes = processCurrentNode(siblingPos, + correction, &childCount, &firstChildPos, &siblingPos, queuePool, + currentWordIndex); + // Update next sibling pos + correction->setTreeSiblingPos(outputIndex, siblingPos); + + if (needsToTraverseChildrenNodes) { + // Goes to child node + outputIndex = correction->goDownTree(outputIndex, childCount, firstChildPos); + } + } else { + // Goes to parent sibling node + outputIndex = correction->getTreeParentIndex(outputIndex); + } + } +} + +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; + + int wordLength; + unsigned short* wordPointer; + + 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); + } +} + +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, 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) { + 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]; + } + + // 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 ((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; +} + +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 (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); + } + + // 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); + } +} + +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) { + AKLOGI("--- Suggest multiple words"); + } + + // 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, ProximityInfo *proximityInfo, unsigned short *word) { + uint16_t inWord[inputLength]; + + for (int i = 0; i < inputLength; ++i) { + inWord[i] = (uint16_t)proximityInfo->getPrimaryCharAt(startInputIndex + i); + } + return getMostFrequentWordLikeInner(inWord, inputLength, word); +} + +// This function will take the position of a character array within a CharGroup, +// and check it actually like-matches the word in inWord starting at startInputIndex, +// that is, it matches it with case and accents squashed. +// The function returns true if there was a full match, false otherwise. +// The function will copy on-the-fly the characters in the CharGroup to outNewWord. +// It will also place the end position of the array in outPos; in outInputIndex, +// it will place the index of the first char AFTER the match if there was a match, +// and the initial position if there was not. It makes sense because if there was +// a match we want to continue searching, but if there was not, we want to go to +// the next CharGroup. +// In and out parameters may point to the same location. This function takes care +// not to use any input parameters after it wrote into its outputs. +static inline bool testCharGroupForContinuedLikeness(const uint8_t flags, + const uint8_t* const root, const int startPos, + const uint16_t* const inWord, const int startInputIndex, + int32_t* outNewWord, int* outInputIndex, int* outPos) { + const bool hasMultipleChars = (0 != (UnigramDictionary::FLAG_HAS_MULTIPLE_CHARS & flags)); + int pos = startPos; + int32_t character = BinaryFormat::getCharCodeAndForwardPointer(root, &pos); + int32_t baseChar = toBaseLowerCase(character); + const uint16_t wChar = toBaseLowerCase(inWord[startInputIndex]); + + if (baseChar != wChar) { + *outPos = hasMultipleChars ? BinaryFormat::skipOtherCharacters(root, pos) : pos; + *outInputIndex = startInputIndex; + return false; + } + int inputIndex = startInputIndex; + outNewWord[inputIndex] = character; + if (hasMultipleChars) { + character = BinaryFormat::getCharCodeAndForwardPointer(root, &pos); + while (NOT_A_CHARACTER != character) { + baseChar = toBaseLowerCase(character); + if (toBaseLowerCase(inWord[++inputIndex]) != baseChar) { + *outPos = BinaryFormat::skipOtherCharacters(root, pos); + *outInputIndex = startInputIndex; + return false; + } + outNewWord[inputIndex] = character; + character = BinaryFormat::getCharCodeAndForwardPointer(root, &pos); + } + } + *outInputIndex = inputIndex + 1; + *outPos = pos; + return true; +} + +// This function is invoked when a word like the word searched for is found. +// It will compare the frequency to the max frequency, and if greater, will +// copy the word into the output buffer. In output value maxFreq, it will +// write the new maximum frequency if it changed. +static inline void onTerminalWordLike(const int freq, int32_t* newWord, const int length, + short unsigned int* outWord, int* maxFreq) { + if (freq > *maxFreq) { + for (int q = 0; q < length; ++q) + outWord[q] = newWord[q]; + outWord[length] = 0; + *maxFreq = freq; + } +} + +// Will find the highest frequency of the words like the one passed as an argument, +// that is, everything that only differs by case/accents. +int UnigramDictionary::getMostFrequentWordLikeInner(const uint16_t * const inWord, + const int length, short unsigned int* outWord) { + int32_t newWord[MAX_WORD_LENGTH_INTERNAL]; + int depth = 0; + int maxFreq = -1; + const uint8_t* const root = DICT_ROOT; + + int startPos = 0; + mStackChildCount[0] = BinaryFormat::getGroupCountAndForwardPointer(root, &startPos); + mStackInputIndex[0] = 0; + mStackSiblingPos[0] = startPos; + while (depth >= 0) { + const int charGroupCount = mStackChildCount[depth]; + int pos = mStackSiblingPos[depth]; + for (int charGroupIndex = charGroupCount - 1; charGroupIndex >= 0; --charGroupIndex) { + int inputIndex = mStackInputIndex[depth]; + const uint8_t flags = BinaryFormat::getFlagsAndForwardPointer(root, &pos); + // Test whether all chars in this group match with the word we are searching for. If so, + // we want to traverse its children (or if the length match, evaluate its frequency). + // Note that this function will output the position regardless, but will only write + // into inputIndex if there is a match. + const bool isAlike = testCharGroupForContinuedLikeness(flags, root, pos, inWord, + inputIndex, newWord, &inputIndex, &pos); + if (isAlike && (FLAG_IS_TERMINAL & flags) && (inputIndex == length)) { + const int frequency = BinaryFormat::readFrequencyWithoutMovingPointer(root, pos); + onTerminalWordLike(frequency, newWord, inputIndex, outWord, &maxFreq); + } + pos = BinaryFormat::skipFrequency(flags, pos); + const int siblingPos = BinaryFormat::skipChildrenPosAndAttributes(root, flags, pos); + const int childrenNodePos = BinaryFormat::readChildrenPosition(root, flags, pos); + // If we had a match and the word has children, we want to traverse them. We don't have + // to traverse words longer than the one we are searching for, since they will not match + // anyway, so don't traverse unless inputIndex < length. + if (isAlike && (-1 != childrenNodePos) && (inputIndex < length)) { + // Save position for this depth, to get back to this once children are done + mStackChildCount[depth] = charGroupIndex; + mStackSiblingPos[depth] = siblingPos; + // Prepare stack values for next depth + ++depth; + int childrenPos = childrenNodePos; + mStackChildCount[depth] = + BinaryFormat::getGroupCountAndForwardPointer(root, &childrenPos); + mStackSiblingPos[depth] = childrenPos; + mStackInputIndex[depth] = inputIndex; + pos = childrenPos; + // Go to the next depth level. + ++depth; + break; + } else { + // No match, or no children, or word too long to ever match: go the next sibling. + pos = siblingPos; + } + } + --depth; + } + return maxFreq; +} + +bool UnigramDictionary::isValidWord(const uint16_t* const inWord, const int length) const { + return NOT_VALID_WORD != BinaryFormat::getTerminalPosition(DICT_ROOT, inWord, length); +} + +// TODO: remove this function. +int UnigramDictionary::getBigramPosition(int pos, unsigned short *word, int offset, + int length) const { + return -1; +} + +// ProcessCurrentNode returns a boolean telling whether to traverse children nodes or not. +// If the return value is false, then the caller should read in the output "nextSiblingPosition" +// to find out the address of the next sibling node and pass it to a new call of processCurrentNode. +// It is worthy to note that when false is returned, the output values other than +// nextSiblingPosition are undefined. +// If the return value is true, then the caller must proceed to traverse the children of this +// node. processCurrentNode will output the information about the children: their count in +// newCount, their position in newChildrenPosition, the traverseAllNodes flag in +// newTraverseAllNodes, the match weight into newMatchRate, the input index into newInputIndex, the +// diffs into newDiffs, the sibling position in nextSiblingPosition, and the output index into +// newOutputIndex. Please also note the following caveat: processCurrentNode does not know when +// there aren't any more nodes at this level, it merely returns the address of the first byte after +// the current node in nextSiblingPosition. Thus, the caller must keep count of the nodes at any +// 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, WordsPriorityQueuePool *queuePool, + const int currentWordIndex) { + if (DEBUG_DICT) { + correction->checkState(); + } + int pos = initialPos; + + // Flags contain the following information: + // - Address type (MASK_GROUP_ADDRESS_TYPE) on two bits: + // - FLAG_GROUP_ADDRESS_TYPE_{ONE,TWO,THREE}_BYTES means there are children and their address + // is on the specified number of bytes. + // - FLAG_GROUP_ADDRESS_TYPE_NOADDRESS means there are no children, and therefore no address. + // - FLAG_HAS_MULTIPLE_CHARS: whether this node has multiple char or not. + // - FLAG_IS_TERMINAL: whether this node is a terminal or not (it may still have children) + // - FLAG_HAS_BIGRAMS: whether this node has bigrams or not + const uint8_t flags = BinaryFormat::getFlagsAndForwardPointer(DICT_ROOT, &pos); + const bool hasMultipleChars = (0 != (FLAG_HAS_MULTIPLE_CHARS & flags)); + const bool isTerminalNode = (0 != (FLAG_IS_TERMINAL & flags)); + + bool needsToInvokeOnTerminal = false; + + // This gets only ONE character from the stream. Next there will be: + // if FLAG_HAS_MULTIPLE CHARS: the other characters of the same node + // else if FLAG_IS_TERMINAL: the frequency + // else if MASK_GROUP_ADDRESS_TYPE is not NONE: the children address + // Note that you can't have a node that both is not a terminal and has no children. + int32_t c = BinaryFormat::getCharCodeAndForwardPointer(DICT_ROOT, &pos); + assert(NOT_A_CHARACTER != c); + + // We are going to loop through each character and make it look like it's a different + // node each time. To do that, we will process characters in this node in order until + // we find the character terminator. This is signalled by getCharCode* returning + // NOT_A_CHARACTER. + // As a special case, if there is only one character in this node, we must not read the + // next bytes so we will simulate the NOT_A_CHARACTER return by testing the flags. + // This way, each loop run will look like a "virtual node". + do { + // We prefetch the next char. If 'c' is the last char of this node, we will have + // NOT_A_CHARACTER in the next char. From this we can decide whether this virtual node + // should behave as a terminal or not and whether we have children. + const int32_t nextc = hasMultipleChars + ? BinaryFormat::getCharCodeAndForwardPointer(DICT_ROOT, &pos) : NOT_A_CHARACTER; + const bool isLastChar = (NOT_A_CHARACTER == nextc); + // If there are more chars in this nodes, then this virtual node is not a terminal. + // If we are on the last char, this virtual node is a terminal if this node is. + const bool isTerminal = isLastChar && isTerminalNode; + + Correction::CorrectionType stateType = correction->processCharAndCalcState( + c, isTerminal); + if (stateType == Correction::TRAVERSE_ALL_ON_TERMINAL + || stateType == Correction::ON_TERMINAL) { + needsToInvokeOnTerminal = true; + } 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 + // characters in this node, the frequency if it's there, read the next sibling + // position to output it, then return false. + // We don't have to output other values because we return false, as in + // "don't traverse children". + if (!isLastChar) { + pos = BinaryFormat::skipOtherCharacters(DICT_ROOT, pos); + } + pos = BinaryFormat::skipFrequency(flags, pos); + *nextSiblingPosition = + BinaryFormat::skipChildrenPosAndAttributes(DICT_ROOT, flags, pos); + return false; + } + + // Prepare for the next character. Promote the prefetched char to current char - the loop + // will take care of prefetching the next. If we finally found our last char, nextc will + // contain NOT_A_CHARACTER. + c = nextc; + } while (NOT_A_CHARACTER != c); + + if (isTerminalNode) { + // 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. + const bool hasChildren = BinaryFormat::hasChildrenInFlags(flags); + + // This character matched the typed character (enough to traverse the node at least) + // so we just evaluated it. Now we should evaluate this virtual node's children - that + // is, if it has any. If it has no children, we're done here - so we skip the end of + // the node, output the siblings position, and return false "don't traverse children". + // Note that !hasChildren implies isLastChar, so we know we don't have to skip any + // remaining char in this group for there can't be any. + if (!hasChildren) { + pos = BinaryFormat::skipFrequency(flags, pos); + *nextSiblingPosition = + BinaryFormat::skipChildrenPosAndAttributes(DICT_ROOT, flags, pos); + return false; + } + + // Optimization: Prune out words that are too long compared to how much was typed. + if (correction->needsToPrune()) { + pos = BinaryFormat::skipFrequency(flags, pos); + *nextSiblingPosition = + BinaryFormat::skipChildrenPosAndAttributes(DICT_ROOT, flags, pos); + if (DEBUG_DICT_FULL) { + AKLOGI("Traversing was pruned."); + } + return false; + } + } + + // Now we finished processing this node, and we want to traverse children. If there are no + // children, we can't come here. + assert(BinaryFormat::hasChildrenInFlags(flags)); + + // If this node was a terminal it still has the frequency under the pointer (it may have been + // read, but not skipped - see readFrequencyWithoutMovingPointer). + // Next come the children position, then possibly attributes (attributes are bigrams only for + // now, maybe something related to shortcuts in the future). + // Once this is read, we still need to output the number of nodes in the immediate children of + // this node, so we read and output it before returning true, as in "please traverse children". + pos = BinaryFormat::skipFrequency(flags, pos); + int childrenPos = BinaryFormat::readChildrenPosition(DICT_ROOT, flags, pos); + *nextSiblingPosition = BinaryFormat::skipChildrenPosAndAttributes(DICT_ROOT, flags, pos); + *newCount = BinaryFormat::getGroupCountAndForwardPointer(DICT_ROOT, &childrenPos); + *newChildrenPosition = childrenPos; + return true; +} + +} // namespace latinime diff --git a/native/src/unigram_dictionary.h b/native/jni/src/unigram_dictionary.h index ef9709a89..c8f15566c 100644 --- a/native/src/unigram_dictionary.h +++ b/native/jni/src/unigram_dictionary.h @@ -22,17 +22,16 @@ #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 { + typedef struct { int first; int second; int replacement; } digraph_t; -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 +45,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,58 +69,86 @@ 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, + int fullWordMultiplier, int maxWordLength, int maxWords, 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); + int getDigraphReplacement(const int *codes, const int i, const int codesSize, + const digraph_t* const digraphs, const unsigned int digraphsSize) 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, const digraph_t* const digraphs, + const unsigned int digraphsSize); 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; const int MAX_WORDS; - const int MAX_PROXIMITY_CHARS; const bool IS_LATEST_DICT_VERSION; const int TYPED_LETTER_MULTIPLIER; const int FULL_WORD_MULTIPLIER; const int ROOT_POS; const unsigned int BYTES_IN_ONE_CHAR; - const int MAX_UMLAUT_SEARCH_DEPTH; + const int MAX_DIGRAPH_SEARCH_DEPTH; // Flags for special processing // Those *must* match the flags in BinaryDictionary.Flags.ALL_FLAGS in BinaryDictionary.java @@ -123,18 +156,14 @@ private: // Please update both at the same time. enum { REQUIRES_GERMAN_UMLAUT_PROCESSING = 0x1, - USE_FULL_EDIT_DISTANCE = 0x2 + USE_FULL_EDIT_DISTANCE = 0x2, + REQUIRES_FRENCH_LIGATURES_PROCESSING = 0x4 }; - 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]; + static const digraph_t GERMAN_UMLAUT_DIGRAPHS[]; + static const digraph_t FRENCH_LIGATURES_DIGRAPHS[]; + // 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/jni/src/words_priority_queue.h b/native/jni/src/words_priority_queue.h new file mode 100644 index 000000000..249962eec --- /dev/null +++ b/native/jni/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/jni/src/words_priority_queue_pool.h b/native/jni/src/words_priority_queue_pool.h new file mode 100644 index 000000000..5b50e8f4f --- /dev/null +++ b/native/jni/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/native/src/char_utils.h b/native/src/char_utils.h deleted file mode 100644 index a69a35e7a..000000000 --- a/native/src/char_utils.h +++ /dev/null @@ -1,26 +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. - */ - -#ifndef LATINIME_CHAR_UTILS_H -#define LATINIME_CHAR_UTILS_H - -namespace latinime { - -unsigned short latin_tolower(unsigned short c); - -} // namespace latinime - -#endif // LATINIME_CHAR_UTILS_H diff --git a/native/src/dictionary.h b/native/src/dictionary.h deleted file mode 100644 index d5de0083a..000000000 --- a/native/src/dictionary.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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_DICTIONARY_H -#define LATINIME_DICTIONARY_H - -#include "basechars.h" -#include "bigram_dictionary.h" -#include "char_utils.h" -#include "defines.h" -#include "proximity_info.h" -#include "unigram_dictionary.h" - -namespace latinime { - -class Dictionary { -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, - codesSize, flags, outWords, frequencies); - } - - // TODO: Call mBigramDictionary instead of mUnigramDictionary - int getBigrams(unsigned short *word, int length, int *codes, int codesSize, - unsigned short *outWords, int *frequencies, int maxWordLength, int maxBigrams, - int maxAlternatives) { - return mBigramDictionary->getBigrams(word, length, codes, codesSize, outWords, frequencies, - maxWordLength, maxBigrams, maxAlternatives); - } - - bool isValidWord(unsigned short *word, int length); - void *getDict() { return (void *)mDict; } - int getDictSize() { return mDictSize; } - int getMmapFd() { return mMmapFd; } - int getDictBufAdjust() { return mDictBufAdjust; } - ~Dictionary(); - - // 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: - bool hasBigram(); - - const unsigned char *mDict; - - // Used only for the mmap version of dictionary loading, but we use these as dummy variables - // also for the malloc version. - const int mDictSize; - const int mMmapFd; - const int mDictBufAdjust; - - const bool IS_LATEST_DICT_VERSION; - UnigramDictionary *mUnigramDictionary; - BigramDictionary *mBigramDictionary; -}; - -// 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; - while (*end) - 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/unigram_dictionary.cpp b/native/src/unigram_dictionary.cpp deleted file mode 100644 index 8eb5a9700..000000000 --- a/native/src/unigram_dictionary.cpp +++ /dev/null @@ -1,729 +0,0 @@ -/* -** -** 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. -*/ - -#include <assert.h> -#include <string.h> - -#define LOG_TAG "LatinIME: unigram_dictionary.cpp" - -#include "char_utils.h" -#include "dictionary.h" -#include "unigram_dictionary.h" - -#include "binary_format.h" - -namespace latinime { - -const UnigramDictionary::digraph_t UnigramDictionary::GERMAN_UMLAUT_DIGRAPHS[] = - { { 'a', 'e' }, - { 'o', 'e' }, - { 'u', 'e' } }; - -// TODO: check the header -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), - MAX_PROXIMITY_CHARS(maxProximityChars), IS_LATEST_DICT_VERSION(isLatestDictVersion), - TYPED_LETTER_MULTIPLIER(typedLetterMultiplier), FULL_WORD_MULTIPLIER(fullWordMultiplier), - // TODO : remove this variable. - ROOT_POS(0), - BYTES_IN_ONE_CHAR(MAX_PROXIMITY_CHARS * sizeof(int)), - MAX_UMLAUT_SEARCH_DEPTH(DEFAULT_MAX_UMLAUT_SEARCH_DEPTH) { - if (DEBUG_DICT) { - LOGI("UnigramDictionary - constructor"); - } - mCorrection = new Correction(typedLetterMultiplier, fullWordMultiplier); -} - -UnigramDictionary::~UnigramDictionary() { - delete mCorrection; -} - -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 { - - // There can't be a digraph if we don't have at least 2 characters to examine - if (i + 2 > codesSize) return false; - - // Search for the first char of some digraph - int lastDigraphIndex = -1; - const int thisChar = codes[i * MAX_PROXIMITY_CHARS]; - for (lastDigraphIndex = sizeof(GERMAN_UMLAUT_DIGRAPHS) / sizeof(GERMAN_UMLAUT_DIGRAPHS[0]) - 1; - lastDigraphIndex >= 0; --lastDigraphIndex) { - if (thisChar == GERMAN_UMLAUT_DIGRAPHS[lastDigraphIndex].first) break; - } - // No match: return early - if (lastDigraphIndex < 0) return false; - - // It's an interesting digraph if the second char matches too. - return GERMAN_UMLAUT_DIGRAPHS[lastDigraphIndex].second == codes[(i + 1) * MAX_PROXIMITY_CHARS]; -} - -// Mostly the same arguments as the non-recursive version, except: -// codes is the original value. It points to the start of the work buffer, and gets passed as is. -// codesSize is the size of the user input (thus, it is the size of codesSrc). -// codesDest is the current point in the work buffer. -// 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) { - - if (currentDepth < MAX_UMLAUT_SEARCH_DEPTH) { - for (int i = 0; i < codesRemain; ++i) { - if (isDigraph(codesSrc, i, codesRemain)) { - // Found a digraph. We will try both spellings. eg. the word is "pruefen" - - // Copy the word up to the first char of the digraph, then continue processing - // on the remaining part of the word, skipping the second char of the digraph. - // In our example, copy "pru" and continue running on "fen" - // Make i the index of the second char of the digraph for simplicity. Forgetting - // to do that results in an infinite recursion so take care! - ++i; - memcpy(codesDest, codesSrc, i * BYTES_IN_ONE_CHAR); - getWordWithDigraphSuggestionsRec(proximityInfo, xcoordinates, ycoordinates, - codesBuffer, codesBufferSize, flags, - codesSrc + (i + 1) * MAX_PROXIMITY_CHARS, codesRemain - i - 1, - currentDepth + 1, codesDest + i * MAX_PROXIMITY_CHARS, outWords, - frequencies); - - // Copy the second char of the digraph in place, then continue processing on - // the remaining part of the word. - // In our example, after "pru" in the buffer copy the "e", and continue on "fen" - 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); - return; - } - } - } - - // If we come here, we hit the end of the word: let's check it against the dictionary. - // In our example, we'll come here once for "prufen" and then once for "pruefen". - // If the word contains several digraphs, we'll come it for the product of them. - // 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) - memcpy(codesDest, codesSrc, remainingBytes); - - getWordSuggestions(proximityInfo, xcoordinates, ycoordinates, codesBuffer, - (codesDest - codesBuffer) / MAX_PROXIMITY_CHARS + codesRemain, outWords, frequencies, - flags); -} - -int UnigramDictionary::getSuggestions(ProximityInfo *proximityInfo, const int *xcoordinates, - const int *ycoordinates, const int *codes, const int codesSize, const int flags, - unsigned short *outWords, int *frequencies) { - - if (REQUIRES_GERMAN_UMLAUT_PROCESSING & flags) - { // Incrementally tune the word and try all possibilities - int codesBuffer[getCodesBufferSize(codes, codesSize, MAX_PROXIMITY_CHARS)]; - getWordWithDigraphSuggestionsRec(proximityInfo, xcoordinates, ycoordinates, codesBuffer, - codesSize, flags, codes, codesSize, 0, codesBuffer, outWords, frequencies); - } else { // Normal processing - getWordSuggestions(proximityInfo, xcoordinates, ycoordinates, codes, codesSize, - outWords, frequencies, flags); - } - - PROF_START(20); - // Get the word count - int suggestedWordsCount = 0; - while (suggestedWordsCount < MAX_WORDS && mFrequencies[suggestedWordsCount] > 0) { - suggestedWordsCount++; - } - - if (DEBUG_DICT) { - LOGI("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; - 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 - } - } - PROF_END(20); - PROF_CLOSE; - return suggestedWordsCount; -} - -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) { - - 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); - PROF_END(1); - - PROF_START(2); - // Note: This line is intentionally left blank - PROF_END(2); - - PROF_START(3); - // Note: This line is intentionally left blank - PROF_END(3); - - PROF_START(4); - // Note: This line is intentionally left blank - 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); - } - } - 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); - } - } - } - 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) { - 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; - } - - // 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; -} - -static const char QUOTE = '\''; -static const char SPACE = ' '; - -void UnigramDictionary::getSuggestionCandidates(const bool useFullEditDistance) { - // TODO: Remove setCorrectionParams - mCorrection->setCorrectionParams(0, 0, 0, - -1 /* spaceProximityPos */, -1 /* missingSpacePos */, useFullEditDistance); - int rootPosition = ROOT_POS; - // Get the number of children of root, then increment the position - int childCount = Dictionary::getCount(DICT_ROOT, &rootPosition); - int outputIndex = 0; - - mCorrection->initCorrectionState(rootPosition, childCount, (mInputLength <= 0)); - - // Depth first search - while (outputIndex >= 0) { - if (mCorrection->initProcessState(outputIndex)) { - int siblingPos = mCorrection->getTreeSiblingPos(outputIndex); - int firstChildPos; - - const bool needsToTraverseChildrenNodes = processCurrentNode(siblingPos, - mCorrection, &childCount, &firstChildPos, &siblingPos); - // Update next sibling pos - mCorrection->setTreeSiblingPos(outputIndex, siblingPos); - - if (needsToTraverseChildrenNodes) { - // Goes to child node - outputIndex = mCorrection->goDownTree(outputIndex, childCount, firstChildPos); - } - } else { - // Goes to parent sibling node - outputIndex = mCorrection->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, Correction *correction) { - int wordLength; - unsigned short* wordPointer; - const int finalFreq = correction->getFinalFreq(freq, &wordPointer, &wordLength); - if (finalFreq >= 0) { - addWord(wordPointer, wordLength, finalFreq); - } -} - -void UnigramDictionary::getSplitTwoWordsSuggestion( - const int inputLength, Correction* correction) { - const int spaceProximityPos = correction->getSpaceProximityPos(); - const int missingSpacePos = correction->getMissingSpacePos(); - 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; - - 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); - } - if (firstFreq <= 0) return; - - for (int i = 0; i < firstWordLength; ++i) { - word[i] = mWord[i]; - } - - const int secondFreq = getMostFrequentWordLike(secondWordStartPos, secondWordLength, mWord); - if (DEBUG_DICT) { - LOGI("Second freq: %d", secondFreq); - } - if (secondFreq <= 0) return; - - word[firstWordLength] = SPACE; - for (int i = (firstWordLength + 1); i < newWordLength; ++i) { - word[i] = mWord[i - firstWordLength - 1]; - } - - const int pairFreq = mCorrection->getFreqForSplitTwoWords(firstFreq, secondFreq, word); - if (DEBUG_DICT) { - LOGI("Split two words: %d, %d, %d, %d", firstFreq, secondFreq, pairFreq, inputLength); - } - addWord(word, newWordLength, pairFreq); - return; -} - -// Wrapper for getMostFrequentWordLikeInner, which matches it to the previous -// interface. -inline int UnigramDictionary::getMostFrequentWordLike(const int startInputIndex, - const int inputLength, unsigned short *word) { - uint16_t inWord[inputLength]; - - for (int i = 0; i < inputLength; ++i) { - inWord[i] = (uint16_t)mProximityInfo->getPrimaryCharAt(startInputIndex + i); - } - return getMostFrequentWordLikeInner(inWord, inputLength, word); -} - -// This function will take the position of a character array within a CharGroup, -// and check it actually like-matches the word in inWord starting at startInputIndex, -// that is, it matches it with case and accents squashed. -// The function returns true if there was a full match, false otherwise. -// The function will copy on-the-fly the characters in the CharGroup to outNewWord. -// It will also place the end position of the array in outPos; in outInputIndex, -// it will place the index of the first char AFTER the match if there was a match, -// and the initial position if there was not. It makes sense because if there was -// a match we want to continue searching, but if there was not, we want to go to -// the next CharGroup. -// In and out parameters may point to the same location. This function takes care -// not to use any input parameters after it wrote into its outputs. -static inline bool testCharGroupForContinuedLikeness(const uint8_t flags, - const uint8_t* const root, const int startPos, - const uint16_t* const inWord, const int startInputIndex, - int32_t* outNewWord, int* outInputIndex, int* outPos) { - 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]); - - if (baseChar != wChar) { - *outPos = hasMultipleChars ? BinaryFormat::skipOtherCharacters(root, pos) : pos; - *outInputIndex = startInputIndex; - return false; - } - int inputIndex = startInputIndex; - outNewWord[inputIndex] = character; - if (hasMultipleChars) { - character = BinaryFormat::getCharCodeAndForwardPointer(root, &pos); - while (NOT_A_CHARACTER != character) { - baseChar = Dictionary::toBaseLowerCase(character); - if (Dictionary::toBaseLowerCase(inWord[++inputIndex]) != baseChar) { - *outPos = BinaryFormat::skipOtherCharacters(root, pos); - *outInputIndex = startInputIndex; - return false; - } - outNewWord[inputIndex] = character; - character = BinaryFormat::getCharCodeAndForwardPointer(root, &pos); - } - } - *outInputIndex = inputIndex + 1; - *outPos = pos; - return true; -} - -// This function is invoked when a word like the word searched for is found. -// It will compare the frequency to the max frequency, and if greater, will -// copy the word into the output buffer. In output value maxFreq, it will -// write the new maximum frequency if it changed. -static inline void onTerminalWordLike(const int freq, int32_t* newWord, const int length, - short unsigned int* outWord, int* maxFreq) { - if (freq > *maxFreq) { - for (int q = 0; q < length; ++q) - outWord[q] = newWord[q]; - outWord[length] = 0; - *maxFreq = freq; - } -} - -// Will find the highest frequency of the words like the one passed as an argument, -// that is, everything that only differs by case/accents. -int UnigramDictionary::getMostFrequentWordLikeInner(const uint16_t * const inWord, - const int length, short unsigned int* outWord) { - int32_t newWord[MAX_WORD_LENGTH_INTERNAL]; - int depth = 0; - int maxFreq = -1; - const uint8_t* const root = DICT_ROOT; - - mStackChildCount[0] = root[0]; - mStackInputIndex[0] = 0; - mStackSiblingPos[0] = 1; - while (depth >= 0) { - const int charGroupCount = mStackChildCount[depth]; - int pos = mStackSiblingPos[depth]; - for (int charGroupIndex = charGroupCount - 1; charGroupIndex >= 0; --charGroupIndex) { - int inputIndex = mStackInputIndex[depth]; - const uint8_t flags = BinaryFormat::getFlagsAndForwardPointer(root, &pos); - // Test whether all chars in this group match with the word we are searching for. If so, - // we want to traverse its children (or if the length match, evaluate its frequency). - // Note that this function will output the position regardless, but will only write - // into inputIndex if there is a match. - const bool isAlike = testCharGroupForContinuedLikeness(flags, root, pos, inWord, - inputIndex, newWord, &inputIndex, &pos); - if (isAlike && (FLAG_IS_TERMINAL & flags) && (inputIndex == length)) { - const int frequency = BinaryFormat::readFrequencyWithoutMovingPointer(root, pos); - onTerminalWordLike(frequency, newWord, inputIndex, outWord, &maxFreq); - } - pos = BinaryFormat::skipFrequency(flags, pos); - const int siblingPos = BinaryFormat::skipChildrenPosAndAttributes(root, flags, pos); - const int childrenNodePos = BinaryFormat::readChildrenPosition(root, flags, pos); - // If we had a match and the word has children, we want to traverse them. We don't have - // to traverse words longer than the one we are searching for, since they will not match - // anyway, so don't traverse unless inputIndex < length. - if (isAlike && (-1 != childrenNodePos) && (inputIndex < length)) { - // Save position for this depth, to get back to this once children are done - mStackChildCount[depth] = charGroupIndex; - mStackSiblingPos[depth] = siblingPos; - // Prepare stack values for next depth - ++depth; - int childrenPos = childrenNodePos; - mStackChildCount[depth] = - BinaryFormat::getGroupCountAndForwardPointer(root, &childrenPos); - mStackSiblingPos[depth] = childrenPos; - mStackInputIndex[depth] = inputIndex; - pos = childrenPos; - // Go to the next depth level. - ++depth; - break; - } else { - // No match, or no children, or word too long to ever match: go the next sibling. - pos = siblingPos; - } - } - --depth; - } - return maxFreq; -} - -bool UnigramDictionary::isValidWord(const uint16_t* const inWord, const int length) const { - return NOT_VALID_WORD != BinaryFormat::getTerminalPosition(DICT_ROOT, inWord, length); -} - -// TODO: remove this function. -int UnigramDictionary::getBigramPosition(int pos, unsigned short *word, int offset, - int length) const { - return -1; -} - -// ProcessCurrentNode returns a boolean telling whether to traverse children nodes or not. -// If the return value is false, then the caller should read in the output "nextSiblingPosition" -// to find out the address of the next sibling node and pass it to a new call of processCurrentNode. -// It is worthy to note that when false is returned, the output values other than -// nextSiblingPosition are undefined. -// If the return value is true, then the caller must proceed to traverse the children of this -// node. processCurrentNode will output the information about the children: their count in -// newCount, their position in newChildrenPosition, the traverseAllNodes flag in -// newTraverseAllNodes, the match weight into newMatchRate, the input index into newInputIndex, the -// diffs into newDiffs, the sibling position in nextSiblingPosition, and the output index into -// newOutputIndex. Please also note the following caveat: processCurrentNode does not know when -// there aren't any more nodes at this level, it merely returns the address of the first byte after -// the current node in nextSiblingPosition. Thus, the caller must keep count of the nodes at any -// 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) { - if (DEBUG_DICT) { - correction->checkState(); - } - int pos = initialPos; - - // Flags contain the following information: - // - Address type (MASK_GROUP_ADDRESS_TYPE) on two bits: - // - FLAG_GROUP_ADDRESS_TYPE_{ONE,TWO,THREE}_BYTES means there are children and their address - // is on the specified number of bytes. - // - FLAG_GROUP_ADDRESS_TYPE_NOADDRESS means there are no children, and therefore no address. - // - FLAG_HAS_MULTIPLE_CHARS: whether this node has multiple char or not. - // - FLAG_IS_TERMINAL: whether this node is a terminal or not (it may still have children) - // - FLAG_HAS_BIGRAMS: whether this node has bigrams or not - const uint8_t flags = BinaryFormat::getFlagsAndForwardPointer(DICT_ROOT, &pos); - const bool hasMultipleChars = (0 != (FLAG_HAS_MULTIPLE_CHARS & flags)); - const bool isTerminalNode = (0 != (FLAG_IS_TERMINAL & flags)); - - bool needsToInvokeOnTerminal = false; - - // This gets only ONE character from the stream. Next there will be: - // if FLAG_HAS_MULTIPLE CHARS: the other characters of the same node - // else if FLAG_IS_TERMINAL: the frequency - // else if MASK_GROUP_ADDRESS_TYPE is not NONE: the children address - // Note that you can't have a node that both is not a terminal and has no children. - int32_t c = BinaryFormat::getCharCodeAndForwardPointer(DICT_ROOT, &pos); - assert(NOT_A_CHARACTER != c); - - // We are going to loop through each character and make it look like it's a different - // node each time. To do that, we will process characters in this node in order until - // we find the character terminator. This is signalled by getCharCode* returning - // NOT_A_CHARACTER. - // As a special case, if there is only one character in this node, we must not read the - // next bytes so we will simulate the NOT_A_CHARACTER return by testing the flags. - // This way, each loop run will look like a "virtual node". - do { - // We prefetch the next char. If 'c' is the last char of this node, we will have - // NOT_A_CHARACTER in the next char. From this we can decide whether this virtual node - // should behave as a terminal or not and whether we have children. - const int32_t nextc = hasMultipleChars - ? BinaryFormat::getCharCodeAndForwardPointer(DICT_ROOT, &pos) : NOT_A_CHARACTER; - const bool isLastChar = (NOT_A_CHARACTER == nextc); - // If there are more chars in this nodes, then this virtual node is not a terminal. - // If we are on the last char, this virtual node is a terminal if this node is. - const bool isTerminal = isLastChar && isTerminalNode; - - Correction::CorrectionType stateType = correction->processCharAndCalcState( - c, isTerminal); - if (stateType == Correction::TRAVERSE_ALL_ON_TERMINAL - || stateType == Correction::ON_TERMINAL) { - needsToInvokeOnTerminal = true; - } else if (stateType == Correction::UNRELATED) { - // 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 - // characters in this node, the frequency if it's there, read the next sibling - // position to output it, then return false. - // We don't have to output other values because we return false, as in - // "don't traverse children". - if (!isLastChar) { - pos = BinaryFormat::skipOtherCharacters(DICT_ROOT, pos); - } - pos = BinaryFormat::skipFrequency(flags, pos); - *nextSiblingPosition = - BinaryFormat::skipChildrenPosAndAttributes(DICT_ROOT, flags, pos); - return false; - } - - // Prepare for the next character. Promote the prefetched char to current char - the loop - // will take care of prefetching the next. If we finally found our last char, nextc will - // contain NOT_A_CHARACTER. - c = nextc; - } 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); - } - - // 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. - const bool hasChildren = BinaryFormat::hasChildrenInFlags(flags); - - // This character matched the typed character (enough to traverse the node at least) - // so we just evaluated it. Now we should evaluate this virtual node's children - that - // is, if it has any. If it has no children, we're done here - so we skip the end of - // the node, output the siblings position, and return false "don't traverse children". - // Note that !hasChildren implies isLastChar, so we know we don't have to skip any - // remaining char in this group for there can't be any. - if (!hasChildren) { - pos = BinaryFormat::skipFrequency(flags, pos); - *nextSiblingPosition = - BinaryFormat::skipChildrenPosAndAttributes(DICT_ROOT, flags, pos); - return false; - } - - // Optimization: Prune out words that are too long compared to how much was typed. - if (correction->needsToPrune()) { - pos = BinaryFormat::skipFrequency(flags, pos); - *nextSiblingPosition = - BinaryFormat::skipChildrenPosAndAttributes(DICT_ROOT, flags, pos); - if (DEBUG_DICT_FULL) { - LOGI("Traversing was pruned."); - } - return false; - } - } - - // Now we finished processing this node, and we want to traverse children. If there are no - // children, we can't come here. - assert(BinaryFormat::hasChildrenInFlags(flags)); - - // If this node was a terminal it still has the frequency under the pointer (it may have been - // read, but not skipped - see readFrequencyWithoutMovingPointer). - // Next come the children position, then possibly attributes (attributes are bigrams only for - // now, maybe something related to shortcuts in the future). - // Once this is read, we still need to output the number of nodes in the immediate children of - // this node, so we read and output it before returning true, as in "please traverse children". - pos = BinaryFormat::skipFrequency(flags, pos); - int childrenPos = BinaryFormat::readChildrenPosition(DICT_ROOT, flags, pos); - *nextSiblingPosition = BinaryFormat::skipChildrenPosAndAttributes(DICT_ROOT, flags, pos); - *newCount = BinaryFormat::getGroupCountAndForwardPointer(DICT_ROOT, &childrenPos); - *newChildrenPosition = childrenPos; - return true; -} - -} // namespace latinime 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/compat/ArraysCompatUtilsTests.java b/tests/src/com/android/inputmethod/compat/ArraysCompatUtilsTests.java deleted file mode 100644 index 93681b616..000000000 --- a/tests/src/com/android/inputmethod/compat/ArraysCompatUtilsTests.java +++ /dev/null @@ -1,103 +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; - -import android.test.AndroidTestCase; - -public class ArraysCompatUtilsTests extends AndroidTestCase { - // See {@link tests.api.java.util.ArraysTest}. - private static final int ARRAY_SIZE = 100; - private final int[] mIntArray = new int[ARRAY_SIZE]; - - @Override - protected void setUp() throws Exception { - super.setUp(); - for (int counter = 0; counter < ARRAY_SIZE; counter++) { - mIntArray[counter] = counter; - } - } - - public void testEmptyArray() { - final int index = ArraysCompatUtils.binarySearch(mIntArray, 0, 0, 0); - assertEquals("empty", ~0, index); - final int compat = ArraysCompatUtils.compatBinarySearch(mIntArray, 0, 0, 0); - assertEquals("empty compat", ~0, compat); - } - - public void testEmptyRangeArray() { - final int mid = ARRAY_SIZE / 3; - final int index = ArraysCompatUtils.binarySearch(mIntArray, mid, mid, 1); - assertEquals("empty", ~mid, index); - final int compat = ArraysCompatUtils.compatBinarySearch(mIntArray, mid, mid, 1); - assertEquals("empty compat", ~mid, compat); - } - - public void testFind() { - for (int counter = 0; counter < ARRAY_SIZE; counter++) { - final int index = ArraysCompatUtils.binarySearch(mIntArray, 0, ARRAY_SIZE, counter); - assertEquals("found", counter, index); - } - for (int counter = 0; counter < ARRAY_SIZE; counter++) { - final int compat = ArraysCompatUtils.compatBinarySearch( - mIntArray, 0, ARRAY_SIZE, counter); - assertEquals("found compat", counter, compat); - } - } - - public void testFindNegative() { - final int offset = ARRAY_SIZE / 2; - for (int counter = 0; counter < ARRAY_SIZE; counter++) { - mIntArray[counter] -= offset; - } - for (int counter = 0; counter < ARRAY_SIZE; counter++) { - final int index = ArraysCompatUtils.binarySearch( - mIntArray, 0, ARRAY_SIZE, counter - offset); - assertEquals("found", counter, index); - } - for (int counter = 0; counter < ARRAY_SIZE; counter++) { - final int compat = ArraysCompatUtils.compatBinarySearch( - mIntArray, 0, ARRAY_SIZE, counter - offset); - assertEquals("found compat", counter, compat); - } - } - - public void testNotFountAtTop() { - final int index = ArraysCompatUtils.binarySearch(mIntArray, 0, ARRAY_SIZE, -1); - assertEquals("not found top", ~0, index); - final int compat = ArraysCompatUtils.compatBinarySearch( - mIntArray, 0, ARRAY_SIZE, -1); - assertEquals("not found top compat", ~0, compat); - } - - public void testNotFountAtEnd() { - final int index = ArraysCompatUtils.binarySearch(mIntArray, 0, ARRAY_SIZE, ARRAY_SIZE); - assertEquals("not found end", ~ARRAY_SIZE, index); - final int compat = ArraysCompatUtils.compatBinarySearch( - mIntArray, 0, ARRAY_SIZE, ARRAY_SIZE); - assertEquals("not found end compat", ~ARRAY_SIZE, compat); - } - - public void testNotFountAtMid() { - final int mid = ARRAY_SIZE / 3; - mIntArray[mid] = mIntArray[mid + 1]; - final int index = ArraysCompatUtils.binarySearch(mIntArray, 0, ARRAY_SIZE, mid); - assertEquals("not found mid", ~mid, index); - final int compat = ArraysCompatUtils.compatBinarySearch( - mIntArray, 0, ARRAY_SIZE, mid); - assertEquals("not found mid compat", ~mid, compat); - } -} 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/BlueUnderlineTests.java b/tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java new file mode 100644 index 000000000..81f744da9 --- /dev/null +++ b/tests/src/com/android/inputmethod/latin/BlueUnderlineTests.java @@ -0,0 +1,102 @@ +/* + * 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.keyboard.Keyboard; + +public class BlueUnderlineTests extends InputTestsBase { + + 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); + } +} 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/InputLogicFrenchTests.java b/tests/src/com/android/inputmethod/latin/InputLogicFrenchTests.java new file mode 100644 index 000000000..5db120d82 --- /dev/null +++ b/tests/src/com/android/inputmethod/latin/InputLogicFrenchTests.java @@ -0,0 +1,59 @@ +/* + * 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.keyboard.Keyboard; + +public class InputLogicFrenchTests extends InputTestsBase { + + 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 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()); + } +} 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..11eb6ab19 --- /dev/null +++ b/tests/src/com/android/inputmethod/latin/InputLogicTests.java @@ -0,0 +1,233 @@ +/* + * 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.keyboard.Keyboard; + +public class InputLogicTests extends InputTestsBase { + + 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 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 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 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()); + } + // TODO: Add some tests for non-BMP characters +} diff --git a/tests/src/com/android/inputmethod/latin/InputTestsBase.java b/tests/src/com/android/inputmethod/latin/InputTestsBase.java new file mode 100644 index 000000000..5f6b229dd --- /dev/null +++ b/tests/src/com/android/inputmethod/latin/InputTestsBase.java @@ -0,0 +1,260 @@ +/* + * 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.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.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputConnection; +import android.view.inputmethod.InputMethodInfo; +import android.view.inputmethod.InputMethodManager; +import android.view.inputmethod.InputMethodSubtype; +import android.widget.FrameLayout; +import android.widget.TextView; + +import com.android.inputmethod.keyboard.Key; +import com.android.inputmethod.keyboard.Keyboard; +import com.android.inputmethod.keyboard.KeyboardActionListener; + +import java.util.HashMap; + +public class InputTestsBase extends ServiceTestCase<LatinIME> { + + private static final String PREF_DEBUG_MODE = "debug_mode"; + + // The message that sets the underline is posted with a 100 ms delay + protected static final int DELAY_TO_WAIT_FOR_UNDERLINE = 200; + + protected LatinIME mLatinIME; + protected Keyboard mKeyboard; + protected TextView mTextView; + protected InputConnection mInputConnection; + private final HashMap<String, InputMethodSubtype> mSubtypeMap = + new HashMap<String, InputMethodSubtype>(); + + // A helper class to ease span tests + public 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()); + } + } + + public InputTestsBase() { + super(LatinIME.class); + } + + // returns the previous setting value + protected 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); + initSubtypeMap(); + 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; + mKeyboard = mLatinIME.mKeyboardSwitcher.getKeyboard(); + changeLanguage("en_US"); + } + + private void initSubtypeMap() { + final InputMethodManager imm = (InputMethodManager)mLatinIME.getSystemService( + Context.INPUT_METHOD_SERVICE); + final String packageName = mLatinIME.getPackageName(); + for (final InputMethodInfo imi : imm.getEnabledInputMethodList()) { + if (imi.getPackageName().equals(packageName)) { + for (final InputMethodSubtype ims : + imm.getEnabledInputMethodSubtypeList(imi, true)) { + final String locale = ims.getLocale(); + mSubtypeMap.put(locale, ims); + } + return; + } + } + fail("LatinIME is disabled"); + } + + // 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. + protected 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. + protected 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); + for (final Key key : mKeyboard.mKeys) { + if (key.mCode == codePoint) { + final int x = key.mX + key.mWidth / 2; + final int y = key.mY + key.mHeight / 2; + mLatinIME.onCodeInput(codePoint, x, y); + return; + } + } + mLatinIME.onCodeInput(codePoint, + KeyboardActionListener.NOT_A_TOUCH_COORDINATE, + KeyboardActionListener.NOT_A_TOUCH_COORDINATE); + //mLatinIME.onReleaseKey(codePoint, false); + } + + protected void type(final String stringToType) { + for (int i = 0; i < stringToType.length(); i = stringToType.offsetByCodePoints(i, 1)) { + type(stringToType.codePointAt(i)); + } + } + + protected 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"); + } + } + + protected void changeLanguage(final String locale) { + final InputMethodSubtype subtype = mSubtypeMap.get(locale); + if (subtype == null) { + fail("InputMethodSubtype for locale " + locale + " is not enabled"); + } + SubtypeSwitcher.getInstance().updateSubtype(subtype); + waitForDictionaryToBeLoaded(); + } + + + // Helper to avoid writing the try{}catch block each time + protected static void sleep(final int milliseconds) { + try { + Thread.sleep(milliseconds); + } catch (InterruptedException e) {} + } +} diff --git a/tests/src/com/android/inputmethod/latin/PunctuationTests.java b/tests/src/com/android/inputmethod/latin/PunctuationTests.java new file mode 100644 index 000000000..1b5b72ff8 --- /dev/null +++ b/tests/src/com/android/inputmethod/latin/PunctuationTests.java @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.android.inputmethod.latin; + +public class PunctuationTests extends InputTestsBase { + + 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 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 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 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()); + } +} diff --git a/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java b/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java index fec3e8ee1..089fdc52c 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,33 @@ 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()); + if (locale.getLanguage().equals("zz")) { + // This is special language name for language agnostic usage. + continue; + } + 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/Android.mk b/tools/makedict/Android.mk index 6832b1cb6..dcfad19f0 100644 --- a/tools/makedict/Android.mk +++ b/tools/makedict/Android.mk @@ -12,11 +12,14 @@ # WITHOUT 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) -LOCAL_SRC_FILES := $(call all-java-files-under,src) +MAKEDICT_CORE_SOURCE_DIRECTORY := ../../java/src/com/android/inputmethod/latin/makedict + +LOCAL_SRC_FILES := $(call all-java-files-under,$(MAKEDICT_CORE_SOURCE_DIRECTORY)) +LOCAL_SRC_FILES += $(call all-java-files-under,src) LOCAL_SRC_FILES += $(call all-java-files-under,tests) LOCAL_JAR_MANIFEST := etc/manifest.txt LOCAL_MODULE_TAGS := eng diff --git a/tools/makedict/etc/manifest.txt b/tools/makedict/etc/manifest.txt index 948609da6..4f085e7c8 100644 --- a/tools/makedict/etc/manifest.txt +++ b/tools/makedict/etc/manifest.txt @@ -1 +1 @@ -Main-Class: com.android.inputmethod.latin.DictionaryMaker +Main-Class: com.android.inputmethod.latin.makedict.DictionaryMaker diff --git a/tools/makedict/src/com/android/inputmethod/latin/DictionaryMaker.java b/tools/makedict/src/com/android/inputmethod/latin/makedict/DictionaryMaker.java index 1ba01075e..5e3921573 100644 --- a/tools/makedict/src/com/android/inputmethod/latin/DictionaryMaker.java +++ b/tools/makedict/src/com/android/inputmethod/latin/makedict/DictionaryMaker.java @@ -14,7 +14,7 @@ * the License. */ -package com.android.inputmethod.latin; +package com.android.inputmethod.latin.makedict; import java.io.File; import java.io.FileInputStream; @@ -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/XmlDictInputOutput.java b/tools/makedict/src/com/android/inputmethod/latin/makedict/XmlDictInputOutput.java index 35a7b51d6..1d45fd25f 100644 --- a/tools/makedict/src/com/android/inputmethod/latin/XmlDictInputOutput.java +++ b/tools/makedict/src/com/android/inputmethod/latin/makedict/XmlDictInputOutput.java @@ -14,9 +14,9 @@ * the License. */ -package com.android.inputmethod.latin; +package com.android.inputmethod.latin.makedict; -import com.android.inputmethod.latin.FusionDictionary.WeightedString; +import com.android.inputmethod.latin.makedict.FusionDictionary.WeightedString; import java.io.IOException; import java.io.InputStream; @@ -40,10 +40,15 @@ import org.xml.sax.helpers.DefaultHandler; */ public class XmlDictInputOutput { + private static final String ROOT_TAG = "wordlist"; 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 +66,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 +75,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; @@ -89,6 +97,11 @@ public class XmlDictInputOutput { mFreq = Integer.parseInt(attrs.getValue(attrIndex)); } } + } else if (ROOT_TAG.equals(localName)) { + for (int attrIndex = 0; attrIndex < attrs.getLength(); ++attrIndex) { + final String attrName = attrs.getLocalName(attrIndex); + mDictionary.mOptions.mAttributes.put(attrName, attrs.getValue(attrIndex)); + } } else { mState = UNKNOWN; } @@ -107,47 +120,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 +220,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 +233,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; } @@ -203,10 +281,27 @@ public class XmlDictInputOutput { set.add(word); } // TODO: use an XMLSerializer if this gets big - destination.write("<wordlist format=\"2\">\n"); + destination.write("<wordlist format=\"2\""); + final HashMap<String, String> options = dict.mOptions.mAttributes; + for (final String key : dict.mOptions.mAttributes.keySet()) { + final String value = dict.mOptions.mAttributes.get(key); + destination.write(" " + key + "=\"" + value + "\""); + } + destination.write(">\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..9682c9b4e 100644 --- a/tools/makedict/tests/com/android/inputmethod/latin/BinaryDictInputOutputTest.java +++ b/tools/makedict/tests/com/android/inputmethod/latin/BinaryDictInputOutputTest.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package com.android.inputmethod.latin; +package com.android.inputmethod.latin.makedict; -import com.android.inputmethod.latin.FusionDictionary.Node; +import com.android.inputmethod.latin.makedict.FusionDictionary.Node; import java.util.ArrayList; @@ -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()) { |