diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 5222ba5f4..697dce28a 100755 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -4,9 +4,11 @@ + + android:backupAgent="LatinIMEBackupAgent" + android:killAfterRestore="false"> FindClass(ex)) { char msg[1000]; @@ -66,7 +66,7 @@ static jint latinime_BinaryDictionary_open Asset *dictAsset = am->openNonAsset(resourcePath, Asset::ACCESS_BUFFER); if (dictAsset == NULL) { - LOGE("DICT: Couldn't get asset %s\n", resourcePath); + LOGE("DICT: Couldn't get asset %s\n", resourcePath); env->ReleaseStringUTFChars(resourceString, resourcePath); return 0; } @@ -79,15 +79,15 @@ static jint latinime_BinaryDictionary_open } Dictionary *dictionary = new Dictionary(dict, typedLetterMultiplier, fullWordMultiplier); dictionary->setAsset(dictAsset); - + env->ReleaseStringUTFChars(resourceString, resourcePath); - return (jint) dictionary; + return (jint) dictionary; } static int latinime_BinaryDictionary_getSuggestions( - JNIEnv *env, jobject object, jint dict, jintArray inputArray, jint arraySize, - jcharArray outputArray, jintArray frequencyArray, jint maxWordLength, jint maxWords, - jint maxAlternatives) + JNIEnv *env, jobject object, jint dict, jintArray inputArray, jint arraySize, + jcharArray outputArray, jintArray frequencyArray, jint maxWordLength, jint maxWords, + jint maxAlternatives, jint skipPos) { Dictionary *dictionary = (Dictionary*) dict; if (dictionary == NULL) @@ -96,9 +96,9 @@ static int latinime_BinaryDictionary_getSuggestions( int *frequencies = env->GetIntArrayElements(frequencyArray, NULL); int *inputCodes = env->GetIntArrayElements(inputArray, NULL); jchar *outputChars = env->GetCharArrayElements(outputArray, NULL); - + int count = dictionary->getSuggestions(inputCodes, arraySize, (unsigned short*) outputChars, frequencies, - maxWordLength, maxWords, maxAlternatives); + maxWordLength, maxWords, maxAlternatives, skipPos); env->ReleaseIntArrayElements(frequencyArray, frequencies, 0); env->ReleaseIntArrayElements(inputArray, inputCodes, JNI_ABORT); @@ -112,16 +112,16 @@ static jboolean latinime_BinaryDictionary_isValidWord { Dictionary *dictionary = (Dictionary*) dict; if (dictionary == NULL) return (jboolean) false; - + jchar *word = env->GetCharArrayElements(wordArray, NULL); 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) + (JNIEnv *env, jobject object, jint dict) { Dictionary *dictionary = (Dictionary*) dict; ((Asset*) dictionary->getAsset())->close(); @@ -131,10 +131,10 @@ static void latinime_BinaryDictionary_close // ---------------------------------------------------------------------------- static JNINativeMethod gMethods[] = { - {"openNative", "(Landroid/content/res/AssetManager;Ljava/lang/String;II)I", + {"openNative", "(Landroid/content/res/AssetManager;Ljava/lang/String;II)I", (void*)latinime_BinaryDictionary_open}, {"closeNative", "(I)V", (void*)latinime_BinaryDictionary_close}, - {"getSuggestionsNative", "(I[II[C[IIII)I", (void*)latinime_BinaryDictionary_getSuggestions}, + {"getSuggestionsNative", "(I[II[C[IIIII)I", (void*)latinime_BinaryDictionary_getSuggestions}, {"isValidWordNative", "(I[CI)Z", (void*)latinime_BinaryDictionary_isValidWord} }; @@ -153,7 +153,7 @@ static int registerNativeMethods(JNIEnv* env, const char* className, fprintf(stderr, "RegisterNatives failed for '%s'\n", className); return JNI_FALSE; } - + return JNI_TRUE; } @@ -161,21 +161,21 @@ static int registerNatives(JNIEnv *env) { const char* const kClassPathName = "com/android/inputmethod/latin/BinaryDictionary"; jclass clazz; - + clazz = env->FindClass("java/io/FileDescriptor"); if (clazz == NULL) { LOGE("Can't find %s", "java/io/FileDescriptor"); return -1; } sDescriptorField = env->GetFieldID(clazz, "descriptor", "I"); - + clazz = env->FindClass("android/content/res/AssetManager"); if (clazz == NULL) { LOGE("Can't find %s", "java/io/FileDescriptor"); return -1; } sAssetManagerNativeField = env->GetFieldID(clazz, "mObject", "I"); - + return registerNativeMethods(env, kClassPathName, gMethods, sizeof(gMethods) / sizeof(gMethods[0])); } diff --git a/dictionary/src/dictionary.cpp b/dictionary/src/dictionary.cpp index b37f4c926..cc711f419 100644 --- a/dictionary/src/dictionary.cpp +++ b/dictionary/src/dictionary.cpp @@ -49,11 +49,8 @@ Dictionary::~Dictionary() } int Dictionary::getSuggestions(int *codes, int codesSize, unsigned short *outWords, int *frequencies, - int maxWordLength, int maxWords, int maxAlternatives) + int maxWordLength, int maxWords, int maxAlternatives, int skipPos) { - memset(frequencies, 0, maxWords * sizeof(*frequencies)); - memset(outWords, 0, maxWords * maxWordLength * sizeof(*outWords)); - mFrequencies = frequencies; mOutputChars = outWords; mInputCodes = codes; @@ -62,8 +59,10 @@ int Dictionary::getSuggestions(int *codes, int codesSize, unsigned short *outWor mMaxWordLength = maxWordLength; mMaxWords = maxWords; mWords = 0; + mSkipPos = skipPos; + mMaxEditDistance = mInputLength < 5 ? 2 : mInputLength / 2; - getWordsRec(0, 0, mInputLength * 3, false, 1, 0); + getWordsRec(0, 0, mInputLength * 3, false, 1, 0, 0); if (DEBUG_DICT) LOGI("Returning %d words", mWords); return mWords; @@ -110,7 +109,11 @@ bool Dictionary::addWord(unsigned short *word, int length, int frequency) { word[length] = 0; - if (DEBUG_DICT) LOGI("Found word = %s, freq = %d : \n", word, frequency); + if (DEBUG_DICT) { + char s[length + 1]; + for (int i = 0; i <= length; i++) s[i] = word[i]; + LOGI("Found word = %s, freq = %d : \n", s, frequency); + } // Find the right insertion point int insertAt = 0; @@ -144,16 +147,14 @@ Dictionary::addWord(unsigned short *word, int length, int frequency) } unsigned short -Dictionary::toLowerCase(unsigned short c, const int depth) { +Dictionary::toLowerCase(unsigned short c) { if (c < sizeof(BASE_CHARS) / sizeof(BASE_CHARS[0])) { c = BASE_CHARS[c]; } - if (depth == 0) { - if (c >='A' && c <= 'Z') { - c |= 32; - } else if (c > 127) { - c = u_tolower(c); - } + if (c >='A' && c <= 'Z') { + c |= 32; + } else if (c > 127) { + c = u_tolower(c); } return c; } @@ -178,12 +179,16 @@ Dictionary::sameAsTyped(unsigned short *word, int length) static char QUOTE = '\''; void -Dictionary::getWordsRec(int pos, int depth, int maxDepth, bool completion, int snr, int inputIndex) +Dictionary::getWordsRec(int pos, int depth, int maxDepth, bool completion, int snr, int inputIndex, + int diffs) { // Optimization: Prune out words that are too long compared to how much was typed. if (depth > maxDepth) { return; } + if (diffs > mMaxEditDistance) { + return; + } int count = getCount(&pos); int *currentChars = NULL; if (mInputLength <= inputIndex) { @@ -194,7 +199,7 @@ Dictionary::getWordsRec(int pos, int depth, int maxDepth, bool completion, int s for (int i = 0; i < count; i++) { unsigned short c = getChar(&pos); - unsigned short lowerC = toLowerCase(c, depth); + unsigned short lowerC = toLowerCase(c); bool terminal = getTerminal(&pos); int childrenAddress = getAddress(&pos); int freq = 1; @@ -207,38 +212,41 @@ Dictionary::getWordsRec(int pos, int depth, int maxDepth, bool completion, int s } if (childrenAddress != 0) { getWordsRec(childrenAddress, depth + 1, maxDepth, - completion, snr, inputIndex); + completion, snr, inputIndex, diffs); } - } else if (c == QUOTE && currentChars[0] != QUOTE) { - // Skip the ' and continue deeper - mWord[depth] = QUOTE; + } else if (c == QUOTE && currentChars[0] != QUOTE || mSkipPos == depth) { + // Skip the ' or other letter and continue deeper + mWord[depth] = c; if (childrenAddress != 0) { - getWordsRec(childrenAddress, depth + 1, maxDepth, false, snr, inputIndex); + getWordsRec(childrenAddress, depth + 1, maxDepth, false, snr, inputIndex, diffs); } } else { int j = 0; while (currentChars[j] > 0) { - int addedWeight = j == 0 ? mTypedLetterMultiplier : 1; if (currentChars[j] == lowerC || currentChars[j] == c) { + int addedWeight = j == 0 ? mTypedLetterMultiplier : 1; mWord[depth] = c; if (mInputLength == inputIndex + 1) { if (terminal) { if (//INCLUDE_TYPED_WORD_IF_VALID || !sameAsTyped(mWord, depth + 1)) { - addWord(mWord, depth + 1, - (freq * snr * addedWeight * mFullWordMultiplier)); + int finalFreq = freq * snr * addedWeight; + if (mSkipPos < 0) finalFreq *= mFullWordMultiplier; + addWord(mWord, depth + 1, finalFreq); } } if (childrenAddress != 0) { getWordsRec(childrenAddress, depth + 1, - maxDepth, true, snr * addedWeight, inputIndex + 1); + maxDepth, true, snr * addedWeight, inputIndex + 1, + diffs + (j > 0)); } } else if (childrenAddress != 0) { getWordsRec(childrenAddress, depth + 1, maxDepth, - false, snr * addedWeight, inputIndex + 1); + false, snr * addedWeight, inputIndex + 1, diffs + (j > 0)); } } j++; + if (mSkipPos >= 0) break; } } } diff --git a/dictionary/src/dictionary.h b/dictionary/src/dictionary.h index b13e97795..8f195ca9a 100644 --- a/dictionary/src/dictionary.h +++ b/dictionary/src/dictionary.h @@ -32,7 +32,7 @@ class Dictionary { public: Dictionary(void *dict, int typedLetterMultipler, int fullWordMultiplier); int getSuggestions(int *codes, int codesSize, unsigned short *outWords, int *frequencies, - int maxWordLength, int maxWords, int maxAlternatives); + int maxWordLength, int maxWords, int maxAlternatives, int skipPos); bool isValidWord(unsigned short *word, int length); void setAsset(void *asset) { mAsset = asset; } void *getAsset() { return mAsset; } @@ -49,9 +49,9 @@ private: bool sameAsTyped(unsigned short *word, int length); bool addWord(unsigned short *word, int length, int frequency); - unsigned short toLowerCase(unsigned short c, int depth); + unsigned short toLowerCase(unsigned short c); void getWordsRec(int pos, int depth, int maxDepth, bool completion, int frequency, - int inputIndex); + int inputIndex, int diffs); bool isValidWordRec(int pos, unsigned short *word, int offset, int length); unsigned char *mDict; @@ -66,6 +66,8 @@ private: int mInputLength; int mMaxAlternatives; unsigned short mWord[128]; + int mSkipPos; + int mMaxEditDistance; int mFullWordMultiplier; int mTypedLetterMultiplier; diff --git a/res/drawable-en-hdpi/sym_keyboard_delete.png b/res/drawable-en-hdpi/sym_keyboard_delete.png new file mode 100755 index 000000000..569369e79 Binary files /dev/null and b/res/drawable-en-hdpi/sym_keyboard_delete.png differ diff --git a/res/drawable-en-hdpi/sym_keyboard_feedback_delete.png b/res/drawable-en-hdpi/sym_keyboard_feedback_delete.png new file mode 100755 index 000000000..ca7637552 Binary files /dev/null and b/res/drawable-en-hdpi/sym_keyboard_feedback_delete.png differ diff --git a/res/drawable-en/sym_keyboard_delete.png b/res/drawable-en-mdpi/sym_keyboard_delete.png similarity index 100% rename from res/drawable-en/sym_keyboard_delete.png rename to res/drawable-en-mdpi/sym_keyboard_delete.png diff --git a/res/drawable-en/sym_keyboard_feedback_delete.png b/res/drawable-en-mdpi/sym_keyboard_feedback_delete.png similarity index 100% rename from res/drawable-en/sym_keyboard_feedback_delete.png rename to res/drawable-en-mdpi/sym_keyboard_feedback_delete.png diff --git a/res/drawable-hdpi/btn_keyboard_key_normal.9.png b/res/drawable-hdpi/btn_keyboard_key_normal.9.png new file mode 100755 index 000000000..90b51fa63 Binary files /dev/null and b/res/drawable-hdpi/btn_keyboard_key_normal.9.png differ diff --git a/res/drawable-hdpi/btn_keyboard_key_normal_off.9.png b/res/drawable-hdpi/btn_keyboard_key_normal_off.9.png new file mode 100755 index 000000000..6ddd516e7 Binary files /dev/null and b/res/drawable-hdpi/btn_keyboard_key_normal_off.9.png differ diff --git a/res/drawable-hdpi/btn_keyboard_key_normal_on.9.png b/res/drawable-hdpi/btn_keyboard_key_normal_on.9.png new file mode 100755 index 000000000..65fdeb353 Binary files /dev/null and b/res/drawable-hdpi/btn_keyboard_key_normal_on.9.png differ diff --git a/res/drawable-hdpi/btn_keyboard_key_pressed.9.png b/res/drawable-hdpi/btn_keyboard_key_pressed.9.png new file mode 100755 index 000000000..efaad9612 Binary files /dev/null and b/res/drawable-hdpi/btn_keyboard_key_pressed.9.png differ diff --git a/res/drawable-hdpi/btn_keyboard_key_pressed_off.9.png b/res/drawable-hdpi/btn_keyboard_key_pressed_off.9.png new file mode 100755 index 000000000..439271723 Binary files /dev/null and b/res/drawable-hdpi/btn_keyboard_key_pressed_off.9.png differ diff --git a/res/drawable-hdpi/btn_keyboard_key_pressed_on.9.png b/res/drawable-hdpi/btn_keyboard_key_pressed_on.9.png new file mode 100755 index 000000000..c2cc32044 Binary files /dev/null and b/res/drawable-hdpi/btn_keyboard_key_pressed_on.9.png differ diff --git a/res/drawable-hdpi/cancel.png b/res/drawable-hdpi/cancel.png new file mode 100755 index 000000000..6585bde17 Binary files /dev/null and b/res/drawable-hdpi/cancel.png differ diff --git a/res/drawable-hdpi/candidate_feedback_background.9.png b/res/drawable-hdpi/candidate_feedback_background.9.png new file mode 100755 index 000000000..203c4e640 Binary files /dev/null and b/res/drawable-hdpi/candidate_feedback_background.9.png differ diff --git a/res/drawable-hdpi/caution.png b/res/drawable-hdpi/caution.png new file mode 100755 index 000000000..5cb6c54b9 Binary files /dev/null and b/res/drawable-hdpi/caution.png differ diff --git a/res/drawable-hdpi/dialog_bubble_step02.9.png b/res/drawable-hdpi/dialog_bubble_step02.9.png new file mode 100755 index 000000000..b338364c5 Binary files /dev/null and b/res/drawable-hdpi/dialog_bubble_step02.9.png differ diff --git a/res/drawable-hdpi/dialog_bubble_step07.9.png b/res/drawable-hdpi/dialog_bubble_step07.9.png new file mode 100755 index 000000000..94b915432 Binary files /dev/null and b/res/drawable-hdpi/dialog_bubble_step07.9.png differ diff --git a/res/drawable-hdpi/dialog_top_dark_bottom_medium.png b/res/drawable-hdpi/dialog_top_dark_bottom_medium.png new file mode 100755 index 000000000..7c79a4f90 Binary files /dev/null and b/res/drawable-hdpi/dialog_top_dark_bottom_medium.png differ diff --git a/res/drawable-hdpi/highlight_pressed.png b/res/drawable-hdpi/highlight_pressed.png new file mode 100755 index 000000000..d2276feb8 Binary files /dev/null and b/res/drawable-hdpi/highlight_pressed.png differ diff --git a/res/drawable-hdpi/ic_dialog_alert_large.png b/res/drawable-hdpi/ic_dialog_alert_large.png new file mode 100755 index 000000000..7e2646d65 Binary files /dev/null and b/res/drawable-hdpi/ic_dialog_alert_large.png differ diff --git a/res/drawable-hdpi/ic_dialog_keyboard.png b/res/drawable-hdpi/ic_dialog_keyboard.png new file mode 100755 index 000000000..c7729566c Binary files /dev/null and b/res/drawable-hdpi/ic_dialog_keyboard.png differ diff --git a/res/drawable-hdpi/ic_dialog_voice_input.png b/res/drawable-hdpi/ic_dialog_voice_input.png new file mode 100755 index 000000000..11a3cfe77 Binary files /dev/null and b/res/drawable-hdpi/ic_dialog_voice_input.png differ diff --git a/res/drawable-hdpi/ic_dialog_wave_0_0.png b/res/drawable-hdpi/ic_dialog_wave_0_0.png new file mode 100755 index 000000000..33023c3f7 Binary files /dev/null and b/res/drawable-hdpi/ic_dialog_wave_0_0.png differ diff --git a/res/drawable-hdpi/ic_dialog_wave_1_3.png b/res/drawable-hdpi/ic_dialog_wave_1_3.png new file mode 100755 index 000000000..662686c0f Binary files /dev/null and b/res/drawable-hdpi/ic_dialog_wave_1_3.png differ diff --git a/res/drawable-hdpi/ic_dialog_wave_2_3.png b/res/drawable-hdpi/ic_dialog_wave_2_3.png new file mode 100755 index 000000000..e23ada57e Binary files /dev/null and b/res/drawable-hdpi/ic_dialog_wave_2_3.png differ diff --git a/res/drawable-hdpi/ic_dialog_wave_3_3.png b/res/drawable-hdpi/ic_dialog_wave_3_3.png new file mode 100755 index 000000000..5fe5492ad Binary files /dev/null and b/res/drawable-hdpi/ic_dialog_wave_3_3.png differ diff --git a/res/drawable-hdpi/ic_dialog_wave_4_3.png b/res/drawable-hdpi/ic_dialog_wave_4_3.png new file mode 100755 index 000000000..81b803fd0 Binary files /dev/null and b/res/drawable-hdpi/ic_dialog_wave_4_3.png differ diff --git a/res/drawable-hdpi/ic_suggest_strip_scroll_left_arrow.png b/res/drawable-hdpi/ic_suggest_strip_scroll_left_arrow.png new file mode 100755 index 000000000..e375f262f Binary files /dev/null and b/res/drawable-hdpi/ic_suggest_strip_scroll_left_arrow.png differ diff --git a/res/drawable-hdpi/ic_suggest_strip_scroll_right_arrow.png b/res/drawable-hdpi/ic_suggest_strip_scroll_right_arrow.png new file mode 100755 index 000000000..d38ae7562 Binary files /dev/null and b/res/drawable-hdpi/ic_suggest_strip_scroll_right_arrow.png differ diff --git a/res/drawable-hdpi/keyboard_background.9.png b/res/drawable-hdpi/keyboard_background.9.png new file mode 100755 index 000000000..edffac5b8 Binary files /dev/null and b/res/drawable-hdpi/keyboard_background.9.png differ diff --git a/res/drawable-hdpi/keyboard_suggest_strip.9.png b/res/drawable-hdpi/keyboard_suggest_strip.9.png new file mode 100755 index 000000000..0cbb3ed86 Binary files /dev/null and b/res/drawable-hdpi/keyboard_suggest_strip.9.png differ diff --git a/res/drawable-hdpi/keyboard_suggest_strip_divider.png b/res/drawable-hdpi/keyboard_suggest_strip_divider.png new file mode 100755 index 000000000..1a03c52e6 Binary files /dev/null and b/res/drawable-hdpi/keyboard_suggest_strip_divider.png differ diff --git a/res/drawable-hdpi/mic_slash.png b/res/drawable-hdpi/mic_slash.png new file mode 100755 index 000000000..87153dc33 Binary files /dev/null and b/res/drawable-hdpi/mic_slash.png differ diff --git a/res/drawable-hdpi/ok_cancel.png b/res/drawable-hdpi/ok_cancel.png new file mode 100755 index 000000000..6a99528ef Binary files /dev/null and b/res/drawable-hdpi/ok_cancel.png differ diff --git a/res/drawable-hdpi/speak_now_level0.png b/res/drawable-hdpi/speak_now_level0.png new file mode 100755 index 000000000..5c5ca309d Binary files /dev/null and b/res/drawable-hdpi/speak_now_level0.png differ diff --git a/res/drawable-hdpi/speak_now_level1.png b/res/drawable-hdpi/speak_now_level1.png new file mode 100755 index 000000000..4d5f7d6bb Binary files /dev/null and b/res/drawable-hdpi/speak_now_level1.png differ diff --git a/res/drawable-hdpi/speak_now_level2.png b/res/drawable-hdpi/speak_now_level2.png new file mode 100755 index 000000000..be5a7d37a Binary files /dev/null and b/res/drawable-hdpi/speak_now_level2.png differ diff --git a/res/drawable-hdpi/speak_now_level3.png b/res/drawable-hdpi/speak_now_level3.png new file mode 100755 index 000000000..82968f476 Binary files /dev/null and b/res/drawable-hdpi/speak_now_level3.png differ diff --git a/res/drawable-hdpi/speak_now_level4.png b/res/drawable-hdpi/speak_now_level4.png new file mode 100755 index 000000000..e8ce7bd7f Binary files /dev/null and b/res/drawable-hdpi/speak_now_level4.png differ diff --git a/res/drawable-hdpi/speak_now_level5.png b/res/drawable-hdpi/speak_now_level5.png new file mode 100755 index 000000000..77d0b8e9b Binary files /dev/null and b/res/drawable-hdpi/speak_now_level5.png differ diff --git a/res/drawable-hdpi/sym_keyboard_delete.png b/res/drawable-hdpi/sym_keyboard_delete.png new file mode 100755 index 000000000..59d78bec0 Binary files /dev/null and b/res/drawable-hdpi/sym_keyboard_delete.png differ diff --git a/res/drawable-hdpi/sym_keyboard_done.png b/res/drawable-hdpi/sym_keyboard_done.png new file mode 100755 index 000000000..471c5021b Binary files /dev/null and b/res/drawable-hdpi/sym_keyboard_done.png differ diff --git a/res/drawable-hdpi/sym_keyboard_feedback_delete.png b/res/drawable-hdpi/sym_keyboard_feedback_delete.png new file mode 100755 index 000000000..ca7637552 Binary files /dev/null and b/res/drawable-hdpi/sym_keyboard_feedback_delete.png differ diff --git a/res/drawable-hdpi/sym_keyboard_feedback_done.png b/res/drawable-hdpi/sym_keyboard_feedback_done.png new file mode 100755 index 000000000..7015e266a Binary files /dev/null and b/res/drawable-hdpi/sym_keyboard_feedback_done.png differ diff --git a/res/drawable-hdpi/sym_keyboard_feedback_numalt.png b/res/drawable-hdpi/sym_keyboard_feedback_numalt.png new file mode 100755 index 000000000..728c6f7d4 Binary files /dev/null and b/res/drawable-hdpi/sym_keyboard_feedback_numalt.png differ diff --git a/res/drawable-hdpi/sym_keyboard_feedback_return.png b/res/drawable-hdpi/sym_keyboard_feedback_return.png new file mode 100755 index 000000000..ae57299e4 Binary files /dev/null and b/res/drawable-hdpi/sym_keyboard_feedback_return.png differ diff --git a/res/drawable-hdpi/sym_keyboard_feedback_search.png b/res/drawable-hdpi/sym_keyboard_feedback_search.png new file mode 100755 index 000000000..d931b39e2 Binary files /dev/null and b/res/drawable-hdpi/sym_keyboard_feedback_search.png differ diff --git a/res/drawable-hdpi/sym_keyboard_feedback_shift.png b/res/drawable-hdpi/sym_keyboard_feedback_shift.png new file mode 100755 index 000000000..4db31c849 Binary files /dev/null and b/res/drawable-hdpi/sym_keyboard_feedback_shift.png differ diff --git a/res/drawable-hdpi/sym_keyboard_feedback_shift_locked.png b/res/drawable-hdpi/sym_keyboard_feedback_shift_locked.png new file mode 100755 index 000000000..3fd5659fd Binary files /dev/null and b/res/drawable-hdpi/sym_keyboard_feedback_shift_locked.png differ diff --git a/res/drawable-hdpi/sym_keyboard_feedback_space.png b/res/drawable-hdpi/sym_keyboard_feedback_space.png new file mode 100755 index 000000000..98266ee52 Binary files /dev/null and b/res/drawable-hdpi/sym_keyboard_feedback_space.png differ diff --git a/res/drawable-hdpi/sym_keyboard_num0.png b/res/drawable-hdpi/sym_keyboard_num0.png new file mode 100755 index 000000000..10ac70b9d Binary files /dev/null and b/res/drawable-hdpi/sym_keyboard_num0.png differ diff --git a/res/drawable-hdpi/sym_keyboard_num1.png b/res/drawable-hdpi/sym_keyboard_num1.png new file mode 100755 index 000000000..0fc03efa5 Binary files /dev/null and b/res/drawable-hdpi/sym_keyboard_num1.png differ diff --git a/res/drawable-hdpi/sym_keyboard_num2.png b/res/drawable-hdpi/sym_keyboard_num2.png new file mode 100755 index 000000000..283560b35 Binary files /dev/null and b/res/drawable-hdpi/sym_keyboard_num2.png differ diff --git a/res/drawable-hdpi/sym_keyboard_num3.png b/res/drawable-hdpi/sym_keyboard_num3.png new file mode 100755 index 000000000..9a3b3294b Binary files /dev/null and b/res/drawable-hdpi/sym_keyboard_num3.png differ diff --git a/res/drawable-hdpi/sym_keyboard_num4.png b/res/drawable-hdpi/sym_keyboard_num4.png new file mode 100755 index 000000000..f13ff1ae9 Binary files /dev/null and b/res/drawable-hdpi/sym_keyboard_num4.png differ diff --git a/res/drawable-hdpi/sym_keyboard_num5.png b/res/drawable-hdpi/sym_keyboard_num5.png new file mode 100755 index 000000000..c251329fa Binary files /dev/null and b/res/drawable-hdpi/sym_keyboard_num5.png differ diff --git a/res/drawable-hdpi/sym_keyboard_num6.png b/res/drawable-hdpi/sym_keyboard_num6.png new file mode 100755 index 000000000..4acba4c91 Binary files /dev/null and b/res/drawable-hdpi/sym_keyboard_num6.png differ diff --git a/res/drawable-hdpi/sym_keyboard_num7.png b/res/drawable-hdpi/sym_keyboard_num7.png new file mode 100755 index 000000000..2246972a8 Binary files /dev/null and b/res/drawable-hdpi/sym_keyboard_num7.png differ diff --git a/res/drawable-hdpi/sym_keyboard_num8.png b/res/drawable-hdpi/sym_keyboard_num8.png new file mode 100755 index 000000000..d4973fdc9 Binary files /dev/null and b/res/drawable-hdpi/sym_keyboard_num8.png differ diff --git a/res/drawable-hdpi/sym_keyboard_num9.png b/res/drawable-hdpi/sym_keyboard_num9.png new file mode 100755 index 000000000..49cec66f4 Binary files /dev/null and b/res/drawable-hdpi/sym_keyboard_num9.png differ diff --git a/res/drawable-hdpi/sym_keyboard_numalt.png b/res/drawable-hdpi/sym_keyboard_numalt.png new file mode 100755 index 000000000..3cc5311cd Binary files /dev/null and b/res/drawable-hdpi/sym_keyboard_numalt.png differ diff --git a/res/drawable-hdpi/sym_keyboard_numpound.png b/res/drawable-hdpi/sym_keyboard_numpound.png new file mode 100755 index 000000000..d09133929 Binary files /dev/null and b/res/drawable-hdpi/sym_keyboard_numpound.png differ diff --git a/res/drawable-hdpi/sym_keyboard_numstar.png b/res/drawable-hdpi/sym_keyboard_numstar.png new file mode 100755 index 000000000..e838e169f Binary files /dev/null and b/res/drawable-hdpi/sym_keyboard_numstar.png differ diff --git a/res/drawable-hdpi/sym_keyboard_return.png b/res/drawable-hdpi/sym_keyboard_return.png new file mode 100755 index 000000000..58505c5e0 Binary files /dev/null and b/res/drawable-hdpi/sym_keyboard_return.png differ diff --git a/res/drawable-hdpi/sym_keyboard_search.png b/res/drawable-hdpi/sym_keyboard_search.png new file mode 100755 index 000000000..e72cde3bb Binary files /dev/null and b/res/drawable-hdpi/sym_keyboard_search.png differ diff --git a/res/drawable-hdpi/sym_keyboard_shift.png b/res/drawable-hdpi/sym_keyboard_shift.png new file mode 100755 index 000000000..814908178 Binary files /dev/null and b/res/drawable-hdpi/sym_keyboard_shift.png differ diff --git a/res/drawable-hdpi/sym_keyboard_shift_locked.png b/res/drawable-hdpi/sym_keyboard_shift_locked.png new file mode 100755 index 000000000..31ca27718 Binary files /dev/null and b/res/drawable-hdpi/sym_keyboard_shift_locked.png differ diff --git a/res/drawable-hdpi/sym_keyboard_space.png b/res/drawable-hdpi/sym_keyboard_space.png new file mode 100755 index 000000000..3e98b3014 Binary files /dev/null and b/res/drawable-hdpi/sym_keyboard_space.png differ diff --git a/res/drawable-hdpi/voice_background.9.png b/res/drawable-hdpi/voice_background.9.png new file mode 100755 index 000000000..73fb0901e Binary files /dev/null and b/res/drawable-hdpi/voice_background.9.png differ diff --git a/res/drawable-hdpi/working.png b/res/drawable-hdpi/working.png new file mode 100755 index 000000000..8b51ed116 Binary files /dev/null and b/res/drawable-hdpi/working.png differ diff --git a/res/drawable-land-hdpi/btn_keyboard_key_normal.9.png b/res/drawable-land-hdpi/btn_keyboard_key_normal.9.png new file mode 100755 index 000000000..603bf0e15 Binary files /dev/null and b/res/drawable-land-hdpi/btn_keyboard_key_normal.9.png differ diff --git a/res/drawable-land-hdpi/btn_keyboard_key_normal_off.9.png b/res/drawable-land-hdpi/btn_keyboard_key_normal_off.9.png new file mode 100755 index 000000000..6ddd516e7 Binary files /dev/null and b/res/drawable-land-hdpi/btn_keyboard_key_normal_off.9.png differ diff --git a/res/drawable-land-hdpi/btn_keyboard_key_normal_on.9.png b/res/drawable-land-hdpi/btn_keyboard_key_normal_on.9.png new file mode 100755 index 000000000..65fdeb353 Binary files /dev/null and b/res/drawable-land-hdpi/btn_keyboard_key_normal_on.9.png differ diff --git a/res/drawable-land-hdpi/btn_keyboard_key_pressed.9.png b/res/drawable-land-hdpi/btn_keyboard_key_pressed.9.png new file mode 100755 index 000000000..7ec915fe8 Binary files /dev/null and b/res/drawable-land-hdpi/btn_keyboard_key_pressed.9.png differ diff --git a/res/drawable-land-hdpi/btn_keyboard_key_pressed_off.9.png b/res/drawable-land-hdpi/btn_keyboard_key_pressed_off.9.png new file mode 100755 index 000000000..439271723 Binary files /dev/null and b/res/drawable-land-hdpi/btn_keyboard_key_pressed_off.9.png differ diff --git a/res/drawable-land-hdpi/btn_keyboard_key_pressed_on.9.png b/res/drawable-land-hdpi/btn_keyboard_key_pressed_on.9.png new file mode 100755 index 000000000..c2cc32044 Binary files /dev/null and b/res/drawable-land-hdpi/btn_keyboard_key_pressed_on.9.png differ diff --git a/res/drawable-land-hdpi/keyboard_suggest_strip_divider.png b/res/drawable-land-hdpi/keyboard_suggest_strip_divider.png new file mode 100755 index 000000000..1a03c52e6 Binary files /dev/null and b/res/drawable-land-hdpi/keyboard_suggest_strip_divider.png differ diff --git a/res/drawable-land-mdpi/btn_keyboard_key_normal.9.png b/res/drawable-land-mdpi/btn_keyboard_key_normal.9.png new file mode 100644 index 000000000..ea2506c6d Binary files /dev/null and b/res/drawable-land-mdpi/btn_keyboard_key_normal.9.png differ diff --git a/res/drawable-land-mdpi/btn_keyboard_key_normal_off.9.png b/res/drawable-land-mdpi/btn_keyboard_key_normal_off.9.png new file mode 100644 index 000000000..bda9b8394 Binary files /dev/null and b/res/drawable-land-mdpi/btn_keyboard_key_normal_off.9.png differ diff --git a/res/drawable-land-mdpi/btn_keyboard_key_normal_on.9.png b/res/drawable-land-mdpi/btn_keyboard_key_normal_on.9.png new file mode 100644 index 000000000..0c16ed509 Binary files /dev/null and b/res/drawable-land-mdpi/btn_keyboard_key_normal_on.9.png differ diff --git a/res/drawable-land-mdpi/btn_keyboard_key_pressed.9.png b/res/drawable-land-mdpi/btn_keyboard_key_pressed.9.png new file mode 100755 index 000000000..6b5c718c7 Binary files /dev/null and b/res/drawable-land-mdpi/btn_keyboard_key_pressed.9.png differ diff --git a/res/drawable-land-mdpi/btn_keyboard_key_pressed_off.9.png b/res/drawable-land-mdpi/btn_keyboard_key_pressed_off.9.png new file mode 100644 index 000000000..bdcf06e1b Binary files /dev/null and b/res/drawable-land-mdpi/btn_keyboard_key_pressed_off.9.png differ diff --git a/res/drawable-land-mdpi/btn_keyboard_key_pressed_on.9.png b/res/drawable-land-mdpi/btn_keyboard_key_pressed_on.9.png new file mode 100644 index 000000000..79621a9e6 Binary files /dev/null and b/res/drawable-land-mdpi/btn_keyboard_key_pressed_on.9.png differ diff --git a/res/drawable-land/keyboard_suggest_strip_divider.png b/res/drawable-land-mdpi/keyboard_suggest_strip_divider.png similarity index 100% rename from res/drawable-land/keyboard_suggest_strip_divider.png rename to res/drawable-land-mdpi/keyboard_suggest_strip_divider.png diff --git a/res/drawable-land/btn_keyboard_key.xml b/res/drawable-land/btn_keyboard_key.xml new file mode 100644 index 000000000..45578e582 --- /dev/null +++ b/res/drawable-land/btn_keyboard_key.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + diff --git a/res/drawable-mdpi/btn_keyboard_key_normal.9.png b/res/drawable-mdpi/btn_keyboard_key_normal.9.png new file mode 100644 index 000000000..d0f9b7cc6 Binary files /dev/null and b/res/drawable-mdpi/btn_keyboard_key_normal.9.png differ diff --git a/res/drawable-mdpi/btn_keyboard_key_normal_off.9.png b/res/drawable-mdpi/btn_keyboard_key_normal_off.9.png new file mode 100644 index 000000000..bda9b8394 Binary files /dev/null and b/res/drawable-mdpi/btn_keyboard_key_normal_off.9.png differ diff --git a/res/drawable-mdpi/btn_keyboard_key_normal_on.9.png b/res/drawable-mdpi/btn_keyboard_key_normal_on.9.png new file mode 100644 index 000000000..0c16ed509 Binary files /dev/null and b/res/drawable-mdpi/btn_keyboard_key_normal_on.9.png differ diff --git a/res/drawable-mdpi/btn_keyboard_key_pressed.9.png b/res/drawable-mdpi/btn_keyboard_key_pressed.9.png new file mode 100755 index 000000000..91809e242 Binary files /dev/null and b/res/drawable-mdpi/btn_keyboard_key_pressed.9.png differ diff --git a/res/drawable-mdpi/btn_keyboard_key_pressed_off.9.png b/res/drawable-mdpi/btn_keyboard_key_pressed_off.9.png new file mode 100644 index 000000000..bdcf06e1b Binary files /dev/null and b/res/drawable-mdpi/btn_keyboard_key_pressed_off.9.png differ diff --git a/res/drawable-mdpi/btn_keyboard_key_pressed_on.9.png b/res/drawable-mdpi/btn_keyboard_key_pressed_on.9.png new file mode 100644 index 000000000..79621a9e6 Binary files /dev/null and b/res/drawable-mdpi/btn_keyboard_key_pressed_on.9.png differ diff --git a/res/drawable/candidate_feedback_background.9.png b/res/drawable-mdpi/candidate_feedback_background.9.png similarity index 100% rename from res/drawable/candidate_feedback_background.9.png rename to res/drawable-mdpi/candidate_feedback_background.9.png diff --git a/res/drawable/dialog_bubble_step02.9.png b/res/drawable-mdpi/dialog_bubble_step02.9.png similarity index 100% rename from res/drawable/dialog_bubble_step02.9.png rename to res/drawable-mdpi/dialog_bubble_step02.9.png diff --git a/res/drawable/dialog_bubble_step07.9.png b/res/drawable-mdpi/dialog_bubble_step07.9.png similarity index 100% rename from res/drawable/dialog_bubble_step07.9.png rename to res/drawable-mdpi/dialog_bubble_step07.9.png diff --git a/res/drawable/highlight_pressed.png b/res/drawable-mdpi/highlight_pressed.png similarity index 100% rename from res/drawable/highlight_pressed.png rename to res/drawable-mdpi/highlight_pressed.png diff --git a/res/drawable/ic_dialog_keyboard.png b/res/drawable-mdpi/ic_dialog_keyboard.png similarity index 100% rename from res/drawable/ic_dialog_keyboard.png rename to res/drawable-mdpi/ic_dialog_keyboard.png diff --git a/res/drawable/ic_suggest_strip_scroll_left_arrow.png b/res/drawable-mdpi/ic_suggest_strip_scroll_left_arrow.png similarity index 100% rename from res/drawable/ic_suggest_strip_scroll_left_arrow.png rename to res/drawable-mdpi/ic_suggest_strip_scroll_left_arrow.png diff --git a/res/drawable/ic_suggest_strip_scroll_right_arrow.png b/res/drawable-mdpi/ic_suggest_strip_scroll_right_arrow.png similarity index 100% rename from res/drawable/ic_suggest_strip_scroll_right_arrow.png rename to res/drawable-mdpi/ic_suggest_strip_scroll_right_arrow.png diff --git a/res/drawable-mdpi/keyboard_background.9.png b/res/drawable-mdpi/keyboard_background.9.png new file mode 100644 index 000000000..2bd4b628d Binary files /dev/null and b/res/drawable-mdpi/keyboard_background.9.png differ diff --git a/res/drawable/keyboard_suggest_strip.9.png b/res/drawable-mdpi/keyboard_suggest_strip.9.png similarity index 100% rename from res/drawable/keyboard_suggest_strip.9.png rename to res/drawable-mdpi/keyboard_suggest_strip.9.png diff --git a/res/drawable-mdpi/keyboard_suggest_strip_divider.png b/res/drawable-mdpi/keyboard_suggest_strip_divider.png new file mode 100644 index 000000000..c9413d7c1 Binary files /dev/null and b/res/drawable-mdpi/keyboard_suggest_strip_divider.png differ diff --git a/res/drawable/sym_keyboard_delete.png b/res/drawable-mdpi/sym_keyboard_delete.png similarity index 100% rename from res/drawable/sym_keyboard_delete.png rename to res/drawable-mdpi/sym_keyboard_delete.png diff --git a/res/drawable/sym_keyboard_done.png b/res/drawable-mdpi/sym_keyboard_done.png similarity index 100% rename from res/drawable/sym_keyboard_done.png rename to res/drawable-mdpi/sym_keyboard_done.png diff --git a/res/drawable/sym_keyboard_feedback_delete.png b/res/drawable-mdpi/sym_keyboard_feedback_delete.png similarity index 100% rename from res/drawable/sym_keyboard_feedback_delete.png rename to res/drawable-mdpi/sym_keyboard_feedback_delete.png diff --git a/res/drawable/sym_keyboard_feedback_done.png b/res/drawable-mdpi/sym_keyboard_feedback_done.png similarity index 100% rename from res/drawable/sym_keyboard_feedback_done.png rename to res/drawable-mdpi/sym_keyboard_feedback_done.png diff --git a/res/drawable/sym_keyboard_feedback_numalt.png b/res/drawable-mdpi/sym_keyboard_feedback_numalt.png similarity index 100% rename from res/drawable/sym_keyboard_feedback_numalt.png rename to res/drawable-mdpi/sym_keyboard_feedback_numalt.png diff --git a/res/drawable/sym_keyboard_feedback_return.png b/res/drawable-mdpi/sym_keyboard_feedback_return.png similarity index 100% rename from res/drawable/sym_keyboard_feedback_return.png rename to res/drawable-mdpi/sym_keyboard_feedback_return.png diff --git a/res/drawable/sym_keyboard_feedback_search.png b/res/drawable-mdpi/sym_keyboard_feedback_search.png similarity index 100% rename from res/drawable/sym_keyboard_feedback_search.png rename to res/drawable-mdpi/sym_keyboard_feedback_search.png diff --git a/res/drawable/sym_keyboard_feedback_shift.png b/res/drawable-mdpi/sym_keyboard_feedback_shift.png similarity index 100% rename from res/drawable/sym_keyboard_feedback_shift.png rename to res/drawable-mdpi/sym_keyboard_feedback_shift.png diff --git a/res/drawable/sym_keyboard_feedback_shift_locked.png b/res/drawable-mdpi/sym_keyboard_feedback_shift_locked.png similarity index 100% rename from res/drawable/sym_keyboard_feedback_shift_locked.png rename to res/drawable-mdpi/sym_keyboard_feedback_shift_locked.png diff --git a/res/drawable/sym_keyboard_feedback_space.png b/res/drawable-mdpi/sym_keyboard_feedback_space.png similarity index 100% rename from res/drawable/sym_keyboard_feedback_space.png rename to res/drawable-mdpi/sym_keyboard_feedback_space.png diff --git a/res/drawable/sym_keyboard_num0.png b/res/drawable-mdpi/sym_keyboard_num0.png similarity index 100% rename from res/drawable/sym_keyboard_num0.png rename to res/drawable-mdpi/sym_keyboard_num0.png diff --git a/res/drawable/sym_keyboard_num1.png b/res/drawable-mdpi/sym_keyboard_num1.png similarity index 100% rename from res/drawable/sym_keyboard_num1.png rename to res/drawable-mdpi/sym_keyboard_num1.png diff --git a/res/drawable/sym_keyboard_num2.png b/res/drawable-mdpi/sym_keyboard_num2.png similarity index 100% rename from res/drawable/sym_keyboard_num2.png rename to res/drawable-mdpi/sym_keyboard_num2.png diff --git a/res/drawable/sym_keyboard_num3.png b/res/drawable-mdpi/sym_keyboard_num3.png similarity index 100% rename from res/drawable/sym_keyboard_num3.png rename to res/drawable-mdpi/sym_keyboard_num3.png diff --git a/res/drawable/sym_keyboard_num4.png b/res/drawable-mdpi/sym_keyboard_num4.png similarity index 100% rename from res/drawable/sym_keyboard_num4.png rename to res/drawable-mdpi/sym_keyboard_num4.png diff --git a/res/drawable/sym_keyboard_num5.png b/res/drawable-mdpi/sym_keyboard_num5.png similarity index 100% rename from res/drawable/sym_keyboard_num5.png rename to res/drawable-mdpi/sym_keyboard_num5.png diff --git a/res/drawable/sym_keyboard_num6.png b/res/drawable-mdpi/sym_keyboard_num6.png similarity index 100% rename from res/drawable/sym_keyboard_num6.png rename to res/drawable-mdpi/sym_keyboard_num6.png diff --git a/res/drawable/sym_keyboard_num7.png b/res/drawable-mdpi/sym_keyboard_num7.png similarity index 100% rename from res/drawable/sym_keyboard_num7.png rename to res/drawable-mdpi/sym_keyboard_num7.png diff --git a/res/drawable/sym_keyboard_num8.png b/res/drawable-mdpi/sym_keyboard_num8.png similarity index 100% rename from res/drawable/sym_keyboard_num8.png rename to res/drawable-mdpi/sym_keyboard_num8.png diff --git a/res/drawable/sym_keyboard_num9.png b/res/drawable-mdpi/sym_keyboard_num9.png similarity index 100% rename from res/drawable/sym_keyboard_num9.png rename to res/drawable-mdpi/sym_keyboard_num9.png diff --git a/res/drawable/sym_keyboard_numalt.png b/res/drawable-mdpi/sym_keyboard_numalt.png similarity index 100% rename from res/drawable/sym_keyboard_numalt.png rename to res/drawable-mdpi/sym_keyboard_numalt.png diff --git a/res/drawable/sym_keyboard_numpound.png b/res/drawable-mdpi/sym_keyboard_numpound.png similarity index 100% rename from res/drawable/sym_keyboard_numpound.png rename to res/drawable-mdpi/sym_keyboard_numpound.png diff --git a/res/drawable/sym_keyboard_numstar.png b/res/drawable-mdpi/sym_keyboard_numstar.png similarity index 100% rename from res/drawable/sym_keyboard_numstar.png rename to res/drawable-mdpi/sym_keyboard_numstar.png diff --git a/res/drawable/sym_keyboard_return.png b/res/drawable-mdpi/sym_keyboard_return.png similarity index 100% rename from res/drawable/sym_keyboard_return.png rename to res/drawable-mdpi/sym_keyboard_return.png diff --git a/res/drawable/sym_keyboard_search.png b/res/drawable-mdpi/sym_keyboard_search.png similarity index 100% rename from res/drawable/sym_keyboard_search.png rename to res/drawable-mdpi/sym_keyboard_search.png diff --git a/res/drawable/sym_keyboard_shift.png b/res/drawable-mdpi/sym_keyboard_shift.png similarity index 100% rename from res/drawable/sym_keyboard_shift.png rename to res/drawable-mdpi/sym_keyboard_shift.png diff --git a/res/drawable/sym_keyboard_shift_locked.png b/res/drawable-mdpi/sym_keyboard_shift_locked.png similarity index 100% rename from res/drawable/sym_keyboard_shift_locked.png rename to res/drawable-mdpi/sym_keyboard_shift_locked.png diff --git a/res/drawable/sym_keyboard_space.png b/res/drawable-mdpi/sym_keyboard_space.png similarity index 100% rename from res/drawable/sym_keyboard_space.png rename to res/drawable-mdpi/sym_keyboard_space.png diff --git a/res/drawable/btn_keyboard_key.xml b/res/drawable/btn_keyboard_key.xml new file mode 100644 index 000000000..45578e582 --- /dev/null +++ b/res/drawable/btn_keyboard_key.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + diff --git a/res/drawable/keyboard_suggest_strip_divider.png b/res/drawable/keyboard_suggest_strip_divider.png deleted file mode 100644 index e54c5b099..000000000 Binary files a/res/drawable/keyboard_suggest_strip_divider.png and /dev/null differ diff --git a/res/layout/candidates.xml b/res/layout/candidates.xml index edd779a81..39df81dd2 100755 --- a/res/layout/candidates.xml +++ b/res/layout/candidates.xml @@ -50,7 +50,7 @@ diff --git a/res/layout/input.xml b/res/layout/input.xml index c4bcc91c3..f2f30ca84 100755 --- a/res/layout/input.xml +++ b/res/layout/input.xml @@ -24,4 +24,6 @@ android:layout_alignParentBottom="true" android:layout_width="fill_parent" android:layout_height="wrap_content" + android:background="@drawable/keyboard_background" + android:keyBackground="@drawable/btn_keyboard_key" /> diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml index 45d5464b8..29b8565ba 100644 --- a/res/values-cs/strings.xml +++ b/res/values-cs/strings.xml @@ -63,6 +63,7 @@ "ňñ" "čç" "ýÿ" + "i" "Podržením klávesy zobrazíte diakritiku (ž, á atd.)" "Stisknutím klávesy Zpět ↶ můžete klávesnici kdykoli zavřít" "Přístup k číslům a symbolům" @@ -87,4 +88,9 @@ "Zavřete klávesnici"\n\n"Stiskněte klávesu Zpět." "Přidržením klávesy zobrazte možnosti"\n\n"Použijte interpunkční znaménka a diakritiku." "Nastavení klávesnice"\n\n"Dotkněte se klávesy ""?123"" a přidržte ji." + ".com" + ".net" + ".org" + ".biz" + ".cz" diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml index 60a4f5f6f..3af5e439a 100644 --- a/res/values-da/strings.xml +++ b/res/values-da/strings.xml @@ -63,6 +63,7 @@ "ñ" "ç" "ýÿ" + "i" "Hold en tast nede for at se accenter (ø, ö osv.)" "Tryk på tilbagetasten ↶ for når som helst at lukke for tastaturet" "Få adgang til tal og symboler" @@ -83,12 +84,13 @@ "123" "ABC" "ALT" - - - - - - - - + "Åbn tastaturet"\n\n"Tryk på et hvilket som helst tekstfelt." + "Luk tastaturet"\n\n"Tryk på Tilbagetasten." + "Tryk på og hold en tast nede for valgmuligheder"\n\n"Få adgang til tegnsætning og accenter." + "Tastaturindstillinger"\n\n"Tryk på og hold tasten ""?123"" nede." + ".com" + ".net" + ".org" + ".gov" + ".edu" diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml index ca1dd626d..aa52380b6 100644 --- a/res/values-de/strings.xml +++ b/res/values-de/strings.xml @@ -63,6 +63,7 @@ "ñ" "ç" "ýÿ" + "i" "Zur Anzeige von Umlauten (ä, ö usw.) Taste gedrückt halten" "Zum Schließen der Tastatur ↶ drücken" "Auf Zahlen und Symbole zugreifen" @@ -87,4 +88,9 @@ "Tastatur schließen"\n\n"Drücken Sie die Taste \"Zurück\"." "Eine Taste für Optionen berühren und gedrückt halten"\n\n"Greifen Sie auf Satzzeichen und Akzente zu." "Tastatureinstellungen"\n\n"Berühren und halten Sie die Taste ""?123"" gedrückt." + ".com" + ".net" + ".org" + ".gov" + ".edu" diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml index 7fe65b5e0..173b384b3 100644 --- a/res/values-el/strings.xml +++ b/res/values-el/strings.xml @@ -63,6 +63,7 @@ "ñ" "ç" "ýÿ" + "i" "Κρατήστε πατημένο ένα πλήκτρο για να δείτε τους τονισμένους χαρακτήρες (ø, ö, κ.τ.λ.)" "Πατήστε το πλήκτρο Πίσω ↶ για να κλείσετε το πληκτρολόγιο ανά πάσα στιγμή" "Πρόσβαση σε αριθμούς και σύμβολα" @@ -83,12 +84,13 @@ "123" "ΑΒΓ" "ALT" - - - - - - - - + "Ανοίξτε το πληκτρολόγιο"\n\n"Αγγίξτε οποιοδήποτε πεδίο κειμένου." + "Κλείστε το πληκτρολόγιο"\n\n"Πατήστε το πλήκτρο Πίσω." + "Αγγίξτε και κρατήστε ένα πλήκτρο για ορισμό επιλογών"\n\n"Πρόσβαση στα σημεία στίξης και τονισμού." + "Ρυθμίσεις πληκτρολογίου"\n\n"Αγγίξτε και κρατήστε το πλήκτρο ""?123""." + ".com" + ".net" + ".org" + ".gov" + ".edu" diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml index d5964940f..6dee06bff 100644 --- a/res/values-es-rUS/strings.xml +++ b/res/values-es-rUS/strings.xml @@ -63,6 +63,7 @@ "ñ" "ç" "ýÿ" + "i" "Mantén una tecla presionada para ver los acentos (ø, ö, etc.)" "Pulsa la tecla hacia atrás ↶ para cerrar el teclado en cualquier momento" "Acceder a números y símbolos" @@ -83,12 +84,13 @@ "123" "ABC" "ALT" - - - - - - - - + "Abrir el teclado"\n\n"Tocar cualquier campo de texto." + "Cerrar el teclado"\n\n"Presionar la tecla Atrás." + "Tocar & y mantener presionada una tecla para las opciones"\n\n"Acceder a puntuación y acentos." + "Configuración del teclado"\n\n"Tocar & y mantener presionada la tecla ""?123""." + ".com" + ".net" + ".org" + ".gov" + ".edu" diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml index 3873bbe8f..faedf7e03 100644 --- a/res/values-es/strings.xml +++ b/res/values-es/strings.xml @@ -63,6 +63,7 @@ "ñ" "ç" "ýÿ" + "i" "Mantén pulsada una tecla para ver los caracteres acentuados (ø, ö, etc.)." "Pulsa la tecla \"Atrás\" ↶ para cerrar el teclado en cualquier momento." "Acceso a números y símbolos" @@ -87,4 +88,9 @@ "Cerrar el teclado"\n\n"Pulsa la tecla \"Atrás\"." "Mantén pulsada una tecla para acceder a las opciones."\n\n"Accede a los signos de puntuación y a los acentos." "Configuración del teclado"\n\n"Mantén pulsada la tecla ""?123""." + ".com" + ".net" + ".org" + ".gov" + ".edu" diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml index 22952737b..226c4fb0b 100644 --- a/res/values-fr/strings.xml +++ b/res/values-fr/strings.xml @@ -63,6 +63,7 @@ "ñ" "ç" "ýÿ" + "i" "Maintenir une touche enfoncée pour afficher les accents (à, é, etc.)" "Appuyez sur la touche Retour ↶ pour fermer le clavier à tout moment." "Accéder aux chiffres et symboles" @@ -87,4 +88,9 @@ "Fermer le clavier"\n\n"Appuyez sur la touche Retour." "Appuyer sur une touche de manière prolongée pour accéder aux options"\n\n"Accédez aux signes de ponctuation et aux accents." "Paramètres du clavier"\n\n"Appuyez sur la touche ""?123"" de manière prolongée." + ".com" + ".net" + ".org" + ".gouv" + ".edu" diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml index fa66568fe..62128e4c5 100644 --- a/res/values-it/strings.xml +++ b/res/values-it/strings.xml @@ -63,6 +63,7 @@ "ñ" "ç" "ýÿ" + "i" "Tieni premuto un tasto per vedere le lettere con segni diacritici (ø, ö etc.)" "Premi il tasto Indietro ↶ per chiudere la tastiera" "Accedi a numeri e simboli" @@ -87,4 +88,9 @@ "Chiusura tastiera"\n\n"Premi il tasto Indietro." "Tocca e tieni premuto un tasto per le opzioni"\n\n"Accesso a punteggiatura e accenti." "Impostazioni tastiera"\n\n"Tocca e tieni premuto il tasto ""?123""." + ".com" + ".net" + ".org" + ".gov" + ".edu" diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml index 6f590de5b..d5e7f8dc8 100644 --- a/res/values-ja/strings.xml +++ b/res/values-ja/strings.xml @@ -63,6 +63,7 @@ "ñ" "ç" "ýÿ" + "i" "キー長押しでアクセント文字を表示(ø、öなど)" "戻るキーでキーボードを閉じます" "数字と記号" @@ -87,4 +88,9 @@ "キーボードを閉じる"\n\n"[戻る]キーを押します。" "キーを長押しして選択する"\n\n"句読点キーとアクセント文字を表示します。" "キーボードの設定"\n\n"[""?123""]キーを長押しします。" + ".com" + ".net" + ".org" + ".gov" + ".edu" diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml index 0c3b970d0..570780f78 100644 --- a/res/values-ko/strings.xml +++ b/res/values-ko/strings.xml @@ -63,6 +63,7 @@ "ñ" "ç" "ýÿ" + "i" "키를 길게 누르면 악센트(ø, ö 등)가 표시됩니다." "키보드를 닫으려면 언제든지 뒤로 키(↶)를 누르세요." "숫자 및 기호 액세스" @@ -83,12 +84,13 @@ "123" "ABC" "ALT" - - - - - - - - + "키보드 열기"\n\n"아무 텍스트 입력란이나 터치하세요." + "키보드 닫기"\n\n"\'뒤로\' 키를 누르세요." + "키를 길게 터치하여 옵션 보기"\n\n"문장 부호 및 악센트 기호에 액세스하세요." + "키보드 설정"\n\n"?123"" 키를 길게 터치하세요." + ".com" + ".net" + ".org" + ".gov" + ".edu" diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml index c5c828ef6..43951552e 100644 --- a/res/values-land/dimens.xml +++ b/res/values-land/dimens.xml @@ -20,4 +20,6 @@ 47dip + 38dip + 2dip \ No newline at end of file diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml index fdaf0244a..bafc613f6 100644 --- a/res/values-nb/strings.xml +++ b/res/values-nb/strings.xml @@ -47,12 +47,9 @@ "Grunnleggende" "Avansert" - - - - - - + "0" + "1" + "2" @@ -66,6 +63,7 @@ "ñ" "ç" "ýÿ" + "i" "Hold en tast nede for å se aksenterte tegn (ø, ö, osv.)" "Trykk tilbakeknappen, ↶, for å lukke tastaturet" "Få tilgang til tall og symboler" @@ -87,7 +85,12 @@ "ABC" "ALT" "Åpne tastaturet"\n\n"Trykk på et tekstfelt." - "Lukk tastaturet"\n\n"Trykk tilbake-knappen." + "Lukke tastaturet"\n\n"Trykk på tilbaketasten." "Trykk og hold nede en tast for flere valg"\n\n"Få tilgang til skilletegn og aksenter." - "Tastaturinnstillinger"\n\n"Trykk og hold nede ""?123""-knappen." + "Innstillinger for tastatur"\n\n"Trykk på & hold ""?123""-tasten." + ".no" + ".com" + ".net" + ".org" + ".info" diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml index ab42128c2..427dcf75c 100644 --- a/res/values-nl/strings.xml +++ b/res/values-nl/strings.xml @@ -63,6 +63,7 @@ "ñ" "ç" "ýÿ" + "i" "Houd een toets ingedrukt om diakritische tekens weer te geven (ø, ö, enzovoort)" "Druk op elk gewenst moment op de toets Terug ↶ om het toetsenbord te sluiten" "Toegang tot cijfers en symbolen" @@ -87,4 +88,9 @@ "Het toetsenbord sluiten"\n\n"Druk op de terugtoets." "Een toets blijven aanraken voor opties"\n\n"Toegang tot interpunctie en diakritische tekens." "Toetsenbordinstellingen"\n\n"Blijf de toets ""?123"" aanraken." + ".com" + ".net" + ".org" + ".gov" + ".edu" diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml index bc0f7039f..663932d38 100644 --- a/res/values-pl/strings.xml +++ b/res/values-pl/strings.xml @@ -63,6 +63,7 @@ "ń" "ć" "ýÿ" + "i" "Przytrzymaj klawisz, aby wyświetlić znaki akcentowane (ą, ó itp.)" "Naciśnij klawisz cofania ↶, aby zamknąć klawiaturę w dowolnym momencie" "Przejdź do cyfr i symboli" @@ -87,4 +88,9 @@ "Zamknij klawiaturę"\n\n"Naciśnij klawisz Wróć." "Dotknij klawisza i przytrzymaj go, aby wyświetlić opcje"\n\n"Dostęp do znaków przestankowych i akcentowanych." "Ustawienia klawiatury"\n\n"Dotknij klawisza ""?123"" i przytrzymaj go." + ".com" + ".net" + ".org" + ".gov" + ".edu" diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml index 2c09a18df..da89aeca9 100644 --- a/res/values-pt-rPT/strings.xml +++ b/res/values-pt-rPT/strings.xml @@ -63,6 +63,7 @@ "ñ" "ç" "ýÿ" + "i" "Mantenha uma tecla premida para ver os acentos (ø, ö, etc.)" "Prima a tecla de retrocesso ↶ para fechar o teclado a qualquer momento" "Aceder a números e símbolos" @@ -83,12 +84,13 @@ "123" "ABC" "ALT" - - - - - - - - + "Abra o teclado"\n\n"Toque em qualquer campo de texto." + "Feche o teclado"\n\n"Prima a tecla \"Anterior\"." + "Mantenha premida uma tecla para as opções"\n\n"Aceder a pontuação e acentos." + "Definições do teclado"\n\n"Mantenha premida a tecla ""?123""." + ".com" + ".net" + ".org" + ".gov" + ".edu" diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml index 159f3f3df..978215ff4 100644 --- a/res/values-pt/strings.xml +++ b/res/values-pt/strings.xml @@ -17,8 +17,8 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Teclado Android" "Configurações de teclado Android" - "Vibrar ao pressionar a tecla" - "Som ao pressionar a tecla" + "Vibrar ao tocar a tecla" + "Som ao tocar a tecla" "Corrigir erros de digitação" "Ativar a correção de erro de entrada" "Erros de entrada de paisagem" @@ -31,7 +31,7 @@ "Conclusão automática" "Aumentar o tamanho do arquivo de texto" "Ocultar sugestões de palavra na visualização da paisagem" - "Capitalização automática" + "Capitaliz. automática" "Colocar em maiúscula o início de uma frase" "Pontuação automática" @@ -41,7 +41,7 @@ "Mostrar sugestões" "Exibir sugestões de palavras durante a digitação" "Conclusão automática" - "A barra de espaço e pontuação inserem automaticamente a palavra destacada" + "Barra de espaço e pontuação inserem a palavra destacada" "Nenhum" "Básico" @@ -63,6 +63,7 @@ "ñ" "ç" "ýÿ" + "i" "Segure uma tecla pressionada para ver os acentos (ø, ö, etc.)" "Apertar a tecla voltar ↶ para fechar o teclado, em qualquer ponto" "Acessar números e símbolos" @@ -76,19 +77,20 @@ "Tocar e segurar esta tecla para alterar as configurações do teclado, como a conclusão automática" "Experimente!" "Ir" - "Próximo" + "Avançar" "Feito" "Enviar" "?123" "123" "ABC" "ALT" - - - - - - - - + "Abra o teclado"\n\n"Toque em qualquer campo de texto." + "Feche o teclado"\n\n"Pressione a tecla Voltar." + "Toque e mantenha pressionada uma tecla para ver as opções"\n\n"Acesse a pontuação e as pronúncias." + "Configurações de teclado"\n\n"Toque e mantenha pressionada a tecla ""?123""." + ".com" + ".net" + ".org" + ".gov" + ".edu" diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml index eebe1771b..25c5d341f 100644 --- a/res/values-ru/strings.xml +++ b/res/values-ru/strings.xml @@ -63,6 +63,7 @@ "ñ" "ç" "ýÿ" + "i" "Удерживайте клавишу, чтобы увидеть варианты с диакритическими знаками (ø, ö и т.д.)" "Нажмите клавишу \"Назад\" ↶, чтобы закрыть клавиатуру в любой момент" "Открыть цифры и символы" @@ -83,12 +84,13 @@ "123" "АБВ" "ALT" - - - - - - - - + "Откройте клавиатуру"\n\n"Нажмите на любое текстовое поле." + "Закрытие клавиатуры"\n\n"Нажмите клавишу \"Назад\"." + "Нажмите и удерживайте клавишу для вызова параметров"\n\n"Доступ к пунктуационным и диакритическим знакам." + "Настройки клавиатуры"\n\n"Нажмите и удерживайте клавишу ""?123""." + ".com" + ".net" + ".org" + ".gov" + ".edu" diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml index 994d17189..38fdaf20b 100644 --- a/res/values-sv/strings.xml +++ b/res/values-sv/strings.xml @@ -63,6 +63,7 @@ "ñ" "ç" "ýÿ" + "i" "Håll nere en tangent om du vill visa accenter (ø, ö, etc.)" "Tryck på Tillbaka ↶ om du vill stänga tangentbordet" "För siffror och symboler" @@ -83,12 +84,13 @@ "123" "ABC" "ALT" - - - - - - - - + "Öppna tangentbordet"\n\n"Tryck på ett textfält." + "Stäng tangentbordet"\n\n"Tryck på Tillbaka." + "Tryck länge på en tangent om du vill se alternativ"\n\n"Använda skiljetecken och accenter." + "Tangentbordsinställningar"\n\n"Tryck länge på tangenten ""?123""." + ".com" + ".net" + ".org" + ".gov" + ".edu" diff --git a/res/values-tr/donottranslate.xml b/res/values-tr/donottranslate.xml new file mode 100644 index 000000000..f206e4c43 --- /dev/null +++ b/res/values-tr/donottranslate.xml @@ -0,0 +1,23 @@ + + + + + ğ + diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml index 33b8b79d4..fe5ee893b 100644 --- a/res/values-tr/strings.xml +++ b/res/values-tr/strings.xml @@ -31,7 +31,7 @@ "Otomatik tamamlama" "Metin alanı boyutunu artır" "Yatay görünümde kelime önerilerini gizle" - "Ot. olarak büyük harf yap" + "Otomatik olarak büyük harf yap" "Cümlenin baş harfini büyük yap" "Otomatik noktalama" @@ -56,13 +56,14 @@ "%s : Kaydedildi" "àáâãäåæ" "èéêë" - "ıìíîï" + "iìíîï" "öòóôõœø" "üùúû" "ş§ß" "ñ" "ç" "ýÿ" + "i" "Vurguları görmek için bir tuşu basılı tutun (ø, ö, v.b.)" "Klavyeyi herhangi bir anda kapatmak için geri tuşuna ↶ basın" "Sayılara ve simgelere erişin" @@ -83,12 +84,13 @@ "123" "ABC" "ALT" - - - - - - - - + "Klavyeyi açın"\n\n"Herhangi bir metin alanına dokunun." + "Klavyeyi kapatın"\n\n"Geri tuşuna basın." + "Seçenekler için bir tuşa dokunun ve basılı tutun"\n\n"Noktalama ve vurgulama işaretlerine erişin." + "Klavye ayarları"\n\n"?123"" tuşuna dokunun ve basılı tutun." + ".com" + ".net" + ".org" + ".gov" + ".edu" diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml index 720d30fae..c68b795c9 100644 --- a/res/values-zh-rCN/strings.xml +++ b/res/values-zh-rCN/strings.xml @@ -63,17 +63,18 @@ "ñ" "ç" "ýÿ" - "长按键可以查看重音符号(ø、ö 等)" + "i" + "长按某些键可看到重音符号(例如 ø、ö 等)" "随时可以通过按后退键 ↶ 关闭键盘" "访问数字和符号" - "按住最左侧的字词可以将其添加到字典中" + "长按最左侧的字可将其添加到词典中" "轻触此提示继续 »" "轻触此处可关闭该提示,然后便可开始输入内容!" "轻触文本字段即可打开键盘" - "轻触并按住某个键可以查看重音符号"\n"(?, ?, ?, ó 等)" + "长按某些键可看到重音符号"\n"(例如 ø、ö、ô、ó 等)" "轻触该键可切换到数字和符号输入模式" "再次轻触该键可返回字母输入模式" - "轻触并按住该键可以更改键盘设置,例如自动输入" + "长按该键可更改键盘设置,例如自动输入" "试试吧!" "开始" "下一步" @@ -83,12 +84,13 @@ "123" "ABC" "ALT" - - - - - - - - + "打开键盘"\n\n"轻触任意文本字段。" + "关闭键盘"\n\n"按“返回”键。" + "长按某些键可开启其他字符选项"\n\n"访问标点和重音符号。" + "键盘设置"\n\n"长按 ""?123"" 键。" + ".com" + ".net" + ".org" + ".gov" + ".edu" diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml index 69d82cca3..8d93b311a 100644 --- a/res/values-zh-rTW/strings.xml +++ b/res/values-zh-rTW/strings.xml @@ -63,6 +63,7 @@ "ñ" "ç" "ýÿ" + "i" "按住按鍵可查看重音符號 (ø、ö 等)" "隨時可以透過按後退鍵 ↶ 關閉鍵盤" "使用數字和符號" @@ -87,4 +88,9 @@ "關閉鍵盤"\n\n"按下 Back 鍵。" \n"輕觸並按住按鍵開啟選項"\n"輸入標點與輕重音。" "鍵盤設定"\n\n"輕觸並按住 ""?123"" 鍵。" + ".com" + ".net" + ".org" + ".gov" + ".edu" diff --git a/res/values/bools.xml b/res/values/bools.xml index 06aa8f308..3a951b271 100644 --- a/res/values/bools.xml +++ b/res/values/bools.xml @@ -19,7 +19,7 @@ --> - false + true false diff --git a/res/values/dimens.xml b/res/values/dimens.xml index d757f096d..5b2095c0e 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -19,6 +19,8 @@ --> - 50dip + 54dip 22dip + 42dip + 4dip \ No newline at end of file diff --git a/res/values/donottranslate.xml b/res/values/donottranslate.xml index d9649f3b1..c6941949e 100644 --- a/res/values/donottranslate.xml +++ b/res/values/donottranslate.xml @@ -32,4 +32,6 @@ + + diff --git a/res/values/strings.xml b/res/values/strings.xml index 2cd996c2e..ec9a8b731 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -125,7 +125,10 @@ ç ýÿ - + + + i + Hold a key down to see accents (ø, ö, etc.) @@ -191,4 +194,15 @@ Keyboard settings\n\nTouch \u0026 hold the \?123\ key. + + + ".com" + + ".net" + + ".org" + + ".gov" + + ".edu" diff --git a/res/xml-de/kbd_qwerty.xml b/res/xml-de/kbd_qwerty.xml index 763492db5..56113e217 100755 --- a/res/xml-de/kbd_qwerty.xml +++ b/res/xml-de/kbd_qwerty.xml @@ -69,7 +69,7 @@ - @@ -89,43 +89,44 @@ android:popupCharacters="@string/alternates_for_n" /> - - - - + + android:keyWidth="40%p" android:isRepeatable="true"/> - + - - - - - @@ -133,35 +134,37 @@ - + - - - - - + + android:keyWidth="40%p" android:isRepeatable="true"/> + android:keyWidth="10%p"/> - \ No newline at end of file diff --git a/res/xml-fr/kbd_qwerty.xml b/res/xml-fr/kbd_qwerty.xml index 573f08a3b..d47042ea7 100644 --- a/res/xml-fr/kbd_qwerty.xml +++ b/res/xml-fr/kbd_qwerty.xml @@ -102,12 +102,12 @@ android:popupKeyboard="@xml/kbd_popup_template" android:popupCharacters="" android:keyWidth="20%p" android:keyEdgeFlags="left"/> - + + android:keyWidth="40%p" android:isRepeatable="true"/> + android:keyWidth="10%p"/> @@ -118,7 +118,8 @@ android:popupKeyboard="@xml/kbd_popup_template" android:popupCharacters="" android:keyWidth="20%p" android:keyEdgeFlags="left"/> - @@ -137,29 +138,32 @@ android:popupKeyboard="@xml/kbd_popup_template" android:popupCharacters="" android:keyWidth="20%p" android:keyEdgeFlags="left"/> - + - - - - - + - + android:keyWidth="40%p" android:isRepeatable="true"/> + diff --git a/res/xml/kbd_phone.xml b/res/xml/kbd_phone.xml index 880d9613a..d2bcdac52 100755 --- a/res/xml/kbd_phone.xml +++ b/res/xml/kbd_phone.xml @@ -51,7 +51,7 @@ diff --git a/res/xml/kbd_phone_symbols.xml b/res/xml/kbd_phone_symbols.xml index 9ce7a1a1f..9604664fa 100755 --- a/res/xml/kbd_phone_symbols.xml +++ b/res/xml/kbd_phone_symbols.xml @@ -44,8 +44,8 @@ - - + + - @@ -70,7 +70,10 @@ android:popupKeyboard="@xml/kbd_popup_template" android:popupCharacters="@string/alternates_for_d"/> - + + /> @@ -100,8 +103,8 @@ android:popupCharacters="@string/alternates_for_n" /> - @@ -109,69 +112,73 @@ - - + + android:keyWidth="40%p" android:isRepeatable="true"/> - + - - - - - - - - + - - - - - + + android:keyWidth="40%p" android:isRepeatable="true"/> + android:keyWidth="10%p"/> - \ No newline at end of file + diff --git a/res/xml/kbd_symbols.xml b/res/xml/kbd_symbols.xml index 2a150397b..f3b8833dc 100755 --- a/res/xml/kbd_symbols.xml +++ b/res/xml/kbd_symbols.xml @@ -94,10 +94,10 @@ - - @@ -119,18 +119,19 @@ - - - - + diff --git a/res/xml/kbd_symbols_shift.xml b/res/xml/kbd_symbols_shift.xml index 6a472a412..56428a3ad 100755 --- a/res/xml/kbd_symbols_shift.xml +++ b/res/xml/kbd_symbols_shift.xml @@ -55,7 +55,7 @@ - @@ -79,14 +79,16 @@ - - + - - + diff --git a/res/xml/popup_domains.xml b/res/xml/popup_domains.xml index 5c86386d5..b733fe24f 100644 --- a/res/xml/popup_domains.xml +++ b/res/xml/popup_domains.xml @@ -26,9 +26,13 @@ > - - - - + + + + diff --git a/res/xml/popup_punctuation.xml b/res/xml/popup_punctuation.xml index 9d4575db6..7f9f61129 100644 --- a/res/xml/popup_punctuation.xml +++ b/res/xml/popup_punctuation.xml @@ -25,7 +25,16 @@ android:keyHeight="@dimen/key_height" > - + + + + + + + + + + diff --git a/src/com/android/inputmethod/latin/BinaryDictionary.java b/src/com/android/inputmethod/latin/BinaryDictionary.java index bb4f1ba46..e7470a8fc 100644 --- a/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -32,6 +32,7 @@ public class BinaryDictionary extends Dictionary { private static final int MAX_WORDS = 16; private static final int TYPED_LETTER_MULTIPLIER = 2; + private static final boolean ENABLE_MISSED_CHARACTERS = true; private int mNativeDict; private int[] mInputCodes = new int[MAX_WORD_LENGTH * MAX_ALTERNATIVES]; @@ -64,9 +65,7 @@ public class BinaryDictionary extends Dictionary { private native boolean isValidWordNative(int nativeData, char[] word, int wordLength); private native int getSuggestionsNative(int dict, int[] inputCodes, int codesSize, char[] outputChars, int[] frequencies, - int maxWordLength, int maxWords, int maxAlternatives); - private native void setParamsNative(int typedLetterMultiplier, - int fullWordMultiplier); + int maxWordLength, int maxWords, int maxAlternatives, int skipPos); private final void loadDictionary(Context context, int resId) { AssetManager am = context.getResources().getAssets(); @@ -88,9 +87,25 @@ public class BinaryDictionary extends Dictionary { Math.min(alternatives.length, MAX_ALTERNATIVES)); } Arrays.fill(mOutputChars, (char) 0); + Arrays.fill(mFrequencies, 0); - int count = getSuggestionsNative(mNativeDict, mInputCodes, codesSize, mOutputChars, mFrequencies, - MAX_WORD_LENGTH, MAX_WORDS, MAX_ALTERNATIVES); + int count = getSuggestionsNative(mNativeDict, mInputCodes, codesSize, + mOutputChars, mFrequencies, + MAX_WORD_LENGTH, MAX_WORDS, MAX_ALTERNATIVES, -1); + + // If there aren't sufficient suggestions, search for words by allowing wild cards at + // the different character positions. This feature is not ready for prime-time as we need + // to figure out the best ranking for such words compared to proximity corrections and + // completions. + if (ENABLE_MISSED_CHARACTERS && count < 5) { + for (int skip = 0; skip < codesSize; skip++) { + int tempCount = getSuggestionsNative(mNativeDict, mInputCodes, codesSize, + mOutputChars, mFrequencies, + MAX_WORD_LENGTH, MAX_WORDS, MAX_ALTERNATIVES, skip); + count = Math.max(count, tempCount); + if (tempCount > 0) break; + } + } for (int j = 0; j < count; j++) { if (mFrequencies[j] < 1) break; @@ -111,7 +126,7 @@ public class BinaryDictionary extends Dictionary { char[] chars = word.toString().toLowerCase().toCharArray(); return isValidWordNative(mNativeDict, chars, chars.length); } - + public synchronized void close() { if (mNativeDict != 0) { closeNative(mNativeDict); diff --git a/src/com/android/inputmethod/latin/ContactsDictionary.java b/src/com/android/inputmethod/latin/ContactsDictionary.java new file mode 100644 index 000000000..6f7f4b6a4 --- /dev/null +++ b/src/com/android/inputmethod/latin/ContactsDictionary.java @@ -0,0 +1,130 @@ +/* + * 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.latin; + +import android.content.ContentResolver; +import android.content.Context; +import android.database.ContentObserver; +import android.database.Cursor; +import android.provider.ContactsContract.Contacts; + +public class ContactsDictionary extends ExpandableDictionary { + + private static final String[] PROJECTION = { + Contacts._ID, + Contacts.DISPLAY_NAME, + }; + + private static final int INDEX_NAME = 1; + + private ContentObserver mObserver; + + private boolean mRequiresReload; + + private long mLastLoadedContacts; + + public ContactsDictionary(Context context) { + super(context); + // Perform a managed query. The Activity will handle closing and requerying the cursor + // when needed. + ContentResolver cres = context.getContentResolver(); + + cres.registerContentObserver(Contacts.CONTENT_URI, true, mObserver = new ContentObserver(null) { + @Override + public void onChange(boolean self) { + mRequiresReload = true; + } + }); + + loadDictionary(); + } + + public synchronized void close() { + if (mObserver != null) { + getContext().getContentResolver().unregisterContentObserver(mObserver); + mObserver = null; + } + } + + private synchronized void loadDictionary() { + long now = android.os.SystemClock.uptimeMillis(); + if (mLastLoadedContacts == 0 + || now - mLastLoadedContacts > 30 * 60 * 1000 /* 30 minutes */) { + Cursor cursor = getContext().getContentResolver() + .query(Contacts.CONTENT_URI, PROJECTION, null, null, null); + if (cursor != null) { + addWords(cursor); + } + mRequiresReload = false; + mLastLoadedContacts = now; + } + } + + @Override + public synchronized void getWords(final WordComposer codes, final WordCallback callback) { + if (mRequiresReload) loadDictionary(); + super.getWords(codes, callback); + } + + @Override + public synchronized boolean isValidWord(CharSequence word) { + if (mRequiresReload) loadDictionary(); + return super.isValidWord(word); + } + + private void addWords(Cursor cursor) { + clearDictionary(); + + final int maxWordLength = getMaxWordLength(); + if (cursor.moveToFirst()) { + while (!cursor.isAfterLast()) { + String name = cursor.getString(INDEX_NAME); + + if (name != null) { + int len = name.length(); + + // TODO: Better tokenization for non-Latin writing systems + for (int i = 0; i < len; i++) { + if (Character.isLetter(name.charAt(i))) { + int j; + for (j = i + 1; j < len; j++) { + char c = name.charAt(j); + + if (!(c == '-' || c == '\'' || + Character.isLetter(c))) { + break; + } + } + + String word = name.substring(i, j); + i = j - 1; + + // Safeguard against adding really long words. Stack + // may overflow due to recursion + if (word.length() < maxWordLength) { + super.addWord(word, 128); + } + } + } + } + + cursor.moveToNext(); + } + } + cursor.close(); + } +} diff --git a/src/com/android/inputmethod/latin/ExpandableDictionary.java b/src/com/android/inputmethod/latin/ExpandableDictionary.java new file mode 100644 index 000000000..a136ee7f4 --- /dev/null +++ b/src/com/android/inputmethod/latin/ExpandableDictionary.java @@ -0,0 +1,457 @@ +/* + * 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.latin; + +import android.content.Context; + +/** + * Base class for an in-memory dictionary that can grow dynamically and can + * be searched for suggestions and valid words. + */ +public class ExpandableDictionary extends Dictionary { + private Context mContext; + private char[] mWordBuilder = new char[MAX_WORD_LENGTH]; + private int mMaxDepth; + private int mInputLength; + + public static final int MAX_WORD_LENGTH = 32; + private static final char QUOTE = '\''; + + static class Node { + char code; + int frequency; + boolean terminal; + NodeArray children; + } + + static class NodeArray { + Node[] data; + int length = 0; + private static final int INCREMENT = 2; + + NodeArray() { + data = new Node[INCREMENT]; + } + + void add(Node n) { + if (length + 1 > data.length) { + Node[] tempData = new Node[length + INCREMENT]; + if (length > 0) { + System.arraycopy(data, 0, tempData, 0, length); + } + data = tempData; + } + data[length++] = n; + } + } + + private NodeArray mRoots; + + private int[][] mCodes; + + ExpandableDictionary(Context context) { + mContext = context; + clearDictionary(); + mCodes = new int[MAX_WORD_LENGTH][]; + } + + Context getContext() { + return mContext; + } + + int getMaxWordLength() { + return MAX_WORD_LENGTH; + } + + public void addWord(String word, int frequency) { + addWordRec(mRoots, word, 0, frequency); + } + + private void addWordRec(NodeArray children, final String word, + final int depth, final int frequency) { + + final int wordLength = word.length(); + final char c = word.charAt(depth); + // Does children have the current character? + final int childrenLength = children.length; + Node childNode = null; + boolean found = false; + for (int i = 0; i < childrenLength; i++) { + childNode = children.data[i]; + if (childNode.code == c) { + found = true; + break; + } + } + if (!found) { + childNode = new Node(); + childNode.code = c; + children.add(childNode); + } + if (wordLength == depth + 1) { + // Terminate this word + childNode.terminal = true; + childNode.frequency += frequency; // If there are multiple similar words + if (childNode.frequency > 256) childNode.frequency = 256; + return; + } + if (childNode.children == null) { + childNode.children = new NodeArray(); + } + addWordRec(childNode.children, word, depth + 1, frequency); + } + + @Override + public void getWords(final WordComposer codes, final WordCallback callback) { + mInputLength = codes.size(); + if (mCodes.length < mInputLength) mCodes = new int[mInputLength][]; + // 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); + } + mMaxDepth = mInputLength * 3; + getWordsRec(mRoots, codes, mWordBuilder, 0, false, 1, 0, -1, callback); + for (int i = 0; i < mInputLength; i++) { + getWordsRec(mRoots, codes, mWordBuilder, 0, false, 1, 0, i, callback); + } + } + + @Override + public synchronized boolean isValidWord(CharSequence word) { + final int freq = getWordFrequencyRec(mRoots, word, 0, word.length()); + return freq > -1; + } + + /** + * Returns the word's frequency or -1 if not found + */ + public int getWordFrequency(CharSequence word) { + return getWordFrequencyRec(mRoots, word, 0, word.length()); + } + + /** + * Returns the word's frequency or -1 if not found + */ + private int getWordFrequencyRec(final NodeArray children, final CharSequence word, + final int offset, final int length) { + final int count = children.length; + char currentChar = word.charAt(offset); + for (int j = 0; j < count; j++) { + final Node node = children.data[j]; + if (node.code == currentChar) { + if (offset == length - 1) { + if (node.terminal) { + return node.frequency; + } + } else { + if (node.children != null) { + int freq = getWordFrequencyRec(node.children, word, offset + 1, length); + if (freq > -1) return freq; + } + } + } + } + return -1; + } + + /** + * Recursively traverse the tree for words that match the input. Input consists of + * a list of arrays. Each item in the list is one input character position. An input + * character is actually an array of multiple possible candidates. This function is not + * optimized for speed, assuming that the user dictionary will only be a few hundred words in + * size. + * @param roots node whose children have to be search for matches + * @param codes the input character codes + * @param word the word being composed as a possible match + * @param depth the depth of traversal - the length of the word being composed thus far + * @param completion whether the traversal is now in completion mode - meaning that we've + * exhausted the input and we're looking for all possible suffixes. + * @param snr current weight of the word being formed + * @param inputIndex position in the input characters. This can be off from the depth in + * case we skip over some punctuations such as apostrophe in the traversal. That is, if you type + * "wouldve", it could be matching "would've", so the depth will be one more than the + * inputIndex + * @param callback the callback class for adding a word + */ + protected void getWordsRec(NodeArray roots, final WordComposer codes, final char[] word, + final int depth, boolean completion, int snr, int inputIndex, int skipPos, + WordCallback callback) { + final int count = roots.length; + final int codeSize = mInputLength; + // Optimization: Prune out words that are too long compared to how much was typed. + if (depth > mMaxDepth) { + return; + } + int[] currentChars = null; + if (codeSize <= inputIndex) { + completion = true; + } else { + currentChars = mCodes[inputIndex]; + } + + for (int i = 0; i < count; i++) { + final Node node = roots.data[i]; + final char c = node.code; + final char lowerC = toLowerCase(c); + final boolean terminal = node.terminal; + final NodeArray children = node.children; + final int freq = node.frequency; + if (completion) { + word[depth] = c; + if (terminal) { + if (!callback.addWord(word, 0, depth + 1, freq * snr)) { + return; + } + } + if (children != null) { + getWordsRec(children, codes, word, depth + 1, completion, snr, inputIndex, + skipPos, callback); + } + } else if ((c == QUOTE && currentChars[0] != QUOTE) || depth == skipPos) { + // Skip the ' and continue deeper + word[depth] = c; + if (children != null) { + getWordsRec(children, codes, word, depth + 1, completion, snr, inputIndex, + skipPos, callback); + } + } else { + // Don't use alternatives if we're looking for missing characters + 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) { + break; + } + if (currentChar == lowerC || currentChar == c) { + word[depth] = c; + + if (codeSize == depth + 1) { + if (terminal) { + if (INCLUDE_TYPED_WORD_IF_VALID + || !same(word, depth + 1, codes.getTypedWord())) { + int finalFreq = freq * snr * addedAttenuation; + if (skipPos < 0) finalFreq *= FULL_WORD_FREQ_MULTIPLIER; + callback.addWord(word, 0, depth + 1, finalFreq); + } + } + if (children != null) { + getWordsRec(children, codes, word, depth + 1, + true, snr * addedAttenuation, inputIndex + 1, + skipPos, callback); + } + } else if (children != null) { + getWordsRec(children, codes, word, depth + 1, + false, snr * addedAttenuation, inputIndex + 1, + skipPos, callback); + } + } + } + } + } + } + + protected void clearDictionary() { + mRoots = new NodeArray(); + } + + static char toLowerCase(char c) { + if (c < BASE_CHARS.length) { + c = BASE_CHARS[c]; + } + if (c >= 'A' && c <= 'Z') { + c = (char) (c | 32); + } else if (c > 127) { + c = Character.toLowerCase(c); + } + return 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 final char BASE_CHARS[] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, + 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, + 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, + 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, + 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, + 0x0020, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, + 0x0020, 0x00a9, 0x0061, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0020, + 0x00b0, 0x00b1, 0x0032, 0x0033, 0x0020, 0x03bc, 0x00b6, 0x00b7, + 0x0020, 0x0031, 0x006f, 0x00bb, 0x0031, 0x0031, 0x0033, 0x00bf, + 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, 0x00c6, 0x0043, + 0x0045, 0x0045, 0x0045, 0x0045, 0x0049, 0x0049, 0x0049, 0x0049, + 0x00d0, 0x004e, 0x004f, 0x004f, 0x004f, 0x004f, 0x004f, 0x00d7, + 0x004f, 0x0055, 0x0055, 0x0055, 0x0055, 0x0059, 0x00de, 0x0073, // Manually changed d8 to 4f + // Manually changed df to 73 + 0x0061, 0x0061, 0x0061, 0x0061, 0x0061, 0x0061, 0x00e6, 0x0063, + 0x0065, 0x0065, 0x0065, 0x0065, 0x0069, 0x0069, 0x0069, 0x0069, + 0x00f0, 0x006e, 0x006f, 0x006f, 0x006f, 0x006f, 0x006f, 0x00f7, + 0x006f, 0x0075, 0x0075, 0x0075, 0x0075, 0x0079, 0x00fe, 0x0079, // Manually changed f8 to 6f + 0x0041, 0x0061, 0x0041, 0x0061, 0x0041, 0x0061, 0x0043, 0x0063, + 0x0043, 0x0063, 0x0043, 0x0063, 0x0043, 0x0063, 0x0044, 0x0064, + 0x0110, 0x0111, 0x0045, 0x0065, 0x0045, 0x0065, 0x0045, 0x0065, + 0x0045, 0x0065, 0x0045, 0x0065, 0x0047, 0x0067, 0x0047, 0x0067, + 0x0047, 0x0067, 0x0047, 0x0067, 0x0048, 0x0068, 0x0126, 0x0127, + 0x0049, 0x0069, 0x0049, 0x0069, 0x0049, 0x0069, 0x0049, 0x0069, + 0x0049, 0x0131, 0x0049, 0x0069, 0x004a, 0x006a, 0x004b, 0x006b, + 0x0138, 0x004c, 0x006c, 0x004c, 0x006c, 0x004c, 0x006c, 0x004c, + 0x006c, 0x0141, 0x0142, 0x004e, 0x006e, 0x004e, 0x006e, 0x004e, + 0x006e, 0x02bc, 0x014a, 0x014b, 0x004f, 0x006f, 0x004f, 0x006f, + 0x004f, 0x006f, 0x0152, 0x0153, 0x0052, 0x0072, 0x0052, 0x0072, + 0x0052, 0x0072, 0x0053, 0x0073, 0x0053, 0x0073, 0x0053, 0x0073, + 0x0053, 0x0073, 0x0054, 0x0074, 0x0054, 0x0074, 0x0166, 0x0167, + 0x0055, 0x0075, 0x0055, 0x0075, 0x0055, 0x0075, 0x0055, 0x0075, + 0x0055, 0x0075, 0x0055, 0x0075, 0x0057, 0x0077, 0x0059, 0x0079, + 0x0059, 0x005a, 0x007a, 0x005a, 0x007a, 0x005a, 0x007a, 0x0073, + 0x0180, 0x0181, 0x0182, 0x0183, 0x0184, 0x0185, 0x0186, 0x0187, + 0x0188, 0x0189, 0x018a, 0x018b, 0x018c, 0x018d, 0x018e, 0x018f, + 0x0190, 0x0191, 0x0192, 0x0193, 0x0194, 0x0195, 0x0196, 0x0197, + 0x0198, 0x0199, 0x019a, 0x019b, 0x019c, 0x019d, 0x019e, 0x019f, + 0x004f, 0x006f, 0x01a2, 0x01a3, 0x01a4, 0x01a5, 0x01a6, 0x01a7, + 0x01a8, 0x01a9, 0x01aa, 0x01ab, 0x01ac, 0x01ad, 0x01ae, 0x0055, + 0x0075, 0x01b1, 0x01b2, 0x01b3, 0x01b4, 0x01b5, 0x01b6, 0x01b7, + 0x01b8, 0x01b9, 0x01ba, 0x01bb, 0x01bc, 0x01bd, 0x01be, 0x01bf, + 0x01c0, 0x01c1, 0x01c2, 0x01c3, 0x0044, 0x0044, 0x0064, 0x004c, + 0x004c, 0x006c, 0x004e, 0x004e, 0x006e, 0x0041, 0x0061, 0x0049, + 0x0069, 0x004f, 0x006f, 0x0055, 0x0075, 0x00dc, 0x00fc, 0x00dc, + 0x00fc, 0x00dc, 0x00fc, 0x00dc, 0x00fc, 0x01dd, 0x00c4, 0x00e4, + 0x0226, 0x0227, 0x00c6, 0x00e6, 0x01e4, 0x01e5, 0x0047, 0x0067, + 0x004b, 0x006b, 0x004f, 0x006f, 0x01ea, 0x01eb, 0x01b7, 0x0292, + 0x006a, 0x0044, 0x0044, 0x0064, 0x0047, 0x0067, 0x01f6, 0x01f7, + 0x004e, 0x006e, 0x00c5, 0x00e5, 0x00c6, 0x00e6, 0x00d8, 0x00f8, + 0x0041, 0x0061, 0x0041, 0x0061, 0x0045, 0x0065, 0x0045, 0x0065, + 0x0049, 0x0069, 0x0049, 0x0069, 0x004f, 0x006f, 0x004f, 0x006f, + 0x0052, 0x0072, 0x0052, 0x0072, 0x0055, 0x0075, 0x0055, 0x0075, + 0x0053, 0x0073, 0x0054, 0x0074, 0x021c, 0x021d, 0x0048, 0x0068, + 0x0220, 0x0221, 0x0222, 0x0223, 0x0224, 0x0225, 0x0041, 0x0061, + 0x0045, 0x0065, 0x00d6, 0x00f6, 0x00d5, 0x00f5, 0x004f, 0x006f, + 0x022e, 0x022f, 0x0059, 0x0079, 0x0234, 0x0235, 0x0236, 0x0237, + 0x0238, 0x0239, 0x023a, 0x023b, 0x023c, 0x023d, 0x023e, 0x023f, + 0x0240, 0x0241, 0x0242, 0x0243, 0x0244, 0x0245, 0x0246, 0x0247, + 0x0248, 0x0249, 0x024a, 0x024b, 0x024c, 0x024d, 0x024e, 0x024f, + 0x0250, 0x0251, 0x0252, 0x0253, 0x0254, 0x0255, 0x0256, 0x0257, + 0x0258, 0x0259, 0x025a, 0x025b, 0x025c, 0x025d, 0x025e, 0x025f, + 0x0260, 0x0261, 0x0262, 0x0263, 0x0264, 0x0265, 0x0266, 0x0267, + 0x0268, 0x0269, 0x026a, 0x026b, 0x026c, 0x026d, 0x026e, 0x026f, + 0x0270, 0x0271, 0x0272, 0x0273, 0x0274, 0x0275, 0x0276, 0x0277, + 0x0278, 0x0279, 0x027a, 0x027b, 0x027c, 0x027d, 0x027e, 0x027f, + 0x0280, 0x0281, 0x0282, 0x0283, 0x0284, 0x0285, 0x0286, 0x0287, + 0x0288, 0x0289, 0x028a, 0x028b, 0x028c, 0x028d, 0x028e, 0x028f, + 0x0290, 0x0291, 0x0292, 0x0293, 0x0294, 0x0295, 0x0296, 0x0297, + 0x0298, 0x0299, 0x029a, 0x029b, 0x029c, 0x029d, 0x029e, 0x029f, + 0x02a0, 0x02a1, 0x02a2, 0x02a3, 0x02a4, 0x02a5, 0x02a6, 0x02a7, + 0x02a8, 0x02a9, 0x02aa, 0x02ab, 0x02ac, 0x02ad, 0x02ae, 0x02af, + 0x0068, 0x0266, 0x006a, 0x0072, 0x0279, 0x027b, 0x0281, 0x0077, + 0x0079, 0x02b9, 0x02ba, 0x02bb, 0x02bc, 0x02bd, 0x02be, 0x02bf, + 0x02c0, 0x02c1, 0x02c2, 0x02c3, 0x02c4, 0x02c5, 0x02c6, 0x02c7, + 0x02c8, 0x02c9, 0x02ca, 0x02cb, 0x02cc, 0x02cd, 0x02ce, 0x02cf, + 0x02d0, 0x02d1, 0x02d2, 0x02d3, 0x02d4, 0x02d5, 0x02d6, 0x02d7, + 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x02de, 0x02df, + 0x0263, 0x006c, 0x0073, 0x0078, 0x0295, 0x02e5, 0x02e6, 0x02e7, + 0x02e8, 0x02e9, 0x02ea, 0x02eb, 0x02ec, 0x02ed, 0x02ee, 0x02ef, + 0x02f0, 0x02f1, 0x02f2, 0x02f3, 0x02f4, 0x02f5, 0x02f6, 0x02f7, + 0x02f8, 0x02f9, 0x02fa, 0x02fb, 0x02fc, 0x02fd, 0x02fe, 0x02ff, + 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, + 0x0308, 0x0309, 0x030a, 0x030b, 0x030c, 0x030d, 0x030e, 0x030f, + 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317, + 0x0318, 0x0319, 0x031a, 0x031b, 0x031c, 0x031d, 0x031e, 0x031f, + 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327, + 0x0328, 0x0329, 0x032a, 0x032b, 0x032c, 0x032d, 0x032e, 0x032f, + 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337, + 0x0338, 0x0339, 0x033a, 0x033b, 0x033c, 0x033d, 0x033e, 0x033f, + 0x0300, 0x0301, 0x0342, 0x0313, 0x0308, 0x0345, 0x0346, 0x0347, + 0x0348, 0x0349, 0x034a, 0x034b, 0x034c, 0x034d, 0x034e, 0x034f, + 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357, + 0x0358, 0x0359, 0x035a, 0x035b, 0x035c, 0x035d, 0x035e, 0x035f, + 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367, + 0x0368, 0x0369, 0x036a, 0x036b, 0x036c, 0x036d, 0x036e, 0x036f, + 0x0370, 0x0371, 0x0372, 0x0373, 0x02b9, 0x0375, 0x0376, 0x0377, + 0x0378, 0x0379, 0x0020, 0x037b, 0x037c, 0x037d, 0x003b, 0x037f, + 0x0380, 0x0381, 0x0382, 0x0383, 0x0020, 0x00a8, 0x0391, 0x00b7, + 0x0395, 0x0397, 0x0399, 0x038b, 0x039f, 0x038d, 0x03a5, 0x03a9, + 0x03ca, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, + 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, + 0x03a0, 0x03a1, 0x03a2, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, + 0x03a8, 0x03a9, 0x0399, 0x03a5, 0x03b1, 0x03b5, 0x03b7, 0x03b9, + 0x03cb, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, + 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, + 0x03c0, 0x03c1, 0x03c2, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, + 0x03c8, 0x03c9, 0x03b9, 0x03c5, 0x03bf, 0x03c5, 0x03c9, 0x03cf, + 0x03b2, 0x03b8, 0x03a5, 0x03d2, 0x03d2, 0x03c6, 0x03c0, 0x03d7, + 0x03d8, 0x03d9, 0x03da, 0x03db, 0x03dc, 0x03dd, 0x03de, 0x03df, + 0x03e0, 0x03e1, 0x03e2, 0x03e3, 0x03e4, 0x03e5, 0x03e6, 0x03e7, + 0x03e8, 0x03e9, 0x03ea, 0x03eb, 0x03ec, 0x03ed, 0x03ee, 0x03ef, + 0x03ba, 0x03c1, 0x03c2, 0x03f3, 0x0398, 0x03b5, 0x03f6, 0x03f7, + 0x03f8, 0x03a3, 0x03fa, 0x03fb, 0x03fc, 0x03fd, 0x03fe, 0x03ff, + 0x0415, 0x0415, 0x0402, 0x0413, 0x0404, 0x0405, 0x0406, 0x0406, + 0x0408, 0x0409, 0x040a, 0x040b, 0x041a, 0x0418, 0x0423, 0x040f, + 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, + 0x0418, 0x0418, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f, + 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, + 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, + 0x0438, 0x0438, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, + 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f, + 0x0435, 0x0435, 0x0452, 0x0433, 0x0454, 0x0455, 0x0456, 0x0456, + 0x0458, 0x0459, 0x045a, 0x045b, 0x043a, 0x0438, 0x0443, 0x045f, + 0x0460, 0x0461, 0x0462, 0x0463, 0x0464, 0x0465, 0x0466, 0x0467, + 0x0468, 0x0469, 0x046a, 0x046b, 0x046c, 0x046d, 0x046e, 0x046f, + 0x0470, 0x0471, 0x0472, 0x0473, 0x0474, 0x0475, 0x0474, 0x0475, + 0x0478, 0x0479, 0x047a, 0x047b, 0x047c, 0x047d, 0x047e, 0x047f, + 0x0480, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, + 0x0488, 0x0489, 0x048a, 0x048b, 0x048c, 0x048d, 0x048e, 0x048f, + 0x0490, 0x0491, 0x0492, 0x0493, 0x0494, 0x0495, 0x0496, 0x0497, + 0x0498, 0x0499, 0x049a, 0x049b, 0x049c, 0x049d, 0x049e, 0x049f, + 0x04a0, 0x04a1, 0x04a2, 0x04a3, 0x04a4, 0x04a5, 0x04a6, 0x04a7, + 0x04a8, 0x04a9, 0x04aa, 0x04ab, 0x04ac, 0x04ad, 0x04ae, 0x04af, + 0x04b0, 0x04b1, 0x04b2, 0x04b3, 0x04b4, 0x04b5, 0x04b6, 0x04b7, + 0x04b8, 0x04b9, 0x04ba, 0x04bb, 0x04bc, 0x04bd, 0x04be, 0x04bf, + 0x04c0, 0x0416, 0x0436, 0x04c3, 0x04c4, 0x04c5, 0x04c6, 0x04c7, + 0x04c8, 0x04c9, 0x04ca, 0x04cb, 0x04cc, 0x04cd, 0x04ce, 0x04cf, + 0x0410, 0x0430, 0x0410, 0x0430, 0x04d4, 0x04d5, 0x0415, 0x0435, + 0x04d8, 0x04d9, 0x04d8, 0x04d9, 0x0416, 0x0436, 0x0417, 0x0437, + 0x04e0, 0x04e1, 0x0418, 0x0438, 0x0418, 0x0438, 0x041e, 0x043e, + 0x04e8, 0x04e9, 0x04e8, 0x04e9, 0x042d, 0x044d, 0x0423, 0x0443, + 0x0423, 0x0443, 0x0423, 0x0443, 0x0427, 0x0447, 0x04f6, 0x04f7, + 0x042b, 0x044b, 0x04fa, 0x04fb, 0x04fc, 0x04fd, 0x04fe, 0x04ff, + }; + + // 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"; }' + +} diff --git a/src/com/android/inputmethod/latin/KeyboardSwitcher.java b/src/com/android/inputmethod/latin/KeyboardSwitcher.java index 92b7cd4a1..c82587b71 100644 --- a/src/com/android/inputmethod/latin/KeyboardSwitcher.java +++ b/src/com/android/inputmethod/latin/KeyboardSwitcher.java @@ -37,6 +37,10 @@ public class KeyboardSwitcher { public static final int KEYBOARDMODE_EMAIL = R.id.mode_email; public static final int KEYBOARDMODE_IM = R.id.mode_im; + private static final int SYMBOLS_MODE_STATE_NONE = 0; + private static final int SYMBOLS_MODE_STATE_BEGIN = 1; + private static final int SYMBOLS_MODE_STATE_SYMBOL = 2; + LatinKeyboardView mInputView; LatinIME mContext; @@ -50,6 +54,8 @@ public class KeyboardSwitcher { private int mImeOptions; private int mTextMode = MODE_TEXT_QWERTY; private boolean mIsSymbols; + private boolean mPreferSymbols; + private int mSymbolsModeState = SYMBOLS_MODE_STATE_NONE; private int mLastDisplayWidth; @@ -64,14 +70,15 @@ public class KeyboardSwitcher { mInputView = inputView; } - void makeKeyboards() { + void makeKeyboards(boolean forceCreate) { + if (forceCreate) mKeyboards.clear(); // Configuration change is coming after the keyboard gets recreated. So don't rely on that. // If keyboards have already been made, check if we have a screen width change and // create the keyboard layouts again at the correct orientation int displayWidth = mContext.getMaxWidth(); if (displayWidth == mLastDisplayWidth) return; mLastDisplayWidth = displayWidth; - mKeyboards.clear(); + if (!forceCreate) mKeyboards.clear(); mSymbolsId = new KeyboardId(R.xml.kbd_symbols); mSymbolsShiftedId = new KeyboardId(R.xml.kbd_symbols_shift); } @@ -109,7 +116,10 @@ public class KeyboardSwitcher { } void setKeyboardMode(int mode, int imeOptions) { - setKeyboardMode(mode, imeOptions, false); + mSymbolsModeState = SYMBOLS_MODE_STATE_NONE; + mPreferSymbols = mode == MODE_SYMBOLS; + setKeyboardMode(mode == MODE_SYMBOLS ? MODE_TEXT : mode, imeOptions, + mPreferSymbols); } void setKeyboardMode(int mode, int imeOptions, boolean isSymbols) { @@ -228,5 +238,30 @@ public class KeyboardSwitcher { void toggleSymbols() { setKeyboardMode(mMode, mImeOptions, !mIsSymbols); + if (mIsSymbols && !mPreferSymbols) { + mSymbolsModeState = SYMBOLS_MODE_STATE_BEGIN; + } else { + mSymbolsModeState = SYMBOLS_MODE_STATE_NONE; + } + } + + /** + * Updates state machine to figure out when to automatically switch back to alpha mode. + * Returns true if the keyboard needs to switch back + */ + boolean onKey(int key) { + // Switch back to alpha mode if user types one or more non-space/enter characters + // followed by a space/enter + switch (mSymbolsModeState) { + case SYMBOLS_MODE_STATE_BEGIN: + if (key != LatinIME.KEYCODE_SPACE && key != LatinIME.KEYCODE_ENTER && key > 0) { + mSymbolsModeState = SYMBOLS_MODE_STATE_SYMBOL; + } + break; + case SYMBOLS_MODE_STATE_SYMBOL: + if (key == LatinIME.KEYCODE_ENTER || key == LatinIME.KEYCODE_SPACE) return true; + break; + } + return false; } } diff --git a/src/com/android/inputmethod/latin/LatinIME.java b/src/com/android/inputmethod/latin/LatinIME.java index 240668ebb..8b76dbd39 100644 --- a/src/com/android/inputmethod/latin/LatinIME.java +++ b/src/com/android/inputmethod/latin/LatinIME.java @@ -71,14 +71,22 @@ public class LatinIME extends InputMethodService private static final int MSG_UPDATE_SUGGESTIONS = 0; private static final int MSG_START_TUTORIAL = 1; + private static final int MSG_UPDATE_SHIFT_STATE = 2; // How many continuous deletes at which to start deleting at a higher speed. private static final int DELETE_ACCELERATE_AT = 20; // Key events coming any faster than this are long-presses. - private static final int QUICK_PRESS = 200; + private static final int QUICK_PRESS = 200; + // 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; + // A word that is frequently typed and get's promoted to the user dictionary, uses this + // frequency. + static final int FREQUENCY_FOR_AUTO_ADD = 250; - private static final int KEYCODE_ENTER = 10; - private static final int KEYCODE_SPACE = ' '; + static final int KEYCODE_ENTER = '\n'; + static final int KEYCODE_SPACE = ' '; // Contextual menu positions private static final int POS_SETTINGS = 0; @@ -95,6 +103,8 @@ public class LatinIME extends InputMethodService KeyboardSwitcher mKeyboardSwitcher; private UserDictionary mUserDictionary; + private ContactsDictionary mContactsDictionary; + private ExpandableDictionary mAutoDictionary; private String mLocale; @@ -114,6 +124,8 @@ public class LatinIME extends InputMethodService private boolean mQuickFixes; private boolean mShowSuggestions; private int mCorrectionMode; + private int mOrientation; + // Indicates whether the suggestion strip is to be on in landscape private boolean mJustAccepted; private CharSequence mJustRevertedSeparator; @@ -126,7 +138,8 @@ public class LatinIME extends InputMethodService private long mVibrateDuration; private AudioManager mAudioManager; - private final float FX_VOLUME = 1.0f; + // Align sound effect volume on music volume + private final float FX_VOLUME = -1.0f; private boolean mSilentMode; private String mWordSeparators; @@ -150,6 +163,9 @@ public class LatinIME extends InputMethodService } } break; + case MSG_UPDATE_SHIFT_STATE: + updateShiftKeyState(getCurrentInputEditorInfo()); + break; } } }; @@ -158,10 +174,12 @@ public class LatinIME extends InputMethodService super.onCreate(); //setStatusIcon(R.drawable.ime_qwerty); mKeyboardSwitcher = new KeyboardSwitcher(this); - initSuggest(getResources().getConfiguration().locale.toString()); - + final Configuration conf = getResources().getConfiguration(); + initSuggest(conf.locale.toString()); + mOrientation = conf.orientation; + mVibrateDuration = getResources().getInteger(R.integer.vibrate_duration_ms); - + // register to receive ringer mode changes for silent mode IntentFilter filter = new IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION); registerReceiver(mReceiver, filter); @@ -172,13 +190,18 @@ public class LatinIME extends InputMethodService mSuggest = new Suggest(this, R.raw.main); mSuggest.setCorrectionMode(mCorrectionMode); mUserDictionary = new UserDictionary(this); + mContactsDictionary = new ContactsDictionary(this); + mAutoDictionary = new AutoDictionary(this); mSuggest.setUserDictionary(mUserDictionary); + mSuggest.setContactsDictionary(mContactsDictionary); + mSuggest.setAutoDictionary(mAutoDictionary); mWordSeparators = getResources().getString(R.string.word_separators); mSentenceSeparators = getResources().getString(R.string.sentence_separators); } @Override public void onDestroy() { mUserDictionary.close(); + mContactsDictionary.close(); unregisterReceiver(mReceiver); super.onDestroy(); } @@ -188,15 +211,24 @@ public class LatinIME extends InputMethodService if (!TextUtils.equals(conf.locale.toString(), mLocale)) { initSuggest(conf.locale.toString()); } + // If orientation changed while predicting, commit the change + if (conf.orientation != mOrientation) { + commitTyped(getCurrentInputConnection()); + mOrientation = conf.orientation; + } + if (mKeyboardSwitcher == null) { + mKeyboardSwitcher = new KeyboardSwitcher(this); + } + mKeyboardSwitcher.makeKeyboards(true); super.onConfigurationChanged(conf); } - + @Override public View onCreateInputView() { mInputView = (LatinKeyboardView) getLayoutInflater().inflate( R.layout.input, null); mKeyboardSwitcher.setInputView(mInputView); - mKeyboardSwitcher.makeKeyboards(); + mKeyboardSwitcher.makeKeyboards(true); mInputView.setOnKeyboardActionListener(this); mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_TEXT, 0); return mInputView; @@ -204,7 +236,7 @@ public class LatinIME extends InputMethodService @Override public View onCreateCandidatesView() { - mKeyboardSwitcher.makeKeyboards(); + mKeyboardSwitcher.makeKeyboards(true); mCandidateViewContainer = (CandidateViewContainer) getLayoutInflater().inflate( R.layout.candidates, null); mCandidateViewContainer.initViews(); @@ -221,7 +253,7 @@ public class LatinIME extends InputMethodService return; } - mKeyboardSwitcher.makeKeyboards(); + mKeyboardSwitcher.makeKeyboards(false); TextEntryState.newSession(this); @@ -233,9 +265,8 @@ public class LatinIME extends InputMethodService switch (attribute.inputType&EditorInfo.TYPE_MASK_CLASS) { case EditorInfo.TYPE_CLASS_NUMBER: case EditorInfo.TYPE_CLASS_DATETIME: - mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_TEXT, + mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_SYMBOLS, attribute.imeOptions); - mKeyboardSwitcher.toggleSymbols(); break; case EditorInfo.TYPE_CLASS_PHONE: mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_PHONE, @@ -278,6 +309,17 @@ public class LatinIME extends InputMethodService disableAutoCorrect = true; } } + + // If NO_SUGGESTIONS is set, don't do prediction. + if ((attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_NO_SUGGESTIONS) != 0) { + mPredictionOn = false; + disableAutoCorrect = true; + } + // If it's not multiline and the autoCorrect flag is not set, then don't correct + if ((attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0 && + (attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE) == 0) { + disableAutoCorrect = true; + } if ((attribute.inputType&EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) { mPredictionOn = false; mCompletionOn = true && isFullscreenMode(); @@ -309,7 +351,7 @@ public class LatinIME extends InputMethodService } mPredictionOn = mPredictionOn && mCorrectionMode > 0; checkTutorial(attribute.privateImeOptions); - if (TRACE) Debug.startMethodTracing("latinime"); + if (TRACE) Debug.startMethodTracing("/data/trace/latinime"); } @Override @@ -344,6 +386,7 @@ public class LatinIME extends InputMethodService TextEntryState.reset(); } mJustAccepted = false; + postUpdateShiftKeyState(); } @Override @@ -465,11 +508,17 @@ public class LatinIME extends InputMethodService } mCommittedLength = mComposing.length(); TextEntryState.acceptedTyped(mComposing); + mAutoDictionary.addWord(mComposing.toString(), FREQUENCY_FOR_TYPED); } updateSuggestions(); } } + private void postUpdateShiftKeyState() { + mHandler.removeMessages(MSG_UPDATE_SHIFT_STATE); + mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_UPDATE_SHIFT_STATE), 300); + } + public void updateShiftKeyState(EditorInfo attr) { InputConnection ic = getCurrentInputConnection(); if (attr != null && mInputView != null && mKeyboardSwitcher.isAlphabetMode() @@ -571,6 +620,9 @@ public class LatinIME extends InputMethodService // Cancel the just reverted state mJustRevertedSeparator = null; } + if (mKeyboardSwitcher.onKey(primaryCode)) { + changeKeyboardMode(); + } } public void onText(CharSequence text) { @@ -606,7 +658,7 @@ public class LatinIME extends InputMethodService } else { deleteChar = true; } - updateShiftKeyState(getCurrentInputEditorInfo()); + postUpdateShiftKeyState(); TextEntryState.backspace(); if (TextEntryState.getState() == TextEntryState.STATE_UNDO_COMMIT) { revertLastWord(deleteChar); @@ -640,7 +692,12 @@ public class LatinIME extends InputMethodService } } if (mInputView.isShifted()) { - primaryCode = Character.toUpperCase(primaryCode); + // TODO: This doesn't work with ß, need to fix it in the next release. + if (keyCodes == null || keyCodes[0] < Character.MIN_CODE_POINT + || keyCodes[0] > Character.MAX_CODE_POINT) { + return; + } + primaryCode = new String(keyCodes, 0, 1).toUpperCase().charAt(0); } if (mPredicting) { if (mInputView.isShifted() && mComposing.length() == 0) { @@ -756,7 +813,9 @@ public class LatinIME extends InputMethodService if (mCorrectionMode == Suggest.CORRECTION_FULL) { correctionAvailable |= typedWordValid; } - + // Don't auto-correct words with multiple capital letter + correctionAvailable &= !mWord.isMostlyCaps(); + mCandidateView.setSuggestions(stringList, false, typedWordValid, correctionAvailable); if (stringList.size() > 0) { if (correctionAvailable && !typedWordValid && stringList.size() > 1) { @@ -813,13 +872,17 @@ public class LatinIME extends InputMethodService suggestion = suggestion.toString().toUpperCase(); } else if (preferCapitalization() || (mKeyboardSwitcher.isAlphabetMode() && mInputView.isShifted())) { - suggestion = Character.toUpperCase(suggestion.charAt(0)) + suggestion = suggestion.toString().toUpperCase().charAt(0) + suggestion.subSequence(1, suggestion.length()).toString(); } InputConnection ic = getCurrentInputConnection(); if (ic != null) { ic.commitText(suggestion, 1); } + // Add the word to the auto dictionary if it's not a known word + if (mAutoDictionary.isValidWord(suggestion) || !mSuggest.isValidWord(suggestion)) { + mAutoDictionary.addWord(suggestion.toString(), FREQUENCY_FOR_PICKED); + } mPredicting = false; mCommittedLength = suggestion.length(); if (mCandidateView != null) { @@ -907,7 +970,7 @@ public class LatinIME extends InputMethodService } public void swipeDown() { - //handleClose(); + handleClose(); } public void swipeUp() { @@ -973,7 +1036,7 @@ public class LatinIME extends InputMethodService return; } if (mVibrator == null) { - mVibrator = new Vibrator(); + mVibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE); } mVibrator.vibrate(mVibrateDuration); } @@ -998,7 +1061,12 @@ public class LatinIME extends InputMethodService void tutorialDone() { mTutorial = null; } - + + void promoteToUserDictionary(String word, int frequency) { + if (mUserDictionary.isValidWord(word)) return; + mUserDictionary.addWord(word, frequency); + } + private void launchSettings() { handleClose(); Intent intent = new Intent(); @@ -1044,7 +1112,8 @@ public class LatinIME extends InputMethodService launchSettings(); break; case POS_METHOD: - InputMethodManager.getInstance(LatinIME.this).showInputMethodPicker(); + ((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE)) + .showInputMethodPicker(); break; } } @@ -1107,7 +1176,35 @@ public class LatinIME extends InputMethodService for (int i = 0; i < CPS_BUFFER_SIZE; i++) total += mCpsIntervals[i]; System.out.println("CPS = " + ((CPS_BUFFER_SIZE * 1000f) / total)); } - + + class AutoDictionary extends ExpandableDictionary { + // 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; + // If the user touches a typed word 5 times or more, it will be added to the user dict. + private static final int PROMOTION_THRESHOLD = 5 * FREQUENCY_FOR_PICKED; + + public AutoDictionary(Context context) { + super(context); + } + + @Override + public boolean isValidWord(CharSequence word) { + final int frequency = getWordFrequency(word); + return frequency > VALIDITY_THRESHOLD; + } + + @Override + public void addWord(String word, int addFrequency) { + final int length = word.length(); + // Don't add very short or very long words. + if (length < 2 || length > getMaxWordLength()) return; + super.addWord(word, addFrequency); + final int freq = getWordFrequency(word); + if (freq > PROMOTION_THRESHOLD) { + LatinIME.this.promoteToUserDictionary(word, FREQUENCY_FOR_AUTO_ADD); + } + } + } } diff --git a/src/com/android/inputmethod/latin/LatinKeyboard.java b/src/com/android/inputmethod/latin/LatinKeyboard.java index 8527d9cd5..9b04aa264 100644 --- a/src/com/android/inputmethod/latin/LatinKeyboard.java +++ b/src/com/android/inputmethod/latin/LatinKeyboard.java @@ -37,20 +37,23 @@ public class LatinKeyboard extends Keyboard { private static final int SHIFT_LOCKED = 2; private int mShiftState = SHIFT_OFF; - + + static int sSpacebarVerticalCorrection; + public LatinKeyboard(Context context, int xmlLayoutResId) { this(context, xmlLayoutResId, 0); } public LatinKeyboard(Context context, int xmlLayoutResId, int mode) { super(context, xmlLayoutResId, mode); - mShiftLockIcon = context.getResources() - .getDrawable(R.drawable.sym_keyboard_shift_locked); - mShiftLockPreviewIcon = context.getResources() - .getDrawable(R.drawable.sym_keyboard_feedback_shift_locked); + Resources res = context.getResources(); + mShiftLockIcon = res.getDrawable(R.drawable.sym_keyboard_shift_locked); + mShiftLockPreviewIcon = res.getDrawable(R.drawable.sym_keyboard_feedback_shift_locked); mShiftLockPreviewIcon.setBounds(0, 0, mShiftLockPreviewIcon.getIntrinsicWidth(), mShiftLockPreviewIcon.getIntrinsicHeight()); + sSpacebarVerticalCorrection = res.getDimensionPixelOffset( + R.dimen.spacebar_vertical_correction); } public LatinKeyboard(Context context, int layoutTemplateResId, @@ -225,6 +228,8 @@ public class LatinKeyboard extends Keyboard { y -= height / 10; if (code == KEYCODE_SHIFT) x += width / 6; if (code == KEYCODE_DELETE) x -= width / 6; + } else if (code == LatinIME.KEYCODE_SPACE) { + y += LatinKeyboard.sSpacebarVerticalCorrection; } return super.isInside(x, y); } diff --git a/src/com/android/inputmethod/latin/Suggest.java b/src/com/android/inputmethod/latin/Suggest.java index 91decd66a..c025566b7 100755 --- a/src/com/android/inputmethod/latin/Suggest.java +++ b/src/com/android/inputmethod/latin/Suggest.java @@ -36,17 +36,21 @@ public class Suggest implements Dictionary.WordCallback { public static final int CORRECTION_NONE = 0; public static final int CORRECTION_BASIC = 1; public static final int CORRECTION_FULL = 2; - + private Dictionary mMainDict; - + private Dictionary mUserDictionary; - + + private Dictionary mAutoDictionary; + + private Dictionary mContactsDictionary; + private int mPrefMaxSuggestions = 12; - + private int[] mPriorities = new int[mPrefMaxSuggestions]; - private List mSuggestions = new ArrayList(); + private ArrayList mSuggestions = new ArrayList(); private boolean mIncludeTypedWordIfValid; - private List mStringPool = new ArrayList(); + private ArrayList mStringPool = new ArrayList(); private Context mContext; private boolean mHaveCorrection; private CharSequence mOriginalWord; @@ -63,11 +67,11 @@ public class Suggest implements Dictionary.WordCallback { mStringPool.add(sb); } } - + public int getCorrectionMode() { return mCorrectionMode; } - + public void setCorrectionMode(int mode) { mCorrectionMode = mode; } @@ -80,6 +84,17 @@ public class Suggest implements Dictionary.WordCallback { mUserDictionary = userDictionary; } + /** + * Sets an optional contacts dictionary resource to be loaded. + */ + public void setContactsDictionary(Dictionary userDictionary) { + mContactsDictionary = userDictionary; + } + + public void setAutoDictionary(Dictionary autoDictionary) { + mAutoDictionary = autoDictionary; + } + /** * Number of suggestions to generate from the input key sequence. This has * to be a number between 1 and 100 (inclusive). @@ -98,24 +113,34 @@ public class Suggest implements Dictionary.WordCallback { mStringPool.add(sb); } } - + private boolean haveSufficientCommonality(String original, CharSequence suggestion) { - final int len = Math.min(original.length(), suggestion.length()); - if (len <= 2) return true; + final int originalLength = original.length(); + final int suggestionLength = suggestion.length(); + final int minLength = Math.min(originalLength, suggestionLength); + if (minLength <= 2) return true; int matching = 0; - for (int i = 0; i < len; i++) { - if (UserDictionary.toLowerCase(original.charAt(i)) - == UserDictionary.toLowerCase(suggestion.charAt(i))) { + int lessMatching = 0; // Count matches if we skip one character + int i; + for (i = 0; i < minLength; i++) { + final char origChar = ExpandableDictionary.toLowerCase(original.charAt(i)); + if (origChar == ExpandableDictionary.toLowerCase(suggestion.charAt(i))) { matching++; + lessMatching++; + } else if (i + 1 < suggestionLength + && origChar == ExpandableDictionary.toLowerCase(suggestion.charAt(i + 1))) { + lessMatching++; } } - if (len <= 4) { + matching = Math.max(matching, lessMatching); + + if (minLength <= 4) { return matching >= 2; } else { - return matching > len / 2; + return matching > minLength / 2; } } - + /** * Returns a list of words that match the list of character codes passed in. * This list will be overwritten the next time this function is called. @@ -142,8 +167,14 @@ public class Suggest implements Dictionary.WordCallback { } // Search the dictionary only if there are at least 2 characters if (wordComposer.size() > 1) { - if (mUserDictionary != null) { - mUserDictionary.getWords(wordComposer, this); + if (mUserDictionary != null || mContactsDictionary != null) { + if (mUserDictionary != null) { + mUserDictionary.getWords(wordComposer, this); + } + if (mContactsDictionary != null) { + mContactsDictionary.getWords(wordComposer, this); + } + if (mSuggestions.size() > 0 && isValidWord(mOriginalWord)) { mHaveCorrection = true; } @@ -187,10 +218,38 @@ public class Suggest implements Dictionary.WordCallback { } i++; } - + + removeDupes(); return mSuggestions; } + private void removeDupes() { + final ArrayList suggestions = mSuggestions; + 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 candidate with each previous candidate + for (int j = 0; j < i; j++) { + CharSequence previous = suggestions.get(j); + if (TextUtils.equals(cur, previous)) { + removeFromSuggestions(i); + i--; + break; + } + } + i++; + } + } + + private void removeFromSuggestions(int index) { + CharSequence garbage = mSuggestions.remove(index); + if (garbage != null && garbage instanceof StringBuilder) { + mStringPool.add(garbage); + } + } + public boolean hasMinimalCorrection() { return mHaveCorrection; } @@ -256,7 +315,9 @@ public class Suggest implements Dictionary.WordCallback { } return (mCorrectionMode == CORRECTION_FULL && mMainDict.isValidWord(word)) || (mCorrectionMode > CORRECTION_NONE && - (mUserDictionary != null && mUserDictionary.isValidWord(word))); + ((mUserDictionary != null && mUserDictionary.isValidWord(word))) + || (mAutoDictionary != null && mAutoDictionary.isValidWord(word)) + || (mContactsDictionary != null && mContactsDictionary.isValidWord(word))); } private void collectGarbage() { diff --git a/src/com/android/inputmethod/latin/UserDictionary.java b/src/com/android/inputmethod/latin/UserDictionary.java index 09549bf8c..2f3447abd 100644 --- a/src/com/android/inputmethod/latin/UserDictionary.java +++ b/src/com/android/inputmethod/latin/UserDictionary.java @@ -26,7 +26,7 @@ import android.database.ContentObserver; import android.database.Cursor; import android.provider.UserDictionary.Words; -public class UserDictionary extends Dictionary { +public class UserDictionary extends ExpandableDictionary { private static final String[] PROJECTION = { Words._ID, @@ -37,31 +37,12 @@ public class UserDictionary extends Dictionary { private static final int INDEX_WORD = 1; private static final int INDEX_FREQUENCY = 2; - private static final char QUOTE = '\''; - - private Context mContext; - - List mRoots; - private int mMaxDepth; - private int mInputLength; - - public static final int MAX_WORD_LENGTH = 32; - - private char[] mWordBuilder = new char[MAX_WORD_LENGTH]; - private ContentObserver mObserver; - static class Node { - char code; - int frequency; - boolean terminal; - List children; - } - private boolean mRequiresReload; public UserDictionary(Context context) { - mContext = context; + super(context); // Perform a managed query. The Activity will handle closing and requerying the cursor // when needed. ContentResolver cres = context.getContentResolver(); @@ -78,13 +59,13 @@ public class UserDictionary extends Dictionary { public synchronized void close() { if (mObserver != null) { - mContext.getContentResolver().unregisterContentObserver(mObserver); + getContext().getContentResolver().unregisterContentObserver(mObserver); mObserver = null; } } private synchronized void loadDictionary() { - Cursor cursor = mContext.getContentResolver() + Cursor cursor = getContext().getContentResolver() .query(Words.CONTENT_URI, PROJECTION, "(locale IS NULL) or (locale=?)", new String[] { Locale.getDefault().toString() }, null); addWords(cursor); @@ -99,12 +80,15 @@ public class UserDictionary extends Dictionary { * the highest. * @TODO use a higher or float range for frequency */ + @Override public synchronized void addWord(String word, int frequency) { if (mRequiresReload) loadDictionary(); // Safeguard against adding long words. Can cause stack overflow. - if (word.length() >= MAX_WORD_LENGTH) return; - addWordRec(mRoots, word, 0, frequency); - Words.addWord(mContext, word, frequency, Words.LOCALE_TYPE_CURRENT); + if (word.length() >= getMaxWordLength()) return; + + super.addWord(word, frequency); + + Words.addWord(getContext(), word, frequency, Words.LOCALE_TYPE_CURRENT); // In case the above does a synchronous callback of the change observer mRequiresReload = false; } @@ -112,362 +96,31 @@ public class UserDictionary extends Dictionary { @Override public synchronized void getWords(final WordComposer codes, final WordCallback callback) { if (mRequiresReload) loadDictionary(); - mInputLength = codes.size(); - mMaxDepth = mInputLength * 3; - getWordsRec(mRoots, codes, mWordBuilder, 0, false, 1.0f, 0, callback); + super.getWords(codes, callback); } @Override public synchronized boolean isValidWord(CharSequence word) { if (mRequiresReload) loadDictionary(); - return isValidWordRec(mRoots, word, 0, word.length()); - } - - private boolean isValidWordRec(final List children, final CharSequence word, - final int offset, final int length) { - final int count = children.size(); - char currentChar = word.charAt(offset); - for (int j = 0; j < count; j++) { - final Node node = children.get(j); - if (node.code == currentChar) { - if (offset == length - 1) { - if (node.terminal) { - return true; - } - } else { - if (node.children != null) { - if (isValidWordRec(node.children, word, offset + 1, length)) { - return true; - } - } - } - } - } - return false; - } - - static char toLowerCase(char c) { - if (c < BASE_CHARS.length) { - c = BASE_CHARS[c]; - } - c = Character.toLowerCase(c); - return c; - } - - /** - * Recursively traverse the tree for words that match the input. Input consists of - * a list of arrays. Each item in the list is one input character position. An input - * character is actually an array of multiple possible candidates. This function is not - * optimized for speed, assuming that the user dictionary will only be a few hundred words in - * size. - * @param roots node whose children have to be search for matches - * @param codes the input character codes - * @param word the word being composed as a possible match - * @param depth the depth of traversal - the length of the word being composed thus far - * @param completion whether the traversal is now in completion mode - meaning that we've - * exhausted the input and we're looking for all possible suffixes. - * @param snr current weight of the word being formed - * @param inputIndex position in the input characters. This can be off from the depth in - * case we skip over some punctuations such as apostrophe in the traversal. That is, if you type - * "wouldve", it could be matching "would've", so the depth will be one more than the - * inputIndex - * @param callback the callback class for adding a word - */ - private void getWordsRec(List roots, final WordComposer codes, final char[] word, - final int depth, boolean completion, float snr, int inputIndex, - WordCallback callback) { - final int count = roots.size(); - final int codeSize = mInputLength; - // Optimization: Prune out words that are too long compared to how much was typed. - if (depth > mMaxDepth) { - return; - } - int[] currentChars = null; - if (codeSize <= inputIndex) { - completion = true; - } else { - currentChars = codes.getCodesAt(inputIndex); - } - - for (int i = 0; i < count; i++) { - final Node node = roots.get(i); - final char c = node.code; - final char lowerC = toLowerCase(c); - boolean terminal = node.terminal; - List children = node.children; - int freq = node.frequency; - if (completion) { - word[depth] = c; - if (terminal) { - if (!callback.addWord(word, 0, depth + 1, (int) (freq * snr))) { - return; - } - } - if (children != null) { - getWordsRec(children, codes, word, depth + 1, completion, snr, inputIndex, - callback); - } - } else if (c == QUOTE && currentChars[0] != QUOTE) { - // Skip the ' and continue deeper - word[depth] = QUOTE; - if (children != null) { - getWordsRec(children, codes, word, depth + 1, completion, snr, inputIndex, - callback); - } - } else { - for (int j = 0; j < currentChars.length; j++) { - float addedAttenuation = (j > 0 ? 1f : 3f); - if (currentChars[j] == -1) { - break; - } - if (currentChars[j] == lowerC || currentChars[j] == c) { - word[depth] = c; - - if (codes.size() == depth + 1) { - if (terminal) { - if (INCLUDE_TYPED_WORD_IF_VALID - || !same(word, depth + 1, codes.getTypedWord())) { - callback.addWord(word, 0, depth + 1, - (int) (freq * snr * addedAttenuation - * FULL_WORD_FREQ_MULTIPLIER)); - } - } - if (children != null) { - getWordsRec(children, codes, word, depth + 1, - true, snr * addedAttenuation, inputIndex + 1, callback); - } - } else if (children != null) { - getWordsRec(children, codes, word, depth + 1, - false, snr * addedAttenuation, inputIndex + 1, callback); - } - } - } - } - } + return super.isValidWord(word); } private void addWords(Cursor cursor) { - mRoots = new ArrayList(); - + clearDictionary(); + + final int maxWordLength = getMaxWordLength(); if (cursor.moveToFirst()) { while (!cursor.isAfterLast()) { String word = cursor.getString(INDEX_WORD); int frequency = cursor.getInt(INDEX_FREQUENCY); // Safeguard against adding really long words. Stack may overflow due // to recursion - if (word.length() < MAX_WORD_LENGTH) { - addWordRec(mRoots, word, 0, frequency); + if (word.length() < maxWordLength) { + super.addWord(word, frequency); } cursor.moveToNext(); } } cursor.close(); } - - private void addWordRec(List children, final String word, - final int depth, final int frequency) { - - final int wordLength = word.length(); - final char c = word.charAt(depth); - // Does children have the current character? - final int childrenLength = children.size(); - Node childNode = null; - boolean found = false; - for (int i = 0; i < childrenLength; i++) { - childNode = children.get(i); - if (childNode.code == c) { - found = true; - break; - } - } - if (!found) { - childNode = new Node(); - childNode.code = c; - children.add(childNode); - } - if (wordLength == depth + 1) { - // Terminate this word - childNode.terminal = true; - childNode.frequency += frequency; // If there are multiple similar words - return; - } - if (childNode.children == null) { - childNode.children = new ArrayList(); - } - addWordRec(childNode.children, word, depth + 1, frequency); - } - - /** - * 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 final char BASE_CHARS[] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, - 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, - 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, - 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, - 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, - 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, - 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, - 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, - 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, - 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, - 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, - 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, - 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, - 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, - 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, - 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f, - 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, - 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, - 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, - 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, - 0x0020, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, - 0x0020, 0x00a9, 0x0061, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0020, - 0x00b0, 0x00b1, 0x0032, 0x0033, 0x0020, 0x03bc, 0x00b6, 0x00b7, - 0x0020, 0x0031, 0x006f, 0x00bb, 0x0031, 0x0031, 0x0033, 0x00bf, - 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, 0x0041, 0x00c6, 0x0043, - 0x0045, 0x0045, 0x0045, 0x0045, 0x0049, 0x0049, 0x0049, 0x0049, - 0x00d0, 0x004e, 0x004f, 0x004f, 0x004f, 0x004f, 0x004f, 0x00d7, - 0x004f, 0x0055, 0x0055, 0x0055, 0x0055, 0x0059, 0x00de, 0x0073, // Manually changed d8 to 4f - // Manually changed df to 73 - 0x0061, 0x0061, 0x0061, 0x0061, 0x0061, 0x0061, 0x00e6, 0x0063, - 0x0065, 0x0065, 0x0065, 0x0065, 0x0069, 0x0069, 0x0069, 0x0069, - 0x00f0, 0x006e, 0x006f, 0x006f, 0x006f, 0x006f, 0x006f, 0x00f7, - 0x006f, 0x0075, 0x0075, 0x0075, 0x0075, 0x0079, 0x00fe, 0x0079, // Manually changed f8 to 6f - 0x0041, 0x0061, 0x0041, 0x0061, 0x0041, 0x0061, 0x0043, 0x0063, - 0x0043, 0x0063, 0x0043, 0x0063, 0x0043, 0x0063, 0x0044, 0x0064, - 0x0110, 0x0111, 0x0045, 0x0065, 0x0045, 0x0065, 0x0045, 0x0065, - 0x0045, 0x0065, 0x0045, 0x0065, 0x0047, 0x0067, 0x0047, 0x0067, - 0x0047, 0x0067, 0x0047, 0x0067, 0x0048, 0x0068, 0x0126, 0x0127, - 0x0049, 0x0069, 0x0049, 0x0069, 0x0049, 0x0069, 0x0049, 0x0069, - 0x0049, 0x0131, 0x0049, 0x0069, 0x004a, 0x006a, 0x004b, 0x006b, - 0x0138, 0x004c, 0x006c, 0x004c, 0x006c, 0x004c, 0x006c, 0x004c, - 0x006c, 0x0141, 0x0142, 0x004e, 0x006e, 0x004e, 0x006e, 0x004e, - 0x006e, 0x02bc, 0x014a, 0x014b, 0x004f, 0x006f, 0x004f, 0x006f, - 0x004f, 0x006f, 0x0152, 0x0153, 0x0052, 0x0072, 0x0052, 0x0072, - 0x0052, 0x0072, 0x0053, 0x0073, 0x0053, 0x0073, 0x0053, 0x0073, - 0x0053, 0x0073, 0x0054, 0x0074, 0x0054, 0x0074, 0x0166, 0x0167, - 0x0055, 0x0075, 0x0055, 0x0075, 0x0055, 0x0075, 0x0055, 0x0075, - 0x0055, 0x0075, 0x0055, 0x0075, 0x0057, 0x0077, 0x0059, 0x0079, - 0x0059, 0x005a, 0x007a, 0x005a, 0x007a, 0x005a, 0x007a, 0x0073, - 0x0180, 0x0181, 0x0182, 0x0183, 0x0184, 0x0185, 0x0186, 0x0187, - 0x0188, 0x0189, 0x018a, 0x018b, 0x018c, 0x018d, 0x018e, 0x018f, - 0x0190, 0x0191, 0x0192, 0x0193, 0x0194, 0x0195, 0x0196, 0x0197, - 0x0198, 0x0199, 0x019a, 0x019b, 0x019c, 0x019d, 0x019e, 0x019f, - 0x004f, 0x006f, 0x01a2, 0x01a3, 0x01a4, 0x01a5, 0x01a6, 0x01a7, - 0x01a8, 0x01a9, 0x01aa, 0x01ab, 0x01ac, 0x01ad, 0x01ae, 0x0055, - 0x0075, 0x01b1, 0x01b2, 0x01b3, 0x01b4, 0x01b5, 0x01b6, 0x01b7, - 0x01b8, 0x01b9, 0x01ba, 0x01bb, 0x01bc, 0x01bd, 0x01be, 0x01bf, - 0x01c0, 0x01c1, 0x01c2, 0x01c3, 0x0044, 0x0044, 0x0064, 0x004c, - 0x004c, 0x006c, 0x004e, 0x004e, 0x006e, 0x0041, 0x0061, 0x0049, - 0x0069, 0x004f, 0x006f, 0x0055, 0x0075, 0x00dc, 0x00fc, 0x00dc, - 0x00fc, 0x00dc, 0x00fc, 0x00dc, 0x00fc, 0x01dd, 0x00c4, 0x00e4, - 0x0226, 0x0227, 0x00c6, 0x00e6, 0x01e4, 0x01e5, 0x0047, 0x0067, - 0x004b, 0x006b, 0x004f, 0x006f, 0x01ea, 0x01eb, 0x01b7, 0x0292, - 0x006a, 0x0044, 0x0044, 0x0064, 0x0047, 0x0067, 0x01f6, 0x01f7, - 0x004e, 0x006e, 0x00c5, 0x00e5, 0x00c6, 0x00e6, 0x00d8, 0x00f8, - 0x0041, 0x0061, 0x0041, 0x0061, 0x0045, 0x0065, 0x0045, 0x0065, - 0x0049, 0x0069, 0x0049, 0x0069, 0x004f, 0x006f, 0x004f, 0x006f, - 0x0052, 0x0072, 0x0052, 0x0072, 0x0055, 0x0075, 0x0055, 0x0075, - 0x0053, 0x0073, 0x0054, 0x0074, 0x021c, 0x021d, 0x0048, 0x0068, - 0x0220, 0x0221, 0x0222, 0x0223, 0x0224, 0x0225, 0x0041, 0x0061, - 0x0045, 0x0065, 0x00d6, 0x00f6, 0x00d5, 0x00f5, 0x004f, 0x006f, - 0x022e, 0x022f, 0x0059, 0x0079, 0x0234, 0x0235, 0x0236, 0x0237, - 0x0238, 0x0239, 0x023a, 0x023b, 0x023c, 0x023d, 0x023e, 0x023f, - 0x0240, 0x0241, 0x0242, 0x0243, 0x0244, 0x0245, 0x0246, 0x0247, - 0x0248, 0x0249, 0x024a, 0x024b, 0x024c, 0x024d, 0x024e, 0x024f, - 0x0250, 0x0251, 0x0252, 0x0253, 0x0254, 0x0255, 0x0256, 0x0257, - 0x0258, 0x0259, 0x025a, 0x025b, 0x025c, 0x025d, 0x025e, 0x025f, - 0x0260, 0x0261, 0x0262, 0x0263, 0x0264, 0x0265, 0x0266, 0x0267, - 0x0268, 0x0269, 0x026a, 0x026b, 0x026c, 0x026d, 0x026e, 0x026f, - 0x0270, 0x0271, 0x0272, 0x0273, 0x0274, 0x0275, 0x0276, 0x0277, - 0x0278, 0x0279, 0x027a, 0x027b, 0x027c, 0x027d, 0x027e, 0x027f, - 0x0280, 0x0281, 0x0282, 0x0283, 0x0284, 0x0285, 0x0286, 0x0287, - 0x0288, 0x0289, 0x028a, 0x028b, 0x028c, 0x028d, 0x028e, 0x028f, - 0x0290, 0x0291, 0x0292, 0x0293, 0x0294, 0x0295, 0x0296, 0x0297, - 0x0298, 0x0299, 0x029a, 0x029b, 0x029c, 0x029d, 0x029e, 0x029f, - 0x02a0, 0x02a1, 0x02a2, 0x02a3, 0x02a4, 0x02a5, 0x02a6, 0x02a7, - 0x02a8, 0x02a9, 0x02aa, 0x02ab, 0x02ac, 0x02ad, 0x02ae, 0x02af, - 0x0068, 0x0266, 0x006a, 0x0072, 0x0279, 0x027b, 0x0281, 0x0077, - 0x0079, 0x02b9, 0x02ba, 0x02bb, 0x02bc, 0x02bd, 0x02be, 0x02bf, - 0x02c0, 0x02c1, 0x02c2, 0x02c3, 0x02c4, 0x02c5, 0x02c6, 0x02c7, - 0x02c8, 0x02c9, 0x02ca, 0x02cb, 0x02cc, 0x02cd, 0x02ce, 0x02cf, - 0x02d0, 0x02d1, 0x02d2, 0x02d3, 0x02d4, 0x02d5, 0x02d6, 0x02d7, - 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x02de, 0x02df, - 0x0263, 0x006c, 0x0073, 0x0078, 0x0295, 0x02e5, 0x02e6, 0x02e7, - 0x02e8, 0x02e9, 0x02ea, 0x02eb, 0x02ec, 0x02ed, 0x02ee, 0x02ef, - 0x02f0, 0x02f1, 0x02f2, 0x02f3, 0x02f4, 0x02f5, 0x02f6, 0x02f7, - 0x02f8, 0x02f9, 0x02fa, 0x02fb, 0x02fc, 0x02fd, 0x02fe, 0x02ff, - 0x0300, 0x0301, 0x0302, 0x0303, 0x0304, 0x0305, 0x0306, 0x0307, - 0x0308, 0x0309, 0x030a, 0x030b, 0x030c, 0x030d, 0x030e, 0x030f, - 0x0310, 0x0311, 0x0312, 0x0313, 0x0314, 0x0315, 0x0316, 0x0317, - 0x0318, 0x0319, 0x031a, 0x031b, 0x031c, 0x031d, 0x031e, 0x031f, - 0x0320, 0x0321, 0x0322, 0x0323, 0x0324, 0x0325, 0x0326, 0x0327, - 0x0328, 0x0329, 0x032a, 0x032b, 0x032c, 0x032d, 0x032e, 0x032f, - 0x0330, 0x0331, 0x0332, 0x0333, 0x0334, 0x0335, 0x0336, 0x0337, - 0x0338, 0x0339, 0x033a, 0x033b, 0x033c, 0x033d, 0x033e, 0x033f, - 0x0300, 0x0301, 0x0342, 0x0313, 0x0308, 0x0345, 0x0346, 0x0347, - 0x0348, 0x0349, 0x034a, 0x034b, 0x034c, 0x034d, 0x034e, 0x034f, - 0x0350, 0x0351, 0x0352, 0x0353, 0x0354, 0x0355, 0x0356, 0x0357, - 0x0358, 0x0359, 0x035a, 0x035b, 0x035c, 0x035d, 0x035e, 0x035f, - 0x0360, 0x0361, 0x0362, 0x0363, 0x0364, 0x0365, 0x0366, 0x0367, - 0x0368, 0x0369, 0x036a, 0x036b, 0x036c, 0x036d, 0x036e, 0x036f, - 0x0370, 0x0371, 0x0372, 0x0373, 0x02b9, 0x0375, 0x0376, 0x0377, - 0x0378, 0x0379, 0x0020, 0x037b, 0x037c, 0x037d, 0x003b, 0x037f, - 0x0380, 0x0381, 0x0382, 0x0383, 0x0020, 0x00a8, 0x0391, 0x00b7, - 0x0395, 0x0397, 0x0399, 0x038b, 0x039f, 0x038d, 0x03a5, 0x03a9, - 0x03ca, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, - 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, - 0x03a0, 0x03a1, 0x03a2, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, - 0x03a8, 0x03a9, 0x0399, 0x03a5, 0x03b1, 0x03b5, 0x03b7, 0x03b9, - 0x03cb, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, - 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, - 0x03c0, 0x03c1, 0x03c2, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, - 0x03c8, 0x03c9, 0x03b9, 0x03c5, 0x03bf, 0x03c5, 0x03c9, 0x03cf, - 0x03b2, 0x03b8, 0x03a5, 0x03d2, 0x03d2, 0x03c6, 0x03c0, 0x03d7, - 0x03d8, 0x03d9, 0x03da, 0x03db, 0x03dc, 0x03dd, 0x03de, 0x03df, - 0x03e0, 0x03e1, 0x03e2, 0x03e3, 0x03e4, 0x03e5, 0x03e6, 0x03e7, - 0x03e8, 0x03e9, 0x03ea, 0x03eb, 0x03ec, 0x03ed, 0x03ee, 0x03ef, - 0x03ba, 0x03c1, 0x03c2, 0x03f3, 0x0398, 0x03b5, 0x03f6, 0x03f7, - 0x03f8, 0x03a3, 0x03fa, 0x03fb, 0x03fc, 0x03fd, 0x03fe, 0x03ff, - 0x0415, 0x0415, 0x0402, 0x0413, 0x0404, 0x0405, 0x0406, 0x0406, - 0x0408, 0x0409, 0x040a, 0x040b, 0x041a, 0x0418, 0x0423, 0x040f, - 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, - 0x0418, 0x0418, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f, - 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, - 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f, - 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, - 0x0438, 0x0438, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f, - 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, - 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f, - 0x0435, 0x0435, 0x0452, 0x0433, 0x0454, 0x0455, 0x0456, 0x0456, - 0x0458, 0x0459, 0x045a, 0x045b, 0x043a, 0x0438, 0x0443, 0x045f, - 0x0460, 0x0461, 0x0462, 0x0463, 0x0464, 0x0465, 0x0466, 0x0467, - 0x0468, 0x0469, 0x046a, 0x046b, 0x046c, 0x046d, 0x046e, 0x046f, - 0x0470, 0x0471, 0x0472, 0x0473, 0x0474, 0x0475, 0x0474, 0x0475, - 0x0478, 0x0479, 0x047a, 0x047b, 0x047c, 0x047d, 0x047e, 0x047f, - 0x0480, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487, - 0x0488, 0x0489, 0x048a, 0x048b, 0x048c, 0x048d, 0x048e, 0x048f, - 0x0490, 0x0491, 0x0492, 0x0493, 0x0494, 0x0495, 0x0496, 0x0497, - 0x0498, 0x0499, 0x049a, 0x049b, 0x049c, 0x049d, 0x049e, 0x049f, - 0x04a0, 0x04a1, 0x04a2, 0x04a3, 0x04a4, 0x04a5, 0x04a6, 0x04a7, - 0x04a8, 0x04a9, 0x04aa, 0x04ab, 0x04ac, 0x04ad, 0x04ae, 0x04af, - 0x04b0, 0x04b1, 0x04b2, 0x04b3, 0x04b4, 0x04b5, 0x04b6, 0x04b7, - 0x04b8, 0x04b9, 0x04ba, 0x04bb, 0x04bc, 0x04bd, 0x04be, 0x04bf, - 0x04c0, 0x0416, 0x0436, 0x04c3, 0x04c4, 0x04c5, 0x04c6, 0x04c7, - 0x04c8, 0x04c9, 0x04ca, 0x04cb, 0x04cc, 0x04cd, 0x04ce, 0x04cf, - 0x0410, 0x0430, 0x0410, 0x0430, 0x04d4, 0x04d5, 0x0415, 0x0435, - 0x04d8, 0x04d9, 0x04d8, 0x04d9, 0x0416, 0x0436, 0x0417, 0x0437, - 0x04e0, 0x04e1, 0x0418, 0x0438, 0x0418, 0x0438, 0x041e, 0x043e, - 0x04e8, 0x04e9, 0x04e8, 0x04e9, 0x042d, 0x044d, 0x0423, 0x0443, - 0x0423, 0x0443, 0x0423, 0x0443, 0x0427, 0x0447, 0x04f6, 0x04f7, - 0x042b, 0x044b, 0x04fa, 0x04fb, 0x04fc, 0x04fd, 0x04fe, 0x04ff, - }; - - // 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"; }' - } diff --git a/src/com/android/inputmethod/latin/WordComposer.java b/src/com/android/inputmethod/latin/WordComposer.java index c950a7f18..50725d481 100644 --- a/src/com/android/inputmethod/latin/WordComposer.java +++ b/src/com/android/inputmethod/latin/WordComposer.java @@ -26,7 +26,7 @@ public class WordComposer { /** * The list of unicode values for each keystroke (including surrounding keys) */ - private List mCodes; + private ArrayList mCodes; /** * The word chosen from the candidate list, until it is committed. @@ -34,6 +34,8 @@ public class WordComposer { private String mPreferredWord; private StringBuilder mTypedWord; + + private int mCapsCount; /** * Whether the user chose to capitalize the word. @@ -53,6 +55,7 @@ public class WordComposer { mIsCapitalized = false; mPreferredWord = null; mTypedWord.setLength(0); + mCapsCount = 0; } /** @@ -80,6 +83,7 @@ public class WordComposer { public void add(int primaryCode, int[] codes) { mTypedWord.append((char) primaryCode); mCodes.add(codes); + if (Character.isUpperCase((char) primaryCode)) mCapsCount++; } /** @@ -87,7 +91,10 @@ public class WordComposer { */ public void deleteLast() { mCodes.remove(mCodes.size() - 1); - mTypedWord.deleteCharAt(mTypedWord.length() - 1); + final int lastPos = mTypedWord.length() - 1; + char last = mTypedWord.charAt(lastPos); + mTypedWord.deleteCharAt(lastPos); + if (Character.isUpperCase(last)) mCapsCount--; } /** @@ -138,4 +145,11 @@ public class WordComposer { public CharSequence getPreferredWord() { return mPreferredWord != null ? mPreferredWord : getTypedWord(); } + + /** + * Returns true if more than one character is upper case, otherwise returns false. + */ + public boolean isMostlyCaps() { + return mCapsCount > 1; + } }