diff --git a/src/java/KP2ASoftkeyboard_AS/.gradle/2.2.1/taskArtifacts/cache.properties b/src/java/KP2ASoftkeyboard_AS/.gradle/2.2.1/taskArtifacts/cache.properties new file mode 100644 index 00000000..d7a1ebf0 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/.gradle/2.2.1/taskArtifacts/cache.properties @@ -0,0 +1 @@ +#Wed Jan 13 21:02:12 CET 2016 diff --git a/src/java/KP2ASoftkeyboard_AS/.gradle/2.2.1/taskArtifacts/cache.properties.lock b/src/java/KP2ASoftkeyboard_AS/.gradle/2.2.1/taskArtifacts/cache.properties.lock new file mode 100644 index 00000000..6b3f09e9 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/.gradle/2.2.1/taskArtifacts/cache.properties.lock differ diff --git a/src/java/KP2ASoftkeyboard_AS/.gradle/2.2.1/taskArtifacts/fileHashes.bin b/src/java/KP2ASoftkeyboard_AS/.gradle/2.2.1/taskArtifacts/fileHashes.bin new file mode 100644 index 00000000..d7797471 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/.gradle/2.2.1/taskArtifacts/fileHashes.bin differ diff --git a/src/java/KP2ASoftkeyboard_AS/.gradle/2.2.1/taskArtifacts/fileSnapshots.bin b/src/java/KP2ASoftkeyboard_AS/.gradle/2.2.1/taskArtifacts/fileSnapshots.bin new file mode 100644 index 00000000..b5aac01a Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/.gradle/2.2.1/taskArtifacts/fileSnapshots.bin differ diff --git a/src/java/KP2ASoftkeyboard_AS/.gradle/2.2.1/taskArtifacts/outputFileStates.bin b/src/java/KP2ASoftkeyboard_AS/.gradle/2.2.1/taskArtifacts/outputFileStates.bin new file mode 100644 index 00000000..95cbdb0a Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/.gradle/2.2.1/taskArtifacts/outputFileStates.bin differ diff --git a/src/java/KP2ASoftkeyboard_AS/.gradle/2.2.1/taskArtifacts/taskArtifacts.bin b/src/java/KP2ASoftkeyboard_AS/.gradle/2.2.1/taskArtifacts/taskArtifacts.bin new file mode 100644 index 00000000..7074d5ee Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/.gradle/2.2.1/taskArtifacts/taskArtifacts.bin differ diff --git a/src/java/KP2ASoftkeyboard_AS/.idea/.name b/src/java/KP2ASoftkeyboard_AS/.idea/.name new file mode 100644 index 00000000..85863977 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/.idea/.name @@ -0,0 +1 @@ +java \ No newline at end of file diff --git a/src/java/KP2ASoftkeyboard_AS/.idea/compiler.xml b/src/java/KP2ASoftkeyboard_AS/.idea/compiler.xml new file mode 100644 index 00000000..96cc43ef --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/.idea/compiler.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/java/KP2ASoftkeyboard_AS/.idea/copyright/profiles_settings.xml b/src/java/KP2ASoftkeyboard_AS/.idea/copyright/profiles_settings.xml new file mode 100644 index 00000000..e7bedf33 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/.idea/copyright/profiles_settings.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/java/KP2ASoftkeyboard_AS/.idea/gradle.xml b/src/java/KP2ASoftkeyboard_AS/.idea/gradle.xml new file mode 100644 index 00000000..3ed2e6cb --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/.idea/gradle.xml @@ -0,0 +1,19 @@ + + + + + + \ No newline at end of file diff --git a/src/java/KP2ASoftkeyboard_AS/.idea/misc.xml b/src/java/KP2ASoftkeyboard_AS/.idea/misc.xml new file mode 100644 index 00000000..8f712fe7 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/.idea/misc.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + 1.7 + + + + + + + + \ No newline at end of file diff --git a/src/java/KP2ASoftkeyboard_AS/.idea/modules.xml b/src/java/KP2ASoftkeyboard_AS/.idea/modules.xml new file mode 100644 index 00000000..0b4bd520 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/.idea/modules.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/java/KP2ASoftkeyboard_AS/.idea/vcs.xml b/src/java/KP2ASoftkeyboard_AS/.idea/vcs.xml new file mode 100644 index 00000000..6564d52d --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/java/KP2ASoftkeyboard_AS/.idea/workspace.xml b/src/java/KP2ASoftkeyboard_AS/.idea/workspace.xml new file mode 100644 index 00000000..6946705a --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/.idea/workspace.xml @@ -0,0 +1,1898 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1452666450747 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/java/KP2ASoftkeyboard_AS/KP2ASoftkeyboard_AS.iml b/src/java/KP2ASoftkeyboard_AS/KP2ASoftkeyboard_AS.iml new file mode 100644 index 00000000..d01d4599 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/KP2ASoftkeyboard_AS.iml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/java/KP2ASoftkeyboard_AS/app/app.iml b/src/java/KP2ASoftkeyboard_AS/app/app.iml new file mode 100644 index 00000000..2b96be4c --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/app.iml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/java/KP2ASoftkeyboard_AS/app/build.gradle b/src/java/KP2ASoftkeyboard_AS/app/build.gradle new file mode 100644 index 00000000..a92e1982 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/build.gradle @@ -0,0 +1,18 @@ +apply plugin: 'com.android.library' + +android { + compileSdkVersion 23 + buildToolsVersion "23.0.0" + + defaultConfig { + minSdkVersion 14 + targetSdkVersion 23 + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' + } + } +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/AndroidManifest.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/AndroidManifest.xml new file mode 100644 index 00000000..4101f662 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/AndroidManifest.xml @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/kbbridge/ImeSwitcher.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/kbbridge/ImeSwitcher.java new file mode 100644 index 00000000..4232e424 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/kbbridge/ImeSwitcher.java @@ -0,0 +1,110 @@ +package keepass2android.kbbridge; + +import java.util.List; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; +import android.content.pm.ActivityInfo; +import android.content.pm.ResolveInfo; +import android.inputmethodservice.InputMethodService; +import android.os.Bundle; +import android.os.IBinder; +import android.preference.PreferenceManager; +import android.util.Log; +import android.view.inputmethod.InputMethod; +import android.view.inputmethod.InputMethodManager; +import android.widget.Toast; + +public class ImeSwitcher { + private static final String SECURE_SETTINGS_PACKAGE_NAME = "com.intangibleobject.securesettings.plugin"; + private static final String PREVIOUS_KEYBOARD = "previous_keyboard"; + private static final String KP2A_SWITCHER = "KP2A_Switcher"; + private static final String Tag = "KP2A_SWITCHER"; + + public static void switchToPreviousKeyboard(InputMethodService ims, boolean silent) + { + try { + InputMethodManager imm = (InputMethodManager) ims.getSystemService(Context.INPUT_METHOD_SERVICE); + final IBinder token = ims.getWindow().getWindow().getAttributes().token; + //imm.setInputMethod(token, LATIN); + imm.switchToLastInputMethod(token); + } catch (Throwable t) { // java.lang.NoSuchMethodError if API_level<11 + Log.e("KP2A","cannot set the previous input method:"); + t.printStackTrace(); + SharedPreferences prefs = ims.getSharedPreferences(KP2A_SWITCHER, Context.MODE_PRIVATE); + switchToKeyboard(ims, prefs.getString(PREVIOUS_KEYBOARD, null), silent); + } + + } + + //silent: if true, do not show picker, only switch in background. Don't do anything if switching fails. + public static void switchToKeyboard(Context ctx, String newImeName, boolean silent) + { + Log.d(Tag,"silent: "+silent); + if ((newImeName == null) || (!autoSwitchEnabled(ctx))) + { + Log.d(Tag, "(newImeName == null): "+(newImeName == null)); + Log.d(Tag, "autoSwitchEnabled(ctx)"+autoSwitchEnabled(ctx)); + if (!silent) + { + showPicker(ctx); + } + return; + } + Intent qi = new Intent("com.twofortyfouram.locale.intent.action.FIRE_SETTING"); + List pkgAppsList = ctx.getPackageManager().queryBroadcastReceivers(qi, 0); + boolean sentBroadcast = false; + for (ResolveInfo ri: pkgAppsList) + { + if (ri.activityInfo.packageName.equals(SECURE_SETTINGS_PACKAGE_NAME)) + { + + String currentIme = android.provider.Settings.Secure.getString( + ctx.getContentResolver(), + android.provider.Settings.Secure.DEFAULT_INPUT_METHOD); + currentIme += ";"+String.valueOf( + android.provider.Settings.Secure.getInt( + ctx.getContentResolver(), + android.provider.Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE, + -1) + ); + SharedPreferences prefs = ctx.getSharedPreferences(KP2A_SWITCHER, Context.MODE_PRIVATE); + Editor edit = prefs.edit(); + + edit.putString(PREVIOUS_KEYBOARD, currentIme); + edit.commit(); + + Intent i=new Intent("com.twofortyfouram.locale.intent.action.FIRE_SETTING"); + Bundle b = new Bundle(); + + b.putString("com.intangibleobject.securesettings.plugin.extra.BLURB", "Input Method/SwitchIME"); + b.putString("com.intangibleobject.securesettings.plugin.extra.INPUT_METHOD", newImeName); + b.putString("com.intangibleobject.securesettings.plugin.extra.SETTING","default_input_method"); + i.putExtra("com.twofortyfouram.locale.intent.extra.BUNDLE", b); + i.setPackage(SECURE_SETTINGS_PACKAGE_NAME); + Log.d(Tag,"trying to switch by broadcast to SecureSettings"); + ctx.sendBroadcast(i); + sentBroadcast = true; + break; + } + } + if ((!sentBroadcast) && (!silent)) + { + showPicker(ctx); + } + + } + + private static boolean autoSwitchEnabled(Context ctx) { + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(ctx); + return sp.getBoolean("kp2a_switch_rooted", false); + } + + private static void showPicker(Context ctx) { + ((InputMethodManager) ctx.getSystemService(InputMethodService.INPUT_METHOD_SERVICE)) + .showInputMethodPicker(); + } +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/kbbridge/KeyboardData.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/kbbridge/KeyboardData.java new file mode 100644 index 00000000..15055895 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/kbbridge/KeyboardData.java @@ -0,0 +1,24 @@ + +package keepass2android.kbbridge; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import android.text.TextUtils; +public class KeyboardData +{ + public static List availableFields = new ArrayList(); + public static String entryName; + public static String entryId; + + public static boolean hasData() + { + return !TextUtils.isEmpty(entryId); + } + + public static void clear() + { + availableFields.clear(); + entryName = entryId = ""; + } +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/kbbridge/KeyboardDataBuilder.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/kbbridge/KeyboardDataBuilder.java new file mode 100644 index 00000000..e2dee9f6 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/kbbridge/KeyboardDataBuilder.java @@ -0,0 +1,20 @@ +package keepass2android.kbbridge; +import java.util.ArrayList; +import java.util.HashMap; +public class KeyboardDataBuilder { + private ArrayList availableFields = new ArrayList(); + + public void addString(String key, String displayName, String valueToType) + { + StringForTyping stringToType = new StringForTyping(); + stringToType.key = key; + stringToType.displayName = displayName; + stringToType.value = valueToType; + availableFields.add(stringToType); + } + + public void commit() + { + KeyboardData.availableFields = this.availableFields; + } +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/kbbridge/StringForTyping.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/kbbridge/StringForTyping.java new file mode 100644 index 00000000..9348dad2 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/kbbridge/StringForTyping.java @@ -0,0 +1,20 @@ +package keepass2android.kbbridge; + +public class StringForTyping { + public String key; //internal identifier (PwEntry string field key) + public String displayName; //display name for displaying the key (might be translated) + public String value; + + @Override + public StringForTyping clone(){ + + StringForTyping theClone = new StringForTyping(); + theClone.key = key; + theClone.displayName = displayName; + theClone.value = value; + + return theClone; + } + + +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/AutoDictionary.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/AutoDictionary.java new file mode 100644 index 00000000..cb427a2c --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/AutoDictionary.java @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 keepass2android.softkeyboard; + +import java.util.HashMap; +import java.util.Set; +import java.util.Map.Entry; + +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.database.sqlite.SQLiteQueryBuilder; +import android.os.AsyncTask; +import android.provider.BaseColumns; +import android.util.Log; + +/** + * Stores new words temporarily until they are promoted to the user dictionary + * for longevity. Words in the auto dictionary are used to determine if it's ok + * to accept a word that's not in the main or user dictionary. Using a new word + * repeatedly will promote it to the user dictionary. + */ +public class AutoDictionary extends ExpandableDictionary { + // 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 gets promoted to the user dictionary, uses this + // frequency. + static final int FREQUENCY_FOR_AUTO_ADD = 250; + // 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 4 times or more, it will be added to the user dict. + private static final int PROMOTION_THRESHOLD = 4 * FREQUENCY_FOR_PICKED; + + private KP2AKeyboard mIme; + // Locale for which this auto dictionary is storing words + private String mLocale; + + private HashMap mPendingWrites = new HashMap(); + private final Object mPendingWritesLock = new Object(); + + private static final String DATABASE_NAME = "auto_dict.db"; + private static final int DATABASE_VERSION = 1; + + // These are the columns in the dictionary + // TODO: Consume less space by using a unique id for locale instead of the whole + // 2-5 character string. + private static final String COLUMN_ID = BaseColumns._ID; + private static final String COLUMN_WORD = "word"; + private static final String COLUMN_FREQUENCY = "freq"; + private static final String COLUMN_LOCALE = "locale"; + + /** Sort by descending order of frequency. */ + public static final String DEFAULT_SORT_ORDER = COLUMN_FREQUENCY + " DESC"; + + /** Name of the words table in the auto_dict.db */ + private static final String AUTODICT_TABLE_NAME = "words"; + + private static HashMap sDictProjectionMap; + + static { + sDictProjectionMap = new HashMap(); + sDictProjectionMap.put(COLUMN_ID, COLUMN_ID); + sDictProjectionMap.put(COLUMN_WORD, COLUMN_WORD); + sDictProjectionMap.put(COLUMN_FREQUENCY, COLUMN_FREQUENCY); + sDictProjectionMap.put(COLUMN_LOCALE, COLUMN_LOCALE); + } + + private static DatabaseHelper sOpenHelper = null; + + public AutoDictionary(Context context, KP2AKeyboard ime, String locale, int dicTypeId) { + super(context, dicTypeId); + mIme = ime; + mLocale = locale; + if (sOpenHelper == null) { + sOpenHelper = new DatabaseHelper(getContext()); + } + if (mLocale != null && mLocale.length() > 1) { + loadDictionary(); + } + } + + @Override + public boolean isValidWord(CharSequence word) { + final int frequency = getWordFrequency(word); + return frequency >= VALIDITY_THRESHOLD; + } + + @Override + public void close() { + flushPendingWrites(); + // Don't close the database as locale changes will require it to be reopened anyway + // Also, the database is written to somewhat frequently, so it needs to be kept alive + // throughout the life of the process. + // mOpenHelper.close(); + super.close(); + } + + @Override + public void loadDictionaryAsync() { + // Load the words that correspond to the current input locale + Cursor cursor = query(COLUMN_LOCALE + "=?", new String[] { mLocale }); + try { + if (cursor.moveToFirst()) { + int wordIndex = cursor.getColumnIndex(COLUMN_WORD); + int frequencyIndex = cursor.getColumnIndex(COLUMN_FREQUENCY); + while (!cursor.isAfterLast()) { + String word = cursor.getString(wordIndex); + int frequency = cursor.getInt(frequencyIndex); + // Safeguard against adding really long words. Stack may overflow due + // to recursive lookup + if (word.length() < getMaxWordLength()) { + super.addWord(word, frequency); + } + cursor.moveToNext(); + } + } + } finally { + cursor.close(); + } + } + + @Override + public void addWord(String word, int addFrequency) { + final int length = word.length(); + // Don't add very short or very long words. + if (length < 2 || length > getMaxWordLength()) return; + if (mIme.getCurrentWord().isAutoCapitalized()) { + // Remove caps before adding + word = Character.toLowerCase(word.charAt(0)) + word.substring(1); + } + int freq = getWordFrequency(word); + freq = freq < 0 ? addFrequency : freq + addFrequency; + super.addWord(word, freq); + + if (freq >= PROMOTION_THRESHOLD) { + mIme.promoteToUserDictionary(word, FREQUENCY_FOR_AUTO_ADD); + freq = 0; + } + + synchronized (mPendingWritesLock) { + // Write a null frequency if it is to be deleted from the db + mPendingWrites.put(word, freq == 0 ? null : new Integer(freq)); + } + } + + /** + * Schedules a background thread to write any pending words to the database. + */ + public void flushPendingWrites() { + synchronized (mPendingWritesLock) { + // Nothing pending? Return + if (mPendingWrites.isEmpty()) return; + // Create a background thread to write the pending entries + new UpdateDbTask(getContext(), sOpenHelper, mPendingWrites, mLocale).execute(); + // Create a new map for writing new entries into while the old one is written to db + mPendingWrites = new HashMap(); + } + } + + /** + * This class helps open, create, and upgrade the database file. + */ + private static class DatabaseHelper extends SQLiteOpenHelper { + + DatabaseHelper(Context context) { + super(context, DATABASE_NAME, null, DATABASE_VERSION); + } + + @Override + public void onCreate(SQLiteDatabase db) { + db.execSQL("CREATE TABLE " + AUTODICT_TABLE_NAME + " (" + + COLUMN_ID + " INTEGER PRIMARY KEY," + + COLUMN_WORD + " TEXT," + + COLUMN_FREQUENCY + " INTEGER," + + COLUMN_LOCALE + " TEXT" + + ");"); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + Log.w("AutoDictionary", "Upgrading database from version " + oldVersion + " to " + + newVersion + ", which will destroy all old data"); + db.execSQL("DROP TABLE IF EXISTS " + AUTODICT_TABLE_NAME); + onCreate(db); + } + } + + private Cursor query(String selection, String[] selectionArgs) { + SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); + qb.setTables(AUTODICT_TABLE_NAME); + qb.setProjectionMap(sDictProjectionMap); + + // Get the database and run the query + SQLiteDatabase db = sOpenHelper.getReadableDatabase(); + Cursor c = qb.query(db, null, selection, selectionArgs, null, null, + DEFAULT_SORT_ORDER); + return c; + } + + /** + * Async task to write pending words to the database so that it stays in sync with + * the in-memory trie. + */ + private static class UpdateDbTask extends AsyncTask { + private final HashMap mMap; + private final DatabaseHelper mDbHelper; + private final String mLocale; + + public UpdateDbTask(Context context, DatabaseHelper openHelper, + HashMap pendingWrites, String locale) { + mMap = pendingWrites; + mLocale = locale; + mDbHelper = openHelper; + } + + @Override + protected Void doInBackground(Void... v) { + SQLiteDatabase db = mDbHelper.getWritableDatabase(); + // Write all the entries to the db + Set> mEntries = mMap.entrySet(); + for (Entry entry : mEntries) { + Integer freq = entry.getValue(); + db.delete(AUTODICT_TABLE_NAME, COLUMN_WORD + "=? AND " + COLUMN_LOCALE + "=?", + new String[] { entry.getKey(), mLocale }); + if (freq != null) { + db.insert(AUTODICT_TABLE_NAME, null, + getContentValues(entry.getKey(), freq, mLocale)); + } + } + return null; + } + + private ContentValues getContentValues(String word, int frequency, String locale) { + ContentValues values = new ContentValues(4); + values.put(COLUMN_WORD, word); + values.put(COLUMN_FREQUENCY, frequency); + values.put(COLUMN_LOCALE, locale); + return values; + } + } +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/BinaryDictionary.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/BinaryDictionary.java new file mode 100644 index 00000000..c4598c5b --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/BinaryDictionary.java @@ -0,0 +1,300 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package keepass2android.softkeyboard; + +import java.io.InputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.channels.Channels; +import java.util.Arrays; + +import android.content.Context; +import android.util.Log; + +/** + * Implements a static, compacted, binary dictionary of standard words. + */ +public class BinaryDictionary extends Dictionary { + + /** + * There is difference between what java and native code can handle. + * This value should only be used in BinaryDictionary.java + * It is necessary to keep it at this value because some languages e.g. German have + * really long words. + */ + protected static final int MAX_WORD_LENGTH = 48; + + private static final String TAG = "BinaryDictionary"; + private static final int MAX_ALTERNATIVES = 16; + private static final int MAX_WORDS = 18; + private static final int MAX_BIGRAMS = 60; + + private static final int TYPED_LETTER_MULTIPLIER = 2; + private static final boolean ENABLE_MISSED_CHARACTERS = true; + + private int mDicTypeId; + private int mNativeDict; + private int mDictLength; + private int[] mInputCodes = new int[MAX_WORD_LENGTH * MAX_ALTERNATIVES]; + private char[] mOutputChars = new char[MAX_WORD_LENGTH * MAX_WORDS]; + private char[] mOutputChars_bigrams = new char[MAX_WORD_LENGTH * MAX_BIGRAMS]; + private int[] mFrequencies = new int[MAX_WORDS]; + private int[] mFrequencies_bigrams = new int[MAX_BIGRAMS]; + // Keep a reference to the native dict direct buffer in Java to avoid + // unexpected deallocation of the direct buffer. + private ByteBuffer mNativeDictDirectBuffer; + + static { + try { + System.loadLibrary("jni_latinime"); + } catch (UnsatisfiedLinkError ule) { + Log.e("BinaryDictionary", "Could not load native library jni_latinime"); + } + } + + /** + * Create a dictionary from a raw resource file + * @param context application context for reading resources + * @param resId the resource containing the raw binary dictionary + */ + public BinaryDictionary(Context context, int[] resId, int dicTypeId) { + if (resId != null && resId.length > 0 && resId[0] != 0) { + loadDictionary(context, resId); + } + mDicTypeId = dicTypeId; + } + + /** + * Create a dictionary from input streams + * @param context application context for reading resources + * @param streams the resource streams containing the raw binary dictionary + */ + public BinaryDictionary(Context context, InputStream[] streams, int dicTypeId) { + if (streams != null && streams.length > 0) { + loadDictionary(context, streams); + } + mDicTypeId = dicTypeId; + } + + + /** + * Create a dictionary from a byte buffer. This is used for testing. + * @param context application context for reading resources + * @param byteBuffer a ByteBuffer containing the binary dictionary + */ + public BinaryDictionary(Context context, ByteBuffer byteBuffer, int dicTypeId) { + if (byteBuffer != null) { + if (byteBuffer.isDirect()) { + mNativeDictDirectBuffer = byteBuffer; + } else { + mNativeDictDirectBuffer = ByteBuffer.allocateDirect(byteBuffer.capacity()); + byteBuffer.rewind(); + mNativeDictDirectBuffer.put(byteBuffer); + } + mDictLength = byteBuffer.capacity(); + mNativeDict = openNative(mNativeDictDirectBuffer, + TYPED_LETTER_MULTIPLIER, FULL_WORD_FREQ_MULTIPLIER); + } + mDicTypeId = dicTypeId; + } + + private native int openNative(ByteBuffer bb, int typedLetterMultiplier, + int fullWordMultiplier); + private native void closeNative(int dict); + 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, int skipPos, int[] nextLettersFrequencies, int nextLettersSize); + private native int getBigramsNative(int dict, char[] prevWord, int prevWordLength, + int[] inputCodes, int inputCodesLength, char[] outputChars, int[] frequencies, + int maxWordLength, int maxBigrams, int maxAlternatives); + + private final void loadDictionary(Context context, int[] resId) { + InputStream[] is = null; + try { + // merging separated dictionary into one if dictionary is separated + is = new InputStream[resId.length]; + for (int i = 0; i < resId.length; i++) { + is[i] = context.getResources().openRawResource(resId[i]); + } + loadDictionary(context, is); + + + } finally { + try { + if (is != null) { + for (int i = 0; i < is.length; i++) { + is[i].close(); + } + } + } catch (IOException e) { + Log.w(TAG, "Failed to close input stream"); + } + } + } + + + private void loadDictionary(Context context, InputStream[] is) + { + try + { + int total = 0; + for (int i = 0; i < is.length; i++) + total += is[i].available(); + + mNativeDictDirectBuffer = + ByteBuffer.allocateDirect(total).order(ByteOrder.nativeOrder()); + int got = 0; + for (int i = 0; i < is.length; i++) { + got += Channels.newChannel(is[i]).read(mNativeDictDirectBuffer); + } + if (got != total) { + Log.e(TAG, "Read " + got + " bytes, expected " + total); + } else { + mNativeDict = openNative(mNativeDictDirectBuffer, + TYPED_LETTER_MULTIPLIER, FULL_WORD_FREQ_MULTIPLIER); + mDictLength = total; + } + + } + catch (IOException e) { + Log.w(TAG, "No available memory for binary dictionary"); + } catch (UnsatisfiedLinkError e) { + Log.w(TAG, "Failed to load native dictionary", e); + } finally { + try { + if (is != null) { + for (int i = 0; i < is.length; i++) { + is[i].close(); + } + } + } catch (IOException e) { + Log.w(TAG, "Failed to close input stream"); + } + } + + } + + @Override + public void getBigrams(final WordComposer codes, final CharSequence previousWord, + final WordCallback callback, int[] nextLettersFrequencies) { + + char[] chars = previousWord.toString().toCharArray(); + Arrays.fill(mOutputChars_bigrams, (char) 0); + Arrays.fill(mFrequencies_bigrams, 0); + + int codesSize = codes.size(); + Arrays.fill(mInputCodes, -1); + int[] alternatives = codes.getCodesAt(0); + System.arraycopy(alternatives, 0, mInputCodes, 0, + Math.min(alternatives.length, MAX_ALTERNATIVES)); + + int count = getBigramsNative(mNativeDict, chars, chars.length, mInputCodes, codesSize, + mOutputChars_bigrams, mFrequencies_bigrams, MAX_WORD_LENGTH, MAX_BIGRAMS, + MAX_ALTERNATIVES); + + for (int j = 0; j < count; j++) { + if (mFrequencies_bigrams[j] < 1) break; + int start = j * MAX_WORD_LENGTH; + int len = 0; + while (mOutputChars_bigrams[start + len] != 0) { + len++; + } + if (len > 0) { + callback.addWord(mOutputChars_bigrams, start, len, mFrequencies_bigrams[j], + mDicTypeId, DataType.BIGRAM); + } + } + } + + @Override + public void getWords(final WordComposer codes, final WordCallback callback, + int[] nextLettersFrequencies) { + final int codesSize = codes.size(); + // Won't deal with really long words. + if (codesSize > MAX_WORD_LENGTH - 1) return; + + Arrays.fill(mInputCodes, -1); + for (int i = 0; i < codesSize; i++) { + int[] alternatives = codes.getCodesAt(i); + System.arraycopy(alternatives, 0, mInputCodes, i * MAX_ALTERNATIVES, + 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, -1, + nextLettersFrequencies, + nextLettersFrequencies != null ? nextLettersFrequencies.length : 0); + + // 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, + null, 0); + count = Math.max(count, tempCount); + if (tempCount > 0) break; + } + } + + for (int j = 0; j < count; j++) { + if (mFrequencies[j] < 1) break; + int start = j * MAX_WORD_LENGTH; + int len = 0; + while (mOutputChars[start + len] != 0) { + len++; + } + if (len > 0) { + callback.addWord(mOutputChars, start, len, mFrequencies[j], mDicTypeId, + DataType.UNIGRAM); + } + } + } + + @Override + public boolean isValidWord(CharSequence word) { + if (word == null) return false; + char[] chars = word.toString().toCharArray(); + return isValidWordNative(mNativeDict, chars, chars.length); + } + + public int getSize() { + return mDictLength; // This value is initialized on the call to openNative() + } + + @Override + public synchronized void close() { + if (mNativeDict != 0) { + closeNative(mNativeDict); + mNativeDict = 0; + } + } + + @Override + protected void finalize() throws Throwable { + close(); + super.finalize(); + } +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/CandidateView.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/CandidateView.java new file mode 100644 index 00000000..9b83ea3b --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/CandidateView.java @@ -0,0 +1,491 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * Copyright (C) 2014 Philipp Crocoll + * Copyright (C) 2014 Wiktor Lawski + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 keepass2android.softkeyboard; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Paint.Align; +import android.graphics.Rect; +import android.graphics.Typeface; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.GestureDetector; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup.LayoutParams; +import android.widget.PopupWindow; +import android.widget.TextView; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class CandidateView extends View { + + private static final int OUT_OF_BOUNDS_WORD_INDEX = -1; + private static final int OUT_OF_BOUNDS_X_COORD = -1; + + private KP2AKeyboard mService; + private final ArrayList mSuggestions = new ArrayList(); + private boolean mShowingCompletions; + private CharSequence mSelectedString; + private int mSelectedIndex; + private int mTouchX = OUT_OF_BOUNDS_X_COORD; + private final Drawable mSelectionHighlight; + private boolean mTypedWordValid; + + private boolean mHaveMinimalSuggestion; + + private Rect mBgPadding; + + private final TextView mPreviewText; + private final PopupWindow mPreviewPopup; + private int mCurrentWordIndex; + private Drawable mDivider; + + private static final int MAX_SUGGESTIONS = 32; + private static final int SCROLL_PIXELS = 20; + + private final int[] mWordWidth = new int[MAX_SUGGESTIONS]; + private final int[] mWordX = new int[MAX_SUGGESTIONS]; + private int mPopupPreviewX; + private int mPopupPreviewY; + + private static final int X_GAP = 10; + + private final int mColorNormal; + private final int mColorRecommended; + private final int mColorOther; + private final Paint mPaint; + private final int mDescent; + private boolean mScrolled; + private boolean mShowingAddToDictionary; + private CharSequence mAddToDictionaryHint; + + private int mTargetScrollX; + + private final int mMinTouchableWidth; + + private int mTotalWidth; + + private final GestureDetector mGestureDetector; + + /** + * Construct a CandidateView for showing suggested words for completion. + * @param context + * @param attrs + */ + public CandidateView(Context context, AttributeSet attrs) { + super(context, attrs); + mSelectionHighlight = context.getResources().getDrawable( + R.drawable.list_selector_background_pressed); + + LayoutInflater inflate = + (LayoutInflater) context + .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + Resources res = context.getResources(); + mPreviewPopup = new PopupWindow(context); + mPreviewText = (TextView) inflate.inflate(R.layout.candidate_preview, null); + mPreviewPopup.setWindowLayoutMode(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + mPreviewPopup.setContentView(mPreviewText); + mPreviewPopup.setBackgroundDrawable(null); + mPreviewPopup.setAnimationStyle(R.style.KeyPreviewAnimation); + mColorNormal = res.getColor(R.color.candidate_normal); + mColorRecommended = res.getColor(R.color.candidate_recommended); + mColorOther = res.getColor(R.color.candidate_other); + mDivider = res.getDrawable(R.drawable.keyboard_suggest_strip_divider); + mAddToDictionaryHint = res.getString(R.string.hint_add_to_dictionary); + + mPaint = new Paint(); + mPaint.setColor(mColorNormal); + mPaint.setAntiAlias(true); + mPaint.setTextSize(mPreviewText.getTextSize()); + mPaint.setStrokeWidth(0); + mPaint.setTextAlign(Align.CENTER); + mDescent = (int) mPaint.descent(); + mMinTouchableWidth = (int)res.getDimension(R.dimen.candidate_min_touchable_width); + + mGestureDetector = new GestureDetector( + new CandidateStripGestureListener(mMinTouchableWidth)); + setWillNotDraw(false); + setHorizontalScrollBarEnabled(false); + setVerticalScrollBarEnabled(false); + scrollTo(0, getScrollY()); + } + + private class CandidateStripGestureListener extends GestureDetector.SimpleOnGestureListener { + private final int mTouchSlopSquare; + + public CandidateStripGestureListener(int touchSlop) { + // Slightly reluctant to scroll to be able to easily choose the suggestion + mTouchSlopSquare = touchSlop * touchSlop; + } + + @Override + public void onLongPress(MotionEvent me) { + if (mSuggestions.size() > 0) { + if (me.getX() + getScrollX() < mWordWidth[0] && getScrollX() < 10) { + longPressFirstWord(); + } + } + } + + @Override + public boolean onDown(MotionEvent e) { + mScrolled = false; + return false; + } + + @Override + public boolean onScroll(MotionEvent e1, MotionEvent e2, + float distanceX, float distanceY) { + if (!mScrolled) { + // This is applied only when we recognize that scrolling is starting. + final int deltaX = (int) (e2.getX() - e1.getX()); + final int deltaY = (int) (e2.getY() - e1.getY()); + final int distance = (deltaX * deltaX) + (deltaY * deltaY); + if (distance < mTouchSlopSquare) { + return true; + } + mScrolled = true; + } + + final int width = getWidth(); + mScrolled = true; + int scrollX = getScrollX(); + scrollX += (int) distanceX; + if (scrollX < 0) { + scrollX = 0; + } + if (distanceX > 0 && scrollX + width > mTotalWidth) { + scrollX -= (int) distanceX; + } + mTargetScrollX = scrollX; + scrollTo(scrollX, getScrollY()); + hidePreview(); + invalidate(); + return true; + } + } + + /** + * A connection back to the service to communicate with the text field + * @param listener + */ + public void setService(KP2AKeyboard listener) { + mService = listener; + } + + @Override + public int computeHorizontalScrollRange() { + return mTotalWidth; + } + + /** + * If the canvas is null, then only touch calculations are performed to pick the target + * candidate. + */ + @Override + protected void onDraw(Canvas canvas) { + if (canvas != null) { + super.onDraw(canvas); + } + mTotalWidth = 0; + + final int height = getHeight(); + if (mBgPadding == null) { + mBgPadding = new Rect(0, 0, 0, 0); + if (getBackground() != null) { + getBackground().getPadding(mBgPadding); + } + mDivider.setBounds(0, 0, mDivider.getIntrinsicWidth(), + mDivider.getIntrinsicHeight()); + } + + final int count = mSuggestions.size(); + final Rect bgPadding = mBgPadding; + final Paint paint = mPaint; + final int touchX = mTouchX; + final int scrollX = getScrollX(); + final boolean scrolled = mScrolled; + final boolean typedWordValid = mTypedWordValid; + final int y = (int) (height + mPaint.getTextSize() - mDescent) / 2; + + boolean existsAutoCompletion = false; + + int x = 0; + for (int i = 0; i < count; i++) { + CharSequence suggestion = mSuggestions.get(i); + if (suggestion == null) continue; + final int wordLength = suggestion.length(); + + paint.setColor(mColorNormal); + if (mHaveMinimalSuggestion + && ((i == 1 && !typedWordValid) || (i == 0 && typedWordValid))) { + paint.setTypeface(Typeface.DEFAULT_BOLD); + paint.setColor(mColorRecommended); + existsAutoCompletion = true; + } else if (i != 0 || (wordLength == 1 && count > 1)) { + // HACK: even if i == 0, we use mColorOther when this suggestion's length is 1 and + // there are multiple suggestions, such as the default punctuation list. + paint.setColor(mColorOther); + } + int wordWidth; + if ((wordWidth = mWordWidth[i]) == 0) { + float textWidth = paint.measureText(suggestion, 0, wordLength); + wordWidth = Math.max(mMinTouchableWidth, (int) textWidth + X_GAP * 2); + mWordWidth[i] = wordWidth; + } + + mWordX[i] = x; + + if (touchX != OUT_OF_BOUNDS_X_COORD && !scrolled + && touchX + scrollX >= x && touchX + scrollX < x + wordWidth) { + if (canvas != null && !mShowingAddToDictionary) { + canvas.translate(x, 0); + mSelectionHighlight.setBounds(0, bgPadding.top, wordWidth, height); + mSelectionHighlight.draw(canvas); + canvas.translate(-x, 0); + } + mSelectedString = suggestion; + mSelectedIndex = i; + } + + if (canvas != null) { + canvas.drawText(suggestion, 0, wordLength, x + wordWidth / 2, y, paint); + paint.setColor(mColorOther); + canvas.translate(x + wordWidth, 0); + // Draw a divider unless it's after the hint + if (!(mShowingAddToDictionary && i == 1)) { + mDivider.draw(canvas); + } + canvas.translate(-x - wordWidth, 0); + } + paint.setTypeface(Typeface.DEFAULT); + x += wordWidth; + } + mService.onAutoCompletionStateChanged(existsAutoCompletion); + mTotalWidth = x; + if (mTargetScrollX != scrollX) { + scrollToTarget(); + } + } + + private void scrollToTarget() { + int scrollX = getScrollX(); + if (mTargetScrollX > scrollX) { + scrollX += SCROLL_PIXELS; + if (scrollX >= mTargetScrollX) { + scrollX = mTargetScrollX; + scrollTo(scrollX, getScrollY()); + requestLayout(); + } else { + scrollTo(scrollX, getScrollY()); + } + } else { + scrollX -= SCROLL_PIXELS; + if (scrollX <= mTargetScrollX) { + scrollX = mTargetScrollX; + scrollTo(scrollX, getScrollY()); + requestLayout(); + } else { + scrollTo(scrollX, getScrollY()); + } + } + invalidate(); + } + + @SuppressLint("WrongCall") + public void setSuggestions(List suggestions, boolean completions, + boolean typedWordValid, boolean haveMinimalSuggestion) { + clear(); + if (suggestions != null) { + int insertCount = Math.min(suggestions.size(), MAX_SUGGESTIONS); + for (CharSequence suggestion : suggestions) { + mSuggestions.add(suggestion); + if (--insertCount == 0) + break; + } + } + mShowingCompletions = completions; + mTypedWordValid = typedWordValid; + scrollTo(0, getScrollY()); + mTargetScrollX = 0; + mHaveMinimalSuggestion = haveMinimalSuggestion; + // Compute the total width + onDraw(null); + invalidate(); + requestLayout(); + } + + public boolean isShowingAddToDictionaryHint() { + return mShowingAddToDictionary; + } + + public void showAddToDictionaryHint(CharSequence word) { + ArrayList suggestions = new ArrayList(); + suggestions.add(word); + suggestions.add(mAddToDictionaryHint); + setSuggestions(suggestions, false, false, false); + mShowingAddToDictionary = true; + } + + public boolean dismissAddToDictionaryHint() { + if (!mShowingAddToDictionary) return false; + clear(); + return true; + } + + /* package */ List getSuggestions() { + return mSuggestions; + } + + public void clear() { + // Don't call mSuggestions.clear() because it's being used for logging + // in LatinIME.pickSuggestionManually(). + mSuggestions.clear(); + mTouchX = OUT_OF_BOUNDS_X_COORD; + mSelectedString = null; + mSelectedIndex = -1; + mShowingAddToDictionary = false; + invalidate(); + Arrays.fill(mWordWidth, 0); + Arrays.fill(mWordX, 0); + } + + @Override + public boolean onTouchEvent(MotionEvent me) { + + if (mGestureDetector.onTouchEvent(me)) { + return true; + } + + int action = me.getAction(); + int x = (int) me.getX(); + int y = (int) me.getY(); + mTouchX = x; + + switch (action) { + case MotionEvent.ACTION_DOWN: + invalidate(); + break; + case MotionEvent.ACTION_MOVE: + if (y <= 0) { + // Fling up!? + if (mSelectedString != null) { + // If there are completions from the application, we don't change the state to + // STATE_PICKED_SUGGESTION + if (!mShowingCompletions) { + // This "acceptedSuggestion" will not be counted as a word because + // it will be counted in pickSuggestion instead. + TextEntryState.acceptedSuggestion(mSuggestions.get(0), + mSelectedString); + } + mService.pickSuggestionManually(mSelectedIndex, mSelectedString); + mSelectedString = null; + mSelectedIndex = -1; + } + } + break; + case MotionEvent.ACTION_UP: + if (!mScrolled) { + if (mSelectedString != null) { + if (mShowingAddToDictionary) { + longPressFirstWord(); + clear(); + } else { + if (!mShowingCompletions) { + TextEntryState.acceptedSuggestion(mSuggestions.get(0), + mSelectedString); + } + mService.pickSuggestionManually(mSelectedIndex, mSelectedString); + } + } + } + mSelectedString = null; + mSelectedIndex = -1; + requestLayout(); + hidePreview(); + invalidate(); + break; + } + return true; + } + + private void hidePreview() { + mTouchX = OUT_OF_BOUNDS_X_COORD; + mCurrentWordIndex = OUT_OF_BOUNDS_WORD_INDEX; + mPreviewPopup.dismiss(); + } + + private void showPreview(int wordIndex, String altText) { + int oldWordIndex = mCurrentWordIndex; + mCurrentWordIndex = wordIndex; + // If index changed or changing text + if (oldWordIndex != mCurrentWordIndex || altText != null) { + if (wordIndex == OUT_OF_BOUNDS_WORD_INDEX) { + hidePreview(); + } else { + CharSequence word = altText != null? altText : mSuggestions.get(wordIndex); + mPreviewText.setText(word); + mPreviewText.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), + MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); + int wordWidth = (int) (mPaint.measureText(word, 0, word.length()) + X_GAP * 2); + final int popupWidth = wordWidth + + mPreviewText.getPaddingLeft() + mPreviewText.getPaddingRight(); + final int popupHeight = mPreviewText.getMeasuredHeight(); + //mPreviewText.setVisibility(INVISIBLE); + mPopupPreviewX = mWordX[wordIndex] - mPreviewText.getPaddingLeft() - getScrollX() + + (mWordWidth[wordIndex] - wordWidth) / 2; + mPopupPreviewY = - popupHeight; + int [] offsetInWindow = new int[2]; + getLocationInWindow(offsetInWindow); + if (mPreviewPopup.isShowing()) { + mPreviewPopup.update(mPopupPreviewX, mPopupPreviewY + offsetInWindow[1], + popupWidth, popupHeight); + } else { + mPreviewPopup.setWidth(popupWidth); + mPreviewPopup.setHeight(popupHeight); + mPreviewPopup.showAtLocation(this, Gravity.NO_GRAVITY, mPopupPreviewX, + mPopupPreviewY + offsetInWindow[1]); + } + mPreviewText.setVisibility(VISIBLE); + } + } + } + + private void longPressFirstWord() { + CharSequence word = mSuggestions.get(0); + if (word.length() < 2) return; + if (mService.addWordToDictionary(word.toString())) { + showPreview(0, getContext().getResources().getString(R.string.added_word, word)); + } + } + + @Override + public void onDetachedFromWindow() { + super.onDetachedFromWindow(); + hidePreview(); + } +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/ContactsDictionary.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/ContactsDictionary.java new file mode 100644 index 00000000..247f8bad --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/ContactsDictionary.java @@ -0,0 +1,152 @@ +/* + * 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 keepass2android.softkeyboard; + +import android.content.ContentResolver; +import android.content.Context; +import android.database.ContentObserver; +import android.database.Cursor; +import android.os.SystemClock; +import android.provider.ContactsContract.Contacts; +import android.text.TextUtils; +import android.util.Log; + +public class ContactsDictionary extends ExpandableDictionary { + + private static final String[] PROJECTION = { + Contacts._ID, + Contacts.DISPLAY_NAME, + }; + + private static final String TAG = "ContactsDictionary"; + + /** + * Frequency for contacts information into the dictionary + */ + private static final int FREQUENCY_FOR_CONTACTS = 128; + private static final int FREQUENCY_FOR_CONTACTS_BIGRAM = 90; + + private static final int INDEX_NAME = 1; + + private ContentObserver mObserver; + + private long mLastLoadedContacts; + + public ContactsDictionary(Context context, int dicTypeId) { + super(context, dicTypeId); + // 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) { + setRequiresReload(true); + } + }); + loadDictionary(); + } + + @Override + public synchronized void close() { + if (mObserver != null) { + getContext().getContentResolver().unregisterContentObserver(mObserver); + mObserver = null; + } + super.close(); + } + + @Override + public void startDictionaryLoadingTaskLocked() { + long now = SystemClock.uptimeMillis(); + if (mLastLoadedContacts == 0 + || now - mLastLoadedContacts > 30 * 60 * 1000 /* 30 minutes */) { + super.startDictionaryLoadingTaskLocked(); + } + } + + @Override + public void loadDictionaryAsync() { + /*try { + Cursor cursor = getContext().getContentResolver() + .query(Contacts.CONTENT_URI, PROJECTION, null, null, null); + if (cursor != null) { + addWords(cursor); + } + } catch(IllegalStateException e) { + Log.e(TAG, "Contacts DB is having problems"); + } + mLastLoadedContacts = SystemClock.uptimeMillis();*/ + } + + private void addWords(Cursor cursor) { + clearDictionary(); + + final int maxWordLength = getMaxWordLength(); + try { + if (cursor.moveToFirst()) { + while (!cursor.isAfterLast()) { + String name = cursor.getString(INDEX_NAME); + + if (name != null) { + int len = name.length(); + String prevWord = null; + + // 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 + // Also don't add single letter words, possibly confuses + // capitalization of i. + final int wordLen = word.length(); + if (wordLen < maxWordLength && wordLen > 1) { + super.addWord(word, FREQUENCY_FOR_CONTACTS); + if (!TextUtils.isEmpty(prevWord)) { + // TODO Do not add email address + // Not so critical + super.setBigram(prevWord, word, + FREQUENCY_FOR_CONTACTS_BIGRAM); + } + prevWord = word; + } + } + } + } + cursor.moveToNext(); + } + } + cursor.close(); + } catch(IllegalStateException e) { + Log.e(TAG, "Contacts DB is having problems"); + } + } +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/Design.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/Design.java new file mode 100644 index 00000000..c8e22ba9 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/Design.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2014 Wiktor Lawski + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 keepass2android.softkeyboard; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.SharedPreferences; + +public class Design { + @SuppressLint("InlinedApi") + public static void updateTheme(Activity activity, SharedPreferences prefs) { + + if (android.os.Build.VERSION.SDK_INT >= 11 + /* android.os.Build.VERSION_CODES.HONEYCOMB */) { + String design = prefs.getString("design_key", "Light"); + + if (design.equals("Light")) { + activity.setTheme(android.R.style.Theme_Holo_Light); + } else { + activity.setTheme(android.R.style.Theme_Holo); + } + } + } +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/Dictionary.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/Dictionary.java new file mode 100644 index 00000000..2b93599b --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/Dictionary.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package keepass2android.softkeyboard; + +/** + * Abstract base class for a dictionary that can do a fuzzy search for words based on a set of key + * strokes. + */ +abstract public class Dictionary { + /** + * Whether or not to replicate the typed word in the suggested list, even if it's valid. + */ + protected static final boolean INCLUDE_TYPED_WORD_IF_VALID = false; + + /** + * The weight to give to a word if it's length is the same as the number of typed characters. + */ + protected static final int FULL_WORD_FREQ_MULTIPLIER = 2; + + public static enum DataType { + UNIGRAM, BIGRAM + } + + /** + * Interface to be implemented by classes requesting words to be fetched from the dictionary. + * @see #getWords(WordComposer, WordCallback) + */ + public interface WordCallback { + /** + * Adds a word to a list of suggestions. The word is expected to be ordered based on + * the provided frequency. + * @param word the character array containing the word + * @param wordOffset starting offset of the word in the character array + * @param wordLength length of valid characters in the character array + * @param frequency the frequency of occurence. This is normalized between 1 and 255, but + * can exceed those limits + * @param dicTypeId of the dictionary where word was from + * @param dataType tells type of this data + * @return true if the word was added, false if no more words are required + */ + boolean addWord(char[] word, int wordOffset, int wordLength, int frequency, int dicTypeId, + DataType dataType); + } + + /** + * Searches for words in the dictionary that match the characters in the composer. Matched + * words are added through the callback object. + * @param composer the key sequence to match + * @param callback the callback object to send matched words to as possible candidates + * @param nextLettersFrequencies array of frequencies of next letters that could follow the + * word so far. For instance, "bracke" can be followed by "t", so array['t'] will have + * a non-zero value on returning from this method. + * Pass in null if you don't want the dictionary to look up next letters. + * @see WordCallback#addWord(char[], int, int) + */ + abstract public void getWords(final WordComposer composer, final WordCallback callback, + int[] nextLettersFrequencies); + + /** + * Searches for pairs in the bigram dictionary that matches the previous word and all the + * possible words following are added through the callback object. + * @param composer the key sequence to match + * @param callback the callback object to send possible word following previous word + * @param nextLettersFrequencies array of frequencies of next letters that could follow the + * word so far. For instance, "bracke" can be followed by "t", so array['t'] will have + * a non-zero value on returning from this method. + * Pass in null if you don't want the dictionary to look up next letters. + */ + public void getBigrams(final WordComposer composer, final CharSequence previousWord, + final WordCallback callback, int[] nextLettersFrequencies) { + // empty base implementation + } + + /** + * Checks if the given word occurs in the dictionary + * @param word the word to search for. The search should be case-insensitive. + * @return true if the word exists, false otherwise + */ + abstract public boolean isValidWord(CharSequence word); + + /** + * Compares the contents of the character array with the typed word and returns true if they + * are the same. + * @param word the array of characters that make up the word + * @param length the number of valid characters in the character array + * @param typedWord the word to compare with + * @return true if they are the same, false otherwise. + */ + protected boolean same(final char[] word, final int length, final CharSequence typedWord) { + if (typedWord.length() != length) { + return false; + } + for (int i = 0; i < length; i++) { + if (word[i] != typedWord.charAt(i)) { + return false; + } + } + return true; + } + + /** + * Override to clean up any resources. + */ + public void close() { + } +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/EditingUtil.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/EditingUtil.java new file mode 100644 index 00000000..3f3df704 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/EditingUtil.java @@ -0,0 +1,337 @@ +/* + * Copyright (C) 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 keepass2android.softkeyboard; + +import android.text.TextUtils; +import android.view.inputmethod.ExtractedText; +import android.view.inputmethod.ExtractedTextRequest; +import android.view.inputmethod.InputConnection; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.regex.Pattern; + +/** + * Utility methods to deal with editing text through an InputConnection. + */ +public class EditingUtil { + /** + * Number of characters we want to look back in order to identify the previous word + */ + private static final int LOOKBACK_CHARACTER_NUM = 15; + + // Cache Method pointers + private static boolean sMethodsInitialized; + private static Method sMethodGetSelectedText; + private static Method sMethodSetComposingRegion; + + private EditingUtil() {}; + + /** + * Append newText to the text field represented by connection. + * The new text becomes selected. + */ + public static void appendText(InputConnection connection, String newText) { + if (connection == null) { + return; + } + + // Commit the composing text + connection.finishComposingText(); + + // Add a space if the field already has text. + CharSequence charBeforeCursor = connection.getTextBeforeCursor(1, 0); + if (charBeforeCursor != null + && !charBeforeCursor.equals(" ") + && (charBeforeCursor.length() > 0)) { + newText = " " + newText; + } + + connection.setComposingText(newText, 1); + } + + private static int getCursorPosition(InputConnection connection) { + ExtractedText extracted = connection.getExtractedText( + new ExtractedTextRequest(), 0); + if (extracted == null) { + return -1; + } + return extracted.startOffset + extracted.selectionStart; + } + + /** + * @param connection connection to the current text field. + * @param sep characters which may separate words + * @param range the range object to store the result into + * @return the word that surrounds the cursor, including up to one trailing + * separator. For example, if the field contains "he|llo world", where | + * represents the cursor, then "hello " will be returned. + */ + public static String getWordAtCursor( + InputConnection connection, String separators, Range range) { + Range r = getWordRangeAtCursor(connection, separators, range); + return (r == null) ? null : r.word; + } + + /** + * Removes the word surrounding the cursor. Parameters are identical to + * getWordAtCursor. + */ + public static void deleteWordAtCursor( + InputConnection connection, String separators) { + + Range range = getWordRangeAtCursor(connection, separators, null); + if (range == null) return; + + connection.finishComposingText(); + // Move cursor to beginning of word, to avoid crash when cursor is outside + // of valid range after deleting text. + int newCursor = getCursorPosition(connection) - range.charsBefore; + connection.setSelection(newCursor, newCursor); + connection.deleteSurroundingText(0, range.charsBefore + range.charsAfter); + } + + /** + * Represents a range of text, relative to the current cursor position. + */ + public static class Range { + /** Characters before selection start */ + public int charsBefore; + + /** + * Characters after selection start, including one trailing word + * separator. + */ + public int charsAfter; + + /** The actual characters that make up a word */ + public String word; + + public Range() {} + + public Range(int charsBefore, int charsAfter, String word) { + if (charsBefore < 0 || charsAfter < 0) { + throw new IndexOutOfBoundsException(); + } + this.charsBefore = charsBefore; + this.charsAfter = charsAfter; + this.word = word; + } + } + + private static Range getWordRangeAtCursor( + InputConnection connection, String sep, Range range) { + if (connection == null || sep == null) { + return null; + } + CharSequence before = connection.getTextBeforeCursor(1000, 0); + CharSequence after = connection.getTextAfterCursor(1000, 0); + if (before == null || after == null) { + return null; + } + + // Find first word separator before the cursor + int start = before.length(); + while (start > 0 && !isWhitespace(before.charAt(start - 1), sep)) start--; + + // Find last word separator after the cursor + int end = -1; + while (++end < after.length() && !isWhitespace(after.charAt(end), sep)); + + int cursor = getCursorPosition(connection); + if (start >= 0 && cursor + end <= after.length() + before.length()) { + String word = before.toString().substring(start, before.length()) + + after.toString().substring(0, end); + + Range returnRange = range != null? range : new Range(); + returnRange.charsBefore = before.length() - start; + returnRange.charsAfter = end; + returnRange.word = word; + return returnRange; + } + + return null; + } + + private static boolean isWhitespace(int code, String whitespace) { + return whitespace.contains(String.valueOf((char) code)); + } + + private static final Pattern spaceRegex = Pattern.compile("\\s+"); + + public static CharSequence getPreviousWord(InputConnection connection, + String sentenceSeperators) { + //TODO: Should fix this. This could be slow! + CharSequence prev = connection.getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0); + if (prev == null) { + return null; + } + String[] w = spaceRegex.split(prev); + if (w.length >= 2 && w[w.length-2].length() > 0) { + char lastChar = w[w.length-2].charAt(w[w.length-2].length() -1); + if (sentenceSeperators.contains(String.valueOf(lastChar))) { + return null; + } + return w[w.length-2]; + } else { + return null; + } + } + + public static class SelectedWord { + public int start; + public int end; + public CharSequence word; + } + + /** + * Takes a character sequence with a single character and checks if the character occurs + * in a list of word separators or is empty. + * @param singleChar A CharSequence with null, zero or one character + * @param wordSeparators A String containing the word separators + * @return true if the character is at a word boundary, false otherwise + */ + private static boolean isWordBoundary(CharSequence singleChar, String wordSeparators) { + return TextUtils.isEmpty(singleChar) || wordSeparators.contains(singleChar); + } + + /** + * Checks if the cursor is inside a word or the current selection is a whole word. + * @param ic the InputConnection for accessing the text field + * @param selStart the start position of the selection within the text field + * @param selEnd the end position of the selection within the text field. This could be + * the same as selStart, if there's no selection. + * @param wordSeparators the word separator characters for the current language + * @return an object containing the text and coordinates of the selected/touching word, + * null if the selection/cursor is not marking a whole word. + */ + public static SelectedWord getWordAtCursorOrSelection(final InputConnection ic, + int selStart, int selEnd, String wordSeparators) { + if (selStart == selEnd) { + // There is just a cursor, so get the word at the cursor + EditingUtil.Range range = new EditingUtil.Range(); + CharSequence touching = getWordAtCursor(ic, wordSeparators, range); + if (!TextUtils.isEmpty(touching)) { + SelectedWord selWord = new SelectedWord(); + selWord.word = touching; + selWord.start = selStart - range.charsBefore; + selWord.end = selEnd + range.charsAfter; + return selWord; + } + } else { + // Is the previous character empty or a word separator? If not, return null. + CharSequence charsBefore = ic.getTextBeforeCursor(1, 0); + if (!isWordBoundary(charsBefore, wordSeparators)) { + return null; + } + + // Is the next character empty or a word separator? If not, return null. + CharSequence charsAfter = ic.getTextAfterCursor(1, 0); + if (!isWordBoundary(charsAfter, wordSeparators)) { + return null; + } + + // Extract the selection alone + CharSequence touching = getSelectedText(ic, selStart, selEnd); + if (TextUtils.isEmpty(touching)) return null; + // Is any part of the selection a separator? If so, return null. + final int length = touching.length(); + for (int i = 0; i < length; i++) { + if (wordSeparators.contains(touching.subSequence(i, i + 1))) { + return null; + } + } + // Prepare the selected word + SelectedWord selWord = new SelectedWord(); + selWord.start = selStart; + selWord.end = selEnd; + selWord.word = touching; + return selWord; + } + return null; + } + + /** + * Cache method pointers for performance + */ + private static void initializeMethodsForReflection() { + try { + // These will either both exist or not, so no need for separate try/catch blocks. + // If other methods are added later, use separate try/catch blocks. + sMethodGetSelectedText = InputConnection.class.getMethod("getSelectedText", int.class); + sMethodSetComposingRegion = InputConnection.class.getMethod("setComposingRegion", + int.class, int.class); + } catch (NoSuchMethodException exc) { + // Ignore + } + sMethodsInitialized = true; + } + + /** + * Returns the selected text between the selStart and selEnd positions. + */ + private static CharSequence getSelectedText(InputConnection ic, int selStart, int selEnd) { + // Use reflection, for backward compatibility + CharSequence result = null; + if (!sMethodsInitialized) { + initializeMethodsForReflection(); + } + if (sMethodGetSelectedText != null) { + try { + result = (CharSequence) sMethodGetSelectedText.invoke(ic, 0); + return result; + } catch (InvocationTargetException exc) { + // Ignore + } catch (IllegalArgumentException e) { + // Ignore + } catch (IllegalAccessException e) { + // Ignore + } + } + // Reflection didn't work, try it the poor way, by moving the cursor to the start, + // getting the text after the cursor and moving the text back to selected mode. + // TODO: Verify that this works properly in conjunction with + // LatinIME#onUpdateSelection + ic.setSelection(selStart, selEnd); + result = ic.getTextAfterCursor(selEnd - selStart, 0); + ic.setSelection(selStart, selEnd); + return result; + } + + /** + * Tries to set the text into composition mode if there is support for it in the framework. + */ + public static void underlineWord(InputConnection ic, SelectedWord word) { + // Use reflection, for backward compatibility + // If method not found, there's nothing we can do. It still works but just wont underline + // the word. + if (!sMethodsInitialized) { + initializeMethodsForReflection(); + } + if (sMethodSetComposingRegion != null) { + try { + sMethodSetComposingRegion.invoke(ic, word.start, word.end); + } catch (InvocationTargetException exc) { + // Ignore + } catch (IllegalArgumentException e) { + // Ignore + } catch (IllegalAccessException e) { + // Ignore + } + } + } +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/ExpandableDictionary.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/ExpandableDictionary.java new file mode 100644 index 00000000..95737626 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/ExpandableDictionary.java @@ -0,0 +1,691 @@ +/* + * 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 keepass2android.softkeyboard; + +import java.util.LinkedList; + +import android.content.Context; +import android.os.AsyncTask; + +/** + * 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 { + /** + * There is difference between what java and native code can handle. + * It uses 32 because Java stack overflows when greater value is used. + */ + protected static final int MAX_WORD_LENGTH = 32; + + private Context mContext; + private char[] mWordBuilder = new char[MAX_WORD_LENGTH]; + private int mDicTypeId; + private int mMaxDepth; + private int mInputLength; + private int[] mNextLettersFrequencies; + private StringBuilder sb = new StringBuilder(MAX_WORD_LENGTH); + + private static final char QUOTE = '\''; + + private boolean mRequiresReload; + + private boolean mUpdatingDictionary; + + // Use this lock before touching mUpdatingDictionary & mRequiresDownload + private Object mUpdatingLock = new Object(); + + static class Node { + char code; + int frequency; + boolean terminal; + Node parent; + NodeArray children; + LinkedList ngrams; // Supports ngram + } + + 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; + } + } + + static class NextWord { + Node word; + NextWord nextWord; + int frequency; + + NextWord(Node word, int frequency) { + this.word = word; + this.frequency = frequency; + } + } + + + private NodeArray mRoots; + + private int[][] mCodes; + + ExpandableDictionary(Context context, int dicTypeId) { + mContext = context; + clearDictionary(); + mCodes = new int[MAX_WORD_LENGTH][]; + mDicTypeId = dicTypeId; + } + + public void loadDictionary() { + synchronized (mUpdatingLock) { + startDictionaryLoadingTaskLocked(); + } + } + + public void startDictionaryLoadingTaskLocked() { + if (!mUpdatingDictionary) { + mUpdatingDictionary = true; + mRequiresReload = false; + new LoadDictionaryTask().execute(); + } + } + + public void setRequiresReload(boolean reload) { + synchronized (mUpdatingLock) { + mRequiresReload = reload; + } + } + + public boolean getRequiresReload() { + return mRequiresReload; + } + + /** Override to load your dictionary here, on a background thread. */ + public void loadDictionaryAsync() { + } + + Context getContext() { + return mContext; + } + + int getMaxWordLength() { + return MAX_WORD_LENGTH; + } + + public void addWord(String word, int frequency) { + addWordRec(mRoots, word, 0, frequency, null); + } + + private void addWordRec(NodeArray children, final String word, final int depth, + final int frequency, Node parentNode) { + 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; + childNode.parent = parentNode; + children.add(childNode); + } + if (wordLength == depth + 1) { + // Terminate this word + childNode.terminal = true; + childNode.frequency = Math.max(frequency, childNode.frequency); + if (childNode.frequency > 255) childNode.frequency = 255; + return; + } + if (childNode.children == null) { + childNode.children = new NodeArray(); + } + addWordRec(childNode.children, word, depth + 1, frequency, childNode); + } + + @Override + public void getWords(final WordComposer codes, final WordCallback callback, + int[] nextLettersFrequencies) { + synchronized (mUpdatingLock) { + // If we need to update, start off a background task + if (mRequiresReload) startDictionaryLoadingTaskLocked(); + // Currently updating contacts, don't return any results. + if (mUpdatingDictionary) return; + } + + mInputLength = codes.size(); + mNextLettersFrequencies = nextLettersFrequencies; + 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) { + synchronized (mUpdatingLock) { + // If we need to update, start off a background task + if (mRequiresReload) startDictionaryLoadingTaskLocked(); + if (mUpdatingDictionary) return false; + } + final int freq = getWordFrequency(word); + return freq > -1; + } + + /** + * Returns the word's frequency or -1 if not found + */ + public int getWordFrequency(CharSequence word) { + Node node = searchNode(mRoots, word, 0, word.length()); + return (node == null) ? -1 : node.frequency; + } + + /** + * 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, mDicTypeId, + DataType.UNIGRAM)) { + return; + } + // Add to frequency of next letters for predictive correction + if (mNextLettersFrequencies != null && depth >= inputIndex && skipPos < 0 + && mNextLettersFrequencies.length > word[inputIndex]) { + mNextLettersFrequencies[word[inputIndex]]++; + } + } + 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 == inputIndex + 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, mDicTypeId, + DataType.UNIGRAM); + } + } + 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 int setBigram(String word1, String word2, int frequency) { + return addOrSetBigram(word1, word2, frequency, false); + } + + protected int addBigram(String word1, String word2, int frequency) { + return addOrSetBigram(word1, word2, frequency, true); + } + + /** + * Adds bigrams to the in-memory trie structure that is being used to retrieve any word + * @param frequency frequency for this bigrams + * @param addFrequency if true, it adds to current frequency + * @return returns the final frequency + */ + private int addOrSetBigram(String word1, String word2, int frequency, boolean addFrequency) { + Node firstWord = searchWord(mRoots, word1, 0, null); + Node secondWord = searchWord(mRoots, word2, 0, null); + LinkedList bigram = firstWord.ngrams; + if (bigram == null || bigram.size() == 0) { + firstWord.ngrams = new LinkedList(); + bigram = firstWord.ngrams; + } else { + for (NextWord nw : bigram) { + if (nw.word == secondWord) { + if (addFrequency) { + nw.frequency += frequency; + } else { + nw.frequency = frequency; + } + return nw.frequency; + } + } + } + NextWord nw = new NextWord(secondWord, frequency); + firstWord.ngrams.add(nw); + return frequency; + } + + /** + * Searches for the word and add the word if it does not exist. + * @return Returns the terminal node of the word we are searching for. + */ + private Node searchWord(NodeArray children, String word, int depth, Node parentNode) { + 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; + childNode.parent = parentNode; + children.add(childNode); + } + if (wordLength == depth + 1) { + // Terminate this word + childNode.terminal = true; + return childNode; + } + if (childNode.children == null) { + childNode.children = new NodeArray(); + } + return searchWord(childNode.children, word, depth + 1, childNode); + } + + // @VisibleForTesting + boolean reloadDictionaryIfRequired() { + synchronized (mUpdatingLock) { + // If we need to update, start off a background task + if (mRequiresReload) startDictionaryLoadingTaskLocked(); + // Currently updating contacts, don't return any results. + return mUpdatingDictionary; + } + } + + private void runReverseLookUp(final CharSequence previousWord, final WordCallback callback) { + Node prevWord = searchNode(mRoots, previousWord, 0, previousWord.length()); + if (prevWord != null && prevWord.ngrams != null) { + reverseLookUp(prevWord.ngrams, callback); + } + } + + @Override + public void getBigrams(final WordComposer codes, final CharSequence previousWord, + final WordCallback callback, int[] nextLettersFrequencies) { + if (!reloadDictionaryIfRequired()) { + runReverseLookUp(previousWord, callback); + } + } + + /** + * Used only for testing purposes + * This function will wait for loading from database to be done + */ + void waitForDictionaryLoading() { + while (mUpdatingDictionary) { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + } + } + } + + /** + * reverseLookUp retrieves the full word given a list of terminal nodes and adds those words + * through callback. + * @param terminalNodes list of terminal nodes we want to add + */ + private void reverseLookUp(LinkedList terminalNodes, + final WordCallback callback) { + Node node; + int freq; + for (NextWord nextWord : terminalNodes) { + node = nextWord.word; + freq = nextWord.frequency; + // TODO Not the best way to limit suggestion threshold + if (freq >= UserBigramDictionary.SUGGEST_THRESHOLD) { + sb.setLength(0); + do { + sb.insert(0, node.code); + node = node.parent; + } while(node != null); + + // TODO better way to feed char array? + callback.addWord(sb.toString().toCharArray(), 0, sb.length(), freq, mDicTypeId, + DataType.BIGRAM); + } + } + } + + /** + * Search for the terminal node of the word + * @return Returns the terminal node of the word if the word exists + */ + private Node searchNode(final NodeArray children, final CharSequence word, final int offset, + final int length) { + // TODO Consider combining with addWordRec + 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; + } + } else { + if (node.children != null) { + Node returnNode = searchNode(node.children, word, offset + 1, length); + if (returnNode != null) return returnNode; + } + } + } + } + return null; + } + + protected void clearDictionary() { + mRoots = new NodeArray(); + } + + private class LoadDictionaryTask extends AsyncTask { + @Override + protected Void doInBackground(Void... v) { + loadDictionaryAsync(); + synchronized (mUpdatingLock) { + mUpdatingDictionary = false; + } + return null; + } + } + + 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/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/Hints.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/Hints.java new file mode 100644 index 00000000..58c15cd8 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/Hints.java @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 keepass2android.softkeyboard; + +import android.content.ContentResolver; +import android.content.Context; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import android.view.inputmethod.InputConnection; + +import java.util.Calendar; +import java.util.HashMap; +import java.util.Map; + +/** + * Logic to determine when to display hints on usage to the user. + */ +public class Hints { + public interface Display { + public void showHint(int viewResource); + } + + private static final String PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN = + "voice_hint_num_unique_days_shown"; + private static final String PREF_VOICE_HINT_LAST_TIME_SHOWN = + "voice_hint_last_time_shown"; + private static final String PREF_VOICE_INPUT_LAST_TIME_USED = + "voice_input_last_time_used"; + private static final String PREF_VOICE_PUNCTUATION_HINT_VIEW_COUNT = + "voice_punctuation_hint_view_count"; + private static final int DEFAULT_SWIPE_HINT_MAX_DAYS_TO_SHOW = 7; + private static final int DEFAULT_PUNCTUATION_HINT_MAX_DISPLAYS = 7; + + private Context mContext; + private Display mDisplay; + private boolean mVoiceResultContainedPunctuation; + private int mSwipeHintMaxDaysToShow; + private int mPunctuationHintMaxDisplays; + + // Only show punctuation hint if voice result did not contain punctuation. + static final Map SPEAKABLE_PUNCTUATION + = new HashMap(); + static { + SPEAKABLE_PUNCTUATION.put(",", "comma"); + SPEAKABLE_PUNCTUATION.put(".", "period"); + SPEAKABLE_PUNCTUATION.put("?", "question mark"); + } + + public Hints(Context context, Display display) { + mContext = context; + mDisplay = display; + + ContentResolver cr = mContext.getContentResolver(); + + } + + public boolean showSwipeHintIfNecessary(boolean fieldRecommended) { + if (fieldRecommended && shouldShowSwipeHint()) { + showHint(R.layout.voice_swipe_hint); + return true; + } + + return false; + } + + public boolean showPunctuationHintIfNecessary(InputConnection ic) { + if (!mVoiceResultContainedPunctuation + && ic != null + && getAndIncrementPref(PREF_VOICE_PUNCTUATION_HINT_VIEW_COUNT) + < mPunctuationHintMaxDisplays) { + CharSequence charBeforeCursor = ic.getTextBeforeCursor(1, 0); + if (SPEAKABLE_PUNCTUATION.containsKey(charBeforeCursor)) { + showHint(R.layout.voice_punctuation_hint); + return true; + } + } + + return false; + } + + public void registerVoiceResult(String text) { + // Update the current time as the last time voice input was used. + SharedPreferences.Editor editor = + PreferenceManager.getDefaultSharedPreferences(mContext).edit(); + editor.putLong(PREF_VOICE_INPUT_LAST_TIME_USED, System.currentTimeMillis()); + SharedPreferencesCompat.apply(editor); + + mVoiceResultContainedPunctuation = false; + for (CharSequence s : SPEAKABLE_PUNCTUATION.keySet()) { + if (text.indexOf(s.toString()) >= 0) { + mVoiceResultContainedPunctuation = true; + break; + } + } + } + + private boolean shouldShowSwipeHint() { + + + return false; + } + + /** + * Determines whether the provided time is from some time today (i.e., this day, month, + * and year). + */ + private boolean isFromToday(long timeInMillis) { + if (timeInMillis == 0) return false; + + Calendar today = Calendar.getInstance(); + today.setTimeInMillis(System.currentTimeMillis()); + + Calendar timestamp = Calendar.getInstance(); + timestamp.setTimeInMillis(timeInMillis); + + return (today.get(Calendar.YEAR) == timestamp.get(Calendar.YEAR) && + today.get(Calendar.DAY_OF_MONTH) == timestamp.get(Calendar.DAY_OF_MONTH) && + today.get(Calendar.MONTH) == timestamp.get(Calendar.MONTH)); + } + + private void showHint(int hintViewResource) { + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext); + + int numUniqueDaysShown = sp.getInt(PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN, 0); + long lastTimeHintWasShown = sp.getLong(PREF_VOICE_HINT_LAST_TIME_SHOWN, 0); + + // If this is the first time the hint is being shown today, increase the saved values + // to represent that. We don't need to increase the last time the hint was shown unless + // it is a different day from the current value. + if (!isFromToday(lastTimeHintWasShown)) { + SharedPreferences.Editor editor = sp.edit(); + editor.putInt(PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN, numUniqueDaysShown + 1); + editor.putLong(PREF_VOICE_HINT_LAST_TIME_SHOWN, System.currentTimeMillis()); + SharedPreferencesCompat.apply(editor); + } + + if (mDisplay != null) { + mDisplay.showHint(hintViewResource); + } + } + + private int getAndIncrementPref(String pref) { + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext); + int value = sp.getInt(pref, 0); + SharedPreferences.Editor editor = sp.edit(); + editor.putInt(pref, value + 1); + SharedPreferencesCompat.apply(editor); + return value; + } +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/InputLanguageSelection.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/InputLanguageSelection.java new file mode 100644 index 00000000..66cb46f0 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/InputLanguageSelection.java @@ -0,0 +1,250 @@ +/* + * Copyright (C) 2008-2009 Google Inc. + * Copyright (C) 2014 Philipp Crocoll + * Copyright (C) 2014 Wiktor Lawski + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 keepass2android.softkeyboard; + +import android.content.Context; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.os.Bundle; +import android.preference.CheckBoxPreference; +import android.preference.PreferenceActivity; +import android.preference.PreferenceGroup; +import android.preference.PreferenceManager; +import android.text.TextUtils; + +import java.text.Collator; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Locale; + +public class InputLanguageSelection extends PreferenceActivity { + + private String mSelectedLanguages; + private ArrayList mAvailableLanguages = new ArrayList(); + + private static final String[] WHITELIST_LANGUAGES = { + "cs", "da", "de", "en_GB", "en_US", "es", "es_US", "fr", "it", "nb", "nl", "pl", "pt", + "ru", "tr" + }; + + private static final String[] WEAK_WHITELIST_LANGUAGES = { + "cs", "da", "de", "en_GB", "en_US", "es", "es_US", "fr", "it", "nb", "nl", "pl", "pt", + "ru", "tr", "en" + }; + + private static boolean isWhitelisted(String lang, boolean strict) { + for (String s : (strict? WHITELIST_LANGUAGES : WEAK_WHITELIST_LANGUAGES)) { + if (s.equalsIgnoreCase(lang)) { + return true; + } + if ((!strict) && (s.length()==2) && lang.toLowerCase(Locale.US).startsWith(s)) + { + return true; + } + } + return false; + } + + private static class Loc implements Comparable { + static Collator sCollator = Collator.getInstance(); + + String label; + Locale locale; + + public Loc(String label, Locale locale) { + this.label = label; + this.locale = locale; + } + + @Override + public String toString() { + return this.label; + } + + public int compareTo(Object o) { + return sCollator.compare(this.label, ((Loc) o).label); + } + } + + @Override + protected void onCreate(Bundle icicle) { + // Get the settings preferences + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this); + + Design.updateTheme(this, sp); + + super.onCreate(icicle); + addPreferencesFromResource(R.xml.language_prefs); + mSelectedLanguages = sp.getString(KP2AKeyboard.PREF_SELECTED_LANGUAGES, ""); + String[] languageList = mSelectedLanguages.split(","); + + //first try to get the unique locales in a strict mode (filtering most redundant layouts like English (Jamaica) etc.) + mAvailableLanguages = getUniqueLocales(true); + //sometimes the strict check returns only EN_US, EN_GB and ES_US. Accept more in these cases: + if (mAvailableLanguages.size() < 5) + { + mAvailableLanguages = getUniqueLocales(false); + } + PreferenceGroup parent = getPreferenceScreen(); + for (int i = 0; i < mAvailableLanguages.size(); i++) { + CheckBoxPreference pref = new CheckBoxPreference(this); + Locale locale = mAvailableLanguages.get(i).locale; + pref.setTitle(LanguageSwitcher.toTitleCase(locale.getDisplayName(locale), locale)); + boolean checked = isLocaleIn(locale, languageList); + pref.setChecked(checked); + if (hasDictionary(locale, this)) { + pref.setSummary(R.string.has_dictionary); + } + parent.addPreference(pref); + } + } + + private boolean isLocaleIn(Locale locale, String[] list) { + String lang = get5Code(locale); + for (int i = 0; i < list.length; i++) { + if (lang.equalsIgnoreCase(list[i])) return true; + } + return false; + } + + private boolean hasDictionary(Locale locale, Context ctx) { + Resources res = getResources(); + Configuration conf = res.getConfiguration(); + Locale saveLocale = conf.locale; + boolean haveDictionary = false; + conf.locale = locale; + res.updateConfiguration(conf, res.getDisplayMetrics()); + + //somewhat a hack. But simply querying the dictionary will always return an English + //dictionary in KP2A so if we get a dict, we wouldn't know if it's language specific + if (locale.getLanguage().equals("en")) + { + haveDictionary = true; + } + else + { + BinaryDictionary plug = PluginManager.getDictionary(getApplicationContext(), locale.getLanguage()); + if (plug != null) { + plug.close(); + haveDictionary = true; + } + } + conf.locale = saveLocale; + res.updateConfiguration(conf, res.getDisplayMetrics()); + return haveDictionary; + } + + private String get5Code(Locale locale) { + String country = locale.getCountry(); + return locale.getLanguage() + + (TextUtils.isEmpty(country) ? "" : "_" + country); + } + + @Override + protected void onResume() { + super.onResume(); + } + + @Override + protected void onPause() { + super.onPause(); + // Save the selected languages + String checkedLanguages = ""; + PreferenceGroup parent = getPreferenceScreen(); + int count = parent.getPreferenceCount(); + for (int i = 0; i < count; i++) { + CheckBoxPreference pref = (CheckBoxPreference) parent.getPreference(i); + if (pref.isChecked()) { + Locale locale = mAvailableLanguages.get(i).locale; + checkedLanguages += get5Code(locale) + ","; + } + } + if (checkedLanguages.length() < 1) checkedLanguages = null; // Save null + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this); + Editor editor = sp.edit(); + editor.putString(KP2AKeyboard.PREF_SELECTED_LANGUAGES, checkedLanguages); + SharedPreferencesCompat.apply(editor); + } + + ArrayList getUniqueLocales(boolean strict) { + String[] locales = getAssets().getLocales(); + Arrays.sort(locales); + ArrayList uniqueLocales = new ArrayList(); + + final int origSize = locales.length; + Loc[] preprocess = new Loc[origSize]; + int finalSize = 0; + for (int i = 0 ; i < origSize; i++ ) { + String s = locales[i]; + + int len = s.length(); + final Locale l; + final String language; + if (len == 5) { + language = s.substring(0, 2); + String country = s.substring(3, 5); + l = new Locale(language, country); + } else if (len == 2) { + language = s; + l = new Locale(language); + } else { + android.util.Log.d("KP2AK", "locale "+s+" has unexpected length."); + continue; + } + // Exclude languages that are not relevant to LatinIME + if (!isWhitelisted(s, strict)) + { + android.util.Log.d("KP2AK", "locale "+s+" is not white-listed"); + continue; + } + + android.util.Log.d("KP2AK", "adding locale "+s); + if (finalSize == 0) { + preprocess[finalSize++] = + new Loc(LanguageSwitcher.toTitleCase(l.getDisplayName(l), l), l); + } else { + // check previous entry: + // same lang and a country -> upgrade to full name and + // insert ours with full name + // diff lang -> insert ours with lang-only name + if (preprocess[finalSize-1].locale.getLanguage().equals( + language)) { + preprocess[finalSize-1].label = LanguageSwitcher.toTitleCase( + preprocess[finalSize-1].locale.getDisplayName(), + preprocess[finalSize-1].locale); + preprocess[finalSize++] = + new Loc(LanguageSwitcher.toTitleCase(l.getDisplayName(), l), l); + } else { + String displayName; + if (s.equals("zz_ZZ")) { + } else { + displayName = LanguageSwitcher.toTitleCase(l.getDisplayName(l), l); + preprocess[finalSize++] = new Loc(displayName, l); + } + } + } + } + for (int i = 0; i < finalSize ; i++) { + uniqueLocales.add(preprocess[i]); + } + return uniqueLocales; + } +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/KP2AKeyboard.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/KP2AKeyboard.java new file mode 100644 index 00000000..a0a5dfde --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/KP2AKeyboard.java @@ -0,0 +1,2598 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package keepass2android.softkeyboard; + +import android.app.AlertDialog; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.content.res.XmlResourceParser; +import android.inputmethodservice.InputMethodService; +import android.inputmethodservice.Keyboard; +import android.media.AudioManager; +import android.os.Debug; +import android.os.Handler; +import android.os.Message; +import android.os.SystemClock; +import android.preference.PreferenceActivity; +import android.preference.PreferenceManager; +import android.text.ClipboardManager; +import android.text.TextUtils; +import android.util.DisplayMetrics; +import android.util.Log; +import android.util.PrintWriterPrinter; +import android.util.Printer; +import android.view.HapticFeedbackConstants; +import android.view.KeyEvent; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.view.inputmethod.CompletionInfo; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.ExtractedText; +import android.view.inputmethod.ExtractedTextRequest; +import android.view.inputmethod.InputConnection; +import android.view.inputmethod.InputMethodManager; +import android.widget.LinearLayout; + +import keepass2android.kbbridge.StringForTyping; +import keepass2android.softkeyboard.LatinIMEUtil.RingCharBuffer; + +import org.xmlpull.v1.XmlPullParserException; + +import java.io.FileDescriptor; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +/** + * Input method implementation for Qwerty'ish keyboard. + */ +public class KP2AKeyboard extends InputMethodService + implements LatinKeyboardBaseView.OnKeyboardActionListener, + SharedPreferences.OnSharedPreferenceChangeListener { + private static String get_KEEPASS2ANDROID_KEYBOARD_CLEARED(Context ctx) + { + return ctx.getPackageName()+".keyboard_cleared"; + } + private static final String KP2A_SAVED_FIELD_HINTS = "savedFieldHints"; + private static final String PREF_KP2A_REMEMBER_AUTO_FILL = "kp2a_remember_auto_fill"; + private static final String TAG = "LatinIME"; + private static final boolean PERF_DEBUG = false; + static final boolean DEBUG = false; + static final boolean TRACE = false; + + private static final String PREF_VIBRATE_ON = "vibrate_on"; + private static final String PREF_SOUND_ON = "sound_on"; + private static final String PREF_POPUP_ON = "popup_on"; + private static final String PREF_AUTO_CAP = "auto_cap"; + private static final String PREF_QUICK_FIXES = "quick_fixes"; + private static final String PREF_SHOW_SUGGESTIONS = "show_suggestions"; + private static final String PREF_AUTO_COMPLETE = "auto_complete"; + //private static final String PREF_BIGRAM_SUGGESTIONS = "bigram_suggestion"; + + + public static final String PREF_SELECTED_LANGUAGES = "selected_languages"; + public static final String PREF_INPUT_LANGUAGE = "input_language"; + private static final String PREF_RECORRECTION_ENABLED = "recorrection_enabled"; + + private static final int MSG_UPDATE_SUGGESTIONS = 0; + private static final int MSG_UPDATE_SHIFT_STATE = 2; + + private static final int MSG_UPDATE_OLD_SUGGESTIONS = 4; + + // 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; + + static final int KEYCODE_ENTER = '\n'; + static final int KEYCODE_SPACE = ' '; + static final int KEYCODE_PERIOD = '.'; + + // Contextual menu positions + private static final int POS_METHOD = 0; + private static final int POS_SETTINGS = 1; + + //private LatinKeyboardView mInputView; + private LinearLayout mCandidateViewContainer; + private CandidateView mCandidateView; + private Suggest mSuggest; + private CompletionInfo[] mCompletions; + + private AlertDialog mOptionsDialog; + + /* package */ KeyboardSwitcher mKeyboardSwitcher; + + //dictionaries disabled for KP2A to reduce permissions + //private UserDictionary mUserDictionary; + //private UserBigramDictionary mUserBigramDictionary; + //private ContactsDictionary mContactsDictionary; + //private AutoDictionary mAutoDictionary; + + private Resources mResources; + + private String mInputLocale; + private String mSystemLocale; + private LanguageSwitcher mLanguageSwitcher; + + private StringBuilder mComposing = new StringBuilder(); + private WordComposer mWord = new WordComposer(); + private int mCommittedLength; + private boolean mPredicting; + private boolean mRecognizing; + private CharSequence mBestWord; + private boolean mPredictionOn; + private boolean mCompletionOn; + private boolean mHasDictionary; + private boolean mAutoSpace; + private boolean mJustAddedAutoSpace; + private boolean mAutoCorrectEnabled; + private boolean mReCorrectionEnabled; + // Bigram Suggestion is disabled in this version. + private final boolean mBigramSuggestionEnabled = false; + private boolean mAutoCorrectOn; + // TODO move this state variable outside LatinIME + private boolean mCapsLock; + private boolean mVibrateOn; + private boolean mSoundOn; + private boolean mPopupOn; + private boolean mAutoCap; + private boolean mQuickFixes; + private boolean mKp2aAutoFillOn; + private boolean mKp2aRememberAutoFill; + private boolean mKp2aEnableSimpleKeyboard; + private boolean mKp2aSwitchKeyboardOnSendGoDone; + private boolean mKp2aLockOnSendGoDone; + + private boolean mIsSendGoDone; + + + private boolean mShowSuggestions; + private boolean mIsShowingHint; + private int mCorrectionMode; + private int mOrientation; + private List mSuggestPuncList; + // Keep track of the last selection range to decide if we need to show word alternatives + private int mLastSelectionStart; + private int mLastSelectionEnd; + + // Input type is such that we should not auto-correct + private boolean mInputTypeNoAutoCorrect; + + // Indicates whether the suggestion strip is to be on in landscape + private boolean mJustAccepted; + private CharSequence mJustRevertedSeparator; + private int mDeleteCount; + private long mLastKeyTime; + + // Modifier keys state + private ModifierKeyState mShiftKeyState = new ModifierKeyState(); + private ModifierKeyState mSymbolKeyState = new ModifierKeyState(); + + + private AudioManager mAudioManager; + // Align sound effect volume on music volume + private final float FX_VOLUME = -1.0f; + private boolean mSilentMode; + + /* package */ String mWordSeparators; + private String mSentenceSeparators; + private String mSuggestPuncs; + private boolean mConfigurationChanging; + + // Keeps track of most recently inserted text (multi-character key) for reverting + private CharSequence mEnteredText; + private boolean mRefreshKeyboardRequired; + + //KP2A + private boolean mShowKp2aKeyboard; //true if the user wants to see/should see the Kp2a keyboard + private boolean mHadKp2aData; //true if we already had data available in the last session + + // For each word, a list of potential replacements, usually from voice. + private Map> mWordToSuggestions = + new HashMap>(); + + private ArrayList mWordHistory = new ArrayList(); + + + public abstract static class WordAlternatives { + protected CharSequence mChosenWord; + + public WordAlternatives() { + // Nothing + } + + public WordAlternatives(CharSequence chosenWord) { + mChosenWord = chosenWord; + } + + @Override + public int hashCode() { + return mChosenWord.hashCode(); + } + + public abstract CharSequence getOriginalWord(); + + public CharSequence getChosenWord() { + return mChosenWord; + } + + public abstract List getAlternatives(); + } + + public class TypedWordAlternatives extends WordAlternatives { + private WordComposer word; + + public TypedWordAlternatives() { + // Nothing + } + + public TypedWordAlternatives(CharSequence chosenWord, WordComposer wordComposer) { + super(chosenWord); + word = wordComposer; + } + + @Override + public CharSequence getOriginalWord() { + return word.getTypedWord(); + } + + @Override + public List getAlternatives() { + return getTypedSuggestions(word); + } + } + + /* package */ Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_UPDATE_SUGGESTIONS: + updateSuggestions(); + break; + case MSG_UPDATE_OLD_SUGGESTIONS: + setOldSuggestions(); + break; + case MSG_UPDATE_SHIFT_STATE: + updateShiftKeyState(getCurrentInputEditorInfo()); + break; + + } + } + }; + private ClearKeyboardBroadcastReceiver mClearKeyboardReceiver; + private PluginManager mPluginManager; + + public class ClearKeyboardBroadcastReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + android.util.Log.d("KP2AK", "received clear keyboard broadcast"); + mShowKp2aKeyboard = false; + updateKeyboardMode(getCurrentInputEditorInfo()); + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); + boolean switchback = sp.getBoolean("AutoSwitchBackKeyboard_key", true); + if (switchback) + { + //switch back, but only "silently" (i.e. if automatic switching is enabled and available) + keepass2android.kbbridge.ImeSwitcher.switchToPreviousKeyboard(KP2AKeyboard.this, true); + } + } + + } + + + + + @Override + public void onCreate() { + LatinImeLogger.init(this); + KeyboardSwitcher.init(this); + super.onCreate(); + //setStatusIcon(R.drawable.ime_qwerty); + mResources = getResources(); + final Configuration conf = mResources.getConfiguration(); + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); + mLanguageSwitcher = new LanguageSwitcher(this); + mLanguageSwitcher.loadLocales(prefs); + mKeyboardSwitcher = KeyboardSwitcher.getInstance(); + mKeyboardSwitcher.setLanguageSwitcher(mLanguageSwitcher); + mSystemLocale = conf.locale.toString(); + mLanguageSwitcher.setSystemLocale(conf.locale); + String inputLanguage = mLanguageSwitcher.getInputLanguage(); + if (inputLanguage == null) { + inputLanguage = conf.locale.toString(); + } + mReCorrectionEnabled = prefs.getBoolean(PREF_RECORRECTION_ENABLED, + getResources().getBoolean(R.bool.default_recorrection_enabled)); + + Log.d("KP2AK","finding plugin dicts..."); + PluginManager.getPluginDictionaries(getApplicationContext()); + mPluginManager = new PluginManager(this); + final IntentFilter pFilter = new IntentFilter(); + pFilter.addDataScheme("package"); + pFilter.addAction("android.intent.action.PACKAGE_ADDED"); + pFilter.addAction("android.intent.action.PACKAGE_REPLACED"); + pFilter.addAction("android.intent.action.PACKAGE_REMOVED"); + registerReceiver(mPluginManager, pFilter); + + + LatinIMEUtil.GCUtils.getInstance().reset(); + boolean tryGC = true; + for (int i = 0; i < LatinIMEUtil.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) { + try { + initSuggest(inputLanguage); + tryGC = false; + } catch (OutOfMemoryError e) { + tryGC = LatinIMEUtil.GCUtils.getInstance().tryGCOrWait(inputLanguage, e); + } + } + + mOrientation = conf.orientation; + initSuggestPuncList(); + + // register to receive ringer mode changes for silent mode + IntentFilter filter = new IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION); + registerReceiver(mReceiver, filter); + + prefs.registerOnSharedPreferenceChangeListener(this); + + //check if we have KP2A data available: + mHadKp2aData = mShowKp2aKeyboard = keepass2android.kbbridge.KeyboardData.hasData(); + + mClearKeyboardReceiver = new ClearKeyboardBroadcastReceiver(); + registerReceiver(mClearKeyboardReceiver, new IntentFilter(get_KEEPASS2ANDROID_KEYBOARD_CLEARED(this))); + android.util.Log.d("KP2AK", "registered receiver for clear keyboard broadcast: "+get_KEEPASS2ANDROID_KEYBOARD_CLEARED(this)); + + } + + /** + * Loads a dictionary or multiple separated dictionary + * @param ctx + * @return returns array of dictionary resource ids + */ + /* package */ static int[] getDictionary(Resources res, Context ctx) { + String packageName = KP2AKeyboard.class.getPackage().getName(); + Log.d("KP2AK", "package of keyboard " + packageName); + XmlResourceParser xrp = res.getXml(R.xml.dictionary); + ArrayList dictionaries = new ArrayList(); + + try { + int current = xrp.getEventType(); + while (current != XmlResourceParser.END_DOCUMENT) { + if (current == XmlResourceParser.START_TAG) { + String tag = xrp.getName(); + if (tag != null) { + if (tag.equals("part")) { + String dictFileName = xrp.getAttributeValue(null, "name"); + int dictId = res.getIdentifier(dictFileName, "raw", ctx.getPackageName()); + Log.d("KP2AK", "Adding " + packageName+"/"+dictFileName+"/"+dictId); + dictionaries.add(dictId); + } + } + } + xrp.next(); + current = xrp.getEventType(); + } + } catch (XmlPullParserException e) { + Log.e(TAG, "Dictionary XML parsing failure"); + } catch (IOException e) { + Log.e(TAG, "Dictionary XML IOException"); + } + + int count = dictionaries.size(); + int[] dict = new int[count]; + for (int i = 0; i < count; i++) { + dict[i] = dictionaries.get(i); + } + + Log.d("KP2AK", "num dicts: " + count); + + return dict; + } + + private void initSuggest(String locale) { + mInputLocale = locale; + + Resources orig = getResources(); + Configuration conf = orig.getConfiguration(); + Locale saveLocale = conf.locale; + conf.locale = new Locale(locale); + orig.updateConfiguration(conf, orig.getDisplayMetrics()); + if (mSuggest != null) { + mSuggest.close(); + } + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this); + mQuickFixes = sp.getBoolean(PREF_QUICK_FIXES, true); + + int[] dictionaries = getDictionary(orig, this); + mSuggest = new Suggest(this, dictionaries); + updateAutoTextEnabled(saveLocale); + //if (mUserDictionary != null) mUserDictionary.close(); + //mUserDictionary = new UserDictionary(this, mInputLocale); + /*if (mContactsDictionary == null) { + mContactsDictionary = new ContactsDictionary(this, Suggest.DIC_CONTACTS); + } + if (mAutoDictionary != null) { + mAutoDictionary.close(); + } + mAutoDictionary = new AutoDictionary(this, this, mInputLocale, Suggest.DIC_AUTO);*/ + //if (mUserBigramDictionary != null) { + // mUserBigramDictionary.close(); + //} + //mUserBigramDictionary = new UserBigramDictionary(this, this, mInputLocale, + // Suggest.DIC_USER); + /*mSuggest.setUserBigramDictionary(mUserBigramDictionary); + mSuggest.setUserDictionary(mUserDictionary); + mSuggest.setContactsDictionary(mContactsDictionary); + mSuggest.setAutoDictionary(mAutoDictionary);*/ + updateCorrectionMode(); + mWordSeparators = mResources.getString(R.string.word_separators); + mSentenceSeparators = mResources.getString(R.string.sentence_separators); + + conf.locale = saveLocale; + orig.updateConfiguration(conf, orig.getDisplayMetrics()); + } + + @Override + public void onDestroy() { + /*if (mUserDictionary != null) { + mUserDictionary.close(); + } + if (mContactsDictionary != null) { + mContactsDictionary.close(); + }*/ + unregisterReceiver(mReceiver); + unregisterReceiver(mPluginManager); + unregisterReceiver(mClearKeyboardReceiver); + + LatinImeLogger.commit(); + LatinImeLogger.onDestroy(); + super.onDestroy(); + } + + @Override + public void onConfigurationChanged(Configuration conf) { + // If the system locale changes and is different from the saved + // locale (mSystemLocale), then reload the input locale list from the + // latin ime settings (shared prefs) and reset the input locale + // to the first one. + final String systemLocale = conf.locale.toString(); + if (!TextUtils.equals(systemLocale, mSystemLocale)) { + mSystemLocale = systemLocale; + if (mLanguageSwitcher != null) { + mLanguageSwitcher.loadLocales( + PreferenceManager.getDefaultSharedPreferences(this)); + mLanguageSwitcher.setSystemLocale(conf.locale); + toggleLanguage(true, true); + } else { + reloadKeyboards(); + } + } + // If orientation changed while predicting, commit the change + if (conf.orientation != mOrientation) { + InputConnection ic = getCurrentInputConnection(); + commitTyped(ic); + if (ic != null) ic.finishComposingText(); // For voice input + mOrientation = conf.orientation; + reloadKeyboards(); + } + mConfigurationChanging = true; + super.onConfigurationChanged(conf); + mConfigurationChanging = false; + } + + @Override + public View onCreateInputView() { + mKeyboardSwitcher.recreateInputView(); + mKeyboardSwitcher.makeKeyboards(true); + + loadSettings(); + + updateShowKp2aMode(); + Log.d("KP2AK", "onCreateInputView -> setKM"); + if ((mShowKp2aKeyboard) && (mKp2aEnableSimpleKeyboard)) + { + mKeyboardSwitcher.setKeyboardMode( + KeyboardSwitcher.MODE_KP2A, 0); + } + else + { + mKeyboardSwitcher.setKeyboardMode( + KeyboardSwitcher.MODE_TEXT, 0); + } + + return mKeyboardSwitcher.getInputView(); + } + + @Override + public View onCreateCandidatesView() { + mKeyboardSwitcher.makeKeyboards(true); + mCandidateViewContainer = (LinearLayout) getLayoutInflater().inflate( + R.layout.candidates, null); + mCandidateView = (CandidateView) mCandidateViewContainer.findViewById(R.id.candidates); + mCandidateView.setService(this); + setCandidatesViewShown(true); + return mCandidateViewContainer; + } + + @Override + public void onStartInputView(EditorInfo attribute, boolean restarting) { + LatinKeyboardView inputView = mKeyboardSwitcher.getInputView(); + // In landscape mode, this method gets called without the input view being created. + if (inputView == null) { + return; + } + + loadSettings(); + + if (mRefreshKeyboardRequired) { + mRefreshKeyboardRequired = false; + toggleLanguage(true, true); + } + + mKeyboardSwitcher.makeKeyboards(false); + + TextEntryState.newSession(this); + + updateKeyboardMode(attribute); + inputView.closing(); + mComposing.setLength(0); + mPredicting = false; + mDeleteCount = 0; + mJustAddedAutoSpace = false; + mIsSendGoDone = ((attribute.imeOptions&(EditorInfo.IME_MASK_ACTION|EditorInfo.IME_FLAG_NO_ENTER_ACTION)) == EditorInfo.IME_ACTION_GO) + || ((attribute.imeOptions&(EditorInfo.IME_MASK_ACTION|EditorInfo.IME_FLAG_NO_ENTER_ACTION)) == EditorInfo.IME_ACTION_DONE) + || ((attribute.imeOptions&(EditorInfo.IME_MASK_ACTION|EditorInfo.IME_FLAG_NO_ENTER_ACTION)) == EditorInfo.IME_ACTION_SEND); + + updateShiftKeyState(attribute); + + setCandidatesViewShownInternal(isCandidateStripVisible() || mCompletionOn, + false /* needsInputViewShown */ ); + updateSuggestions(); + + // If the dictionary is not big enough, don't auto correct + mHasDictionary = mSuggest.hasMainDictionary(); + Log.d("KP2AK", "has main dict: " + mHasDictionary); + + updateCorrectionMode(); + + inputView.setPreviewEnabled(mPopupOn); + inputView.setProximityCorrectionEnabled(true); + mPredictionOn = mPredictionOn && (mCorrectionMode > 0 || mShowSuggestions); + // If we just entered a text field, maybe it has some old text that requires correction + checkReCorrectionOnStart(); + + tryKp2aAutoFill(attribute); + + if (TRACE) Debug.startMethodTracing("/data/trace/latinime"); + } + + private void updateKeyboardMode(EditorInfo attribute) { + + mInputTypeNoAutoCorrect = false; + mPredictionOn = false; + mCompletionOn = false; + mCompletions = null; + mCapsLock = false; + mEnteredText = null; + + int variation = attribute.inputType & EditorInfo.TYPE_MASK_VARIATION; + + updateShowKp2aMode(); + Log.d("KP2AK", "updateKeyboardMode -> setKM"); + if ((mShowKp2aKeyboard) && (mKp2aEnableSimpleKeyboard)) + { + mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_KP2A, attribute.imeOptions); + mPredictionOn = false; + mPredicting = false; + mCompletionOn = false; + mInputTypeNoAutoCorrect = true; + } + else + { + + switch (attribute.inputType & EditorInfo.TYPE_MASK_CLASS) { + case EditorInfo.TYPE_CLASS_NUMBER: + case EditorInfo.TYPE_CLASS_DATETIME: + // fall through + // NOTE: For now, we use the phone keyboard for NUMBER and DATETIME until we get + // a dedicated number entry keypad. + // TODO: Use a dedicated number entry keypad here when we get one. + case EditorInfo.TYPE_CLASS_PHONE: + mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_PHONE, + attribute.imeOptions); + break; + case EditorInfo.TYPE_CLASS_TEXT: + mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_TEXT, + attribute.imeOptions); + //startPrediction(); + mPredictionOn = true; + // Make sure that passwords are not displayed in candidate view + if (variation == EditorInfo.TYPE_TEXT_VARIATION_PASSWORD || + variation == EditorInfo.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD ) { + mPredictionOn = false; + } + if (variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS + || variation == EditorInfo.TYPE_TEXT_VARIATION_PERSON_NAME) { + mAutoSpace = false; + } else { + mAutoSpace = true; + } + if (variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS) { + mPredictionOn = false; + mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_EMAIL, + attribute.imeOptions); + } else if (variation == EditorInfo.TYPE_TEXT_VARIATION_URI) { + mPredictionOn = false; + mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_URL, + attribute.imeOptions); + } else if (variation == EditorInfo.TYPE_TEXT_VARIATION_SHORT_MESSAGE) { + mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_IM, + attribute.imeOptions); + } else if (variation == EditorInfo.TYPE_TEXT_VARIATION_FILTER) { + mPredictionOn = false; + } else if (variation == EditorInfo.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT) { + mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_WEB, + attribute.imeOptions); + // If it's a browser edit field and auto correct is not ON explicitly, then + // disable auto correction, but keep suggestions on. + if ((attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_AUTO_CORRECT) == 0) { + mInputTypeNoAutoCorrect = true; + } + } + + // If NO_SUGGESTIONS is set, don't do prediction. + if ((attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_NO_SUGGESTIONS) != 0) { + mPredictionOn = false; + mInputTypeNoAutoCorrect = 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) { + mInputTypeNoAutoCorrect = true; + } + if ((attribute.inputType & EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE) != 0) { + mPredictionOn = false; + mCompletionOn = isFullscreenMode(); + } + break; + default: + mKeyboardSwitcher.setKeyboardMode(KeyboardSwitcher.MODE_TEXT, + attribute.imeOptions); + } + } + } + + private void updateShowKp2aMode() { + if (!keepass2android.kbbridge.KeyboardData.hasData()) + { + //data no longer available. hide kp2a keyboard: + mShowKp2aKeyboard = false; + mHadKp2aData = false; + } + else + { + + if (!mHadKp2aData) + { + if (keepass2android.kbbridge.KeyboardData.hasData()) + { + //new data available -> show kp2a keyboard: + mShowKp2aKeyboard = true; + } + } + + mHadKp2aData = keepass2android.kbbridge.KeyboardData.hasData(); + } + + Log.d("KP2AK", "show: " + mShowKp2aKeyboard); + } + + private boolean tryKp2aAutoFill(final EditorInfo editorInfo) { + + if (!mKp2aAutoFillOn) + return false; + + //auto fill in? + InputConnection ic = getCurrentInputConnection(); + if (ic == null) return false; + ExtractedTextRequest etr = new ExtractedTextRequest(); + etr.token = 0; // anything is fine here + ExtractedText et = ic.getExtractedText(etr, 0); + + boolean hasTextInField = (et != null) && (!TextUtils.isEmpty(et.text)); + if (!hasTextInField) //only auto-fill if target field is empty + { + //try to look up saved field hint: + if (!TextUtils.isEmpty(editorInfo.hintText)) + { + SharedPreferences prefs = getApplicationContext().getSharedPreferences(KP2A_SAVED_FIELD_HINTS, MODE_PRIVATE); + + String key = editorInfo.packageName+"/"+keepass2android.kbbridge.KeyboardData.entryId+"/"+editorInfo.hintText; + Log.d("KP2AK", "looking up saved field hint for "+key); + + String savedKey = prefs.getString(key, ""); + + if ("".equals(savedKey) == false) + { + Log.d("KP2AK","Found field "+savedKey); + if (commitTextForKey(editorInfo, savedKey)) + return true; + } + } + + //try to look up by hint + if ((editorInfo.hintText != null) && (editorInfo.hintText.length() > 0)) + { + if (commitTextForKey(editorInfo, editorInfo.hintText.toString())) + return true; + } + + } + return false; + } + + private boolean commitTextForKey(final EditorInfo attribute, String key) { + List availableFields = keepass2android.kbbridge.KeyboardData.availableFields; + for (StringForTyping str: availableFields) + { + if (str.key.equals(key)) + { + Log.d("KP2AK", "Typing!"); + commitKp2aString(str.value, attribute); + return true; + } + } + return false; + } + + private void commitKp2aString(String value, EditorInfo editorInfo) { + //getCurrentInputConnection().commitText(value, 0); + onText(value); + + if ((editorInfo.imeOptions&(EditorInfo.IME_MASK_ACTION|EditorInfo.IME_FLAG_NO_ENTER_ACTION)) == EditorInfo.IME_ACTION_NEXT) + { + Log.d("KP2AK", "action is NEXT"); + getCurrentInputConnection().performEditorAction(editorInfo.actionId); + } + } + + + private void checkReCorrectionOnStart() { + if (mReCorrectionEnabled && isPredictionOn()) { + // First get the cursor position. This is required by setOldSuggestions(), so that + // it can pass the correct range to setComposingRegion(). At this point, we don't + // have valid values for mLastSelectionStart/Stop because onUpdateSelection() has + // not been called yet. + InputConnection ic = getCurrentInputConnection(); + if (ic == null) return; + ExtractedTextRequest etr = new ExtractedTextRequest(); + etr.token = 0; // anything is fine here + ExtractedText et = ic.getExtractedText(etr, 0); + if (et == null) return; + + mLastSelectionStart = et.startOffset + et.selectionStart; + mLastSelectionEnd = et.startOffset + et.selectionEnd; + + // Then look for possible corrections in a delayed fashion + if (!TextUtils.isEmpty(et.text) && isCursorTouchingWord()) { + postUpdateOldSuggestions(); + } + } + } + + @Override + public void onFinishInput() { + super.onFinishInput(); + + LatinImeLogger.commit(); + onAutoCompletionStateChanged(false); + + + if (mKeyboardSwitcher.getInputView() != null) { + mKeyboardSwitcher.getInputView().closing(); + } + //if (mAutoDictionary != null) mAutoDictionary.flushPendingWrites(); + //if (mUserBigramDictionary != null) mUserBigramDictionary.flushPendingWrites(); + } + + @Override + public void onFinishInputView(boolean finishingInput) { + super.onFinishInputView(finishingInput); + // Remove penging messages related to update suggestions + mHandler.removeMessages(MSG_UPDATE_SUGGESTIONS); + mHandler.removeMessages(MSG_UPDATE_OLD_SUGGESTIONS); + } + + @Override + public void onUpdateSelection(int oldSelStart, int oldSelEnd, + int newSelStart, int newSelEnd, + int candidatesStart, int candidatesEnd) { + super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, + candidatesStart, candidatesEnd); + + if (DEBUG) { + Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart + + ", ose=" + oldSelEnd + + ", nss=" + newSelStart + + ", nse=" + newSelEnd + + ", cs=" + candidatesStart + + ", ce=" + candidatesEnd); + } + + // If the current selection in the text view changes, we should + // clear whatever candidate text we have. + if ((((mComposing.length() > 0 && mPredicting)) + && (newSelStart != candidatesEnd + || newSelEnd != candidatesEnd) + && mLastSelectionStart != newSelStart)) { + mComposing.setLength(0); + mPredicting = false; + postUpdateSuggestions(); + TextEntryState.reset(); + InputConnection ic = getCurrentInputConnection(); + if (ic != null) { + ic.finishComposingText(); + } + } else if (!mPredicting && !mJustAccepted) { + switch (TextEntryState.getState()) { + case ACCEPTED_DEFAULT: + TextEntryState.reset(); + // fall through + case SPACE_AFTER_PICKED: + mJustAddedAutoSpace = false; // The user moved the cursor. + break; + } + } + mJustAccepted = false; + postUpdateShiftKeyState(); + + // Make a note of the cursor position + mLastSelectionStart = newSelStart; + mLastSelectionEnd = newSelEnd; + + if (mReCorrectionEnabled) { + // Don't look for corrections if the keyboard is not visible + if (mKeyboardSwitcher != null && mKeyboardSwitcher.getInputView() != null + && mKeyboardSwitcher.getInputView().isShown()) { + // Check if we should go in or out of correction mode. + if (isPredictionOn() + && mJustRevertedSeparator == null + && (candidatesStart == candidatesEnd || newSelStart != oldSelStart + || TextEntryState.isCorrecting()) + && (newSelStart < newSelEnd - 1 || (!mPredicting)) + ) { + if (isCursorTouchingWord() || mLastSelectionStart < mLastSelectionEnd) { + postUpdateOldSuggestions(); + } else { + abortCorrection(false); + // Show the punctuation suggestions list if the current one is not + // and if not showing "Touch again to save". + if (mCandidateView != null + && !mSuggestPuncList.equals(mCandidateView.getSuggestions()) + && !mCandidateView.isShowingAddToDictionaryHint()) { + setNextSuggestions(); + } + } + } + } + } + } + + /** + * This is called when the user has clicked on the extracted text view, + * when running in fullscreen mode. The default implementation hides + * the candidates view when this happens, but only if the extracted text + * editor has a vertical scroll bar because its text doesn't fit. + * Here we override the behavior due to the possibility that a re-correction could + * cause the candidate strip to disappear and re-appear. + */ + @Override + public void onExtractedTextClicked() { + if (mReCorrectionEnabled && isPredictionOn()) return; + + super.onExtractedTextClicked(); + } + + /** + * This is called when the user has performed a cursor movement in the + * extracted text view, when it is running in fullscreen mode. The default + * implementation hides the candidates view when a vertical movement + * happens, but only if the extracted text editor has a vertical scroll bar + * because its text doesn't fit. + * Here we override the behavior due to the possibility that a re-correction could + * cause the candidate strip to disappear and re-appear. + */ + @Override + public void onExtractedCursorMovement(int dx, int dy) { + if (mReCorrectionEnabled && isPredictionOn()) return; + + super.onExtractedCursorMovement(dx, dy); + } + + @Override + public void hideWindow() { + LatinImeLogger.commit(); + onAutoCompletionStateChanged(false); + + if (TRACE) Debug.stopMethodTracing(); + if (mOptionsDialog != null && mOptionsDialog.isShowing()) { + mOptionsDialog.dismiss(); + mOptionsDialog = null; + } + mWordToSuggestions.clear(); + mWordHistory.clear(); + super.hideWindow(); + TextEntryState.endSession(); + } + + @Override + public void onDisplayCompletions(CompletionInfo[] completions) { + if (DEBUG) { + Log.i("foo", "Received completions:"); + for (int i=0; i<(completions != null ? completions.length : 0); i++) { + Log.i("foo", " #" + i + ": " + completions[i]); + } + } + if (mCompletionOn) { + mCompletions = completions; + if (completions == null) { + clearSuggestions(); + return; + } + + List stringList = new ArrayList(); + for (int i=0; i<(completions != null ? completions.length : 0); i++) { + CompletionInfo ci = completions[i]; + if (ci != null) stringList.add(ci.getText()); + } + // When in fullscreen mode, show completions generated by the application + setSuggestions(stringList, true, true, true); + mBestWord = null; + setCandidatesViewShown(true); + } + } + + private void setCandidatesViewShownInternal(boolean shown, boolean needsInputViewShown) { + // TODO: Remove this if we support candidates with hard keyboard + if (onEvaluateInputViewShown()) { + super.setCandidatesViewShown(shown && mKeyboardSwitcher.getInputView() != null + && (needsInputViewShown ? mKeyboardSwitcher.getInputView().isShown() : true)); + } + } + + @Override + public void setCandidatesViewShown(boolean shown) { + setCandidatesViewShownInternal(shown, true /* needsInputViewShown */ ); + } + + @Override + public void onComputeInsets(InputMethodService.Insets outInsets) { + super.onComputeInsets(outInsets); + if (!isFullscreenMode()) { + outInsets.contentTopInsets = outInsets.visibleTopInsets; + } + } + + @Override + public boolean onEvaluateFullscreenMode() { + + //no full screen mode if only simple Kp2aKeyboard is shown + if (mShowKp2aKeyboard) + return false; + + DisplayMetrics dm = getResources().getDisplayMetrics(); + float displayHeight = dm.heightPixels; + // If the display is more than X inches high, don't go to fullscreen mode + float dimen = getResources().getDimension(R.dimen.max_height_for_fullscreen); + if (displayHeight > dimen) { + return false; + } else { + return super.onEvaluateFullscreenMode(); + } + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + switch (keyCode) { + case KeyEvent.KEYCODE_BACK: + if (event.getRepeatCount() == 0 && mKeyboardSwitcher.getInputView() != null) { + if (mKeyboardSwitcher.getInputView().handleBack()) { + return true; + } + } + break; + case KeyEvent.KEYCODE_DPAD_DOWN: + case KeyEvent.KEYCODE_DPAD_UP: + case KeyEvent.KEYCODE_DPAD_LEFT: + case KeyEvent.KEYCODE_DPAD_RIGHT: + break; + } + return super.onKeyDown(keyCode, event); + } + + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) { + switch (keyCode) { + case KeyEvent.KEYCODE_DPAD_DOWN: + case KeyEvent.KEYCODE_DPAD_UP: + case KeyEvent.KEYCODE_DPAD_LEFT: + case KeyEvent.KEYCODE_DPAD_RIGHT: + LatinKeyboardView inputView = mKeyboardSwitcher.getInputView(); + // Enable shift key and DPAD to do selections + if (inputView != null && inputView.isShown() + && inputView.isShifted()) { + event = new KeyEvent(event.getDownTime(), event.getEventTime(), + event.getAction(), event.getKeyCode(), event.getRepeatCount(), + event.getDeviceId(), event.getScanCode(), + KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_ON); + InputConnection ic = getCurrentInputConnection(); + if (ic != null) ic.sendKeyEvent(event); + return true; + } + break; + } + return super.onKeyUp(keyCode, event); + } + + + private void reloadKeyboards() { + mKeyboardSwitcher.setLanguageSwitcher(mLanguageSwitcher); + mKeyboardSwitcher.makeKeyboards(true); + } + + private void commitTyped(InputConnection inputConnection) { + if (mPredicting) { + mPredicting = false; + if (mComposing.length() > 0) { + if (inputConnection != null) { + inputConnection.commitText(mComposing, 1); + } + mCommittedLength = mComposing.length(); + TextEntryState.acceptedTyped(mComposing); + addToDictionaries(mComposing, AutoDictionary.FREQUENCY_FOR_TYPED); + } + updateSuggestions(); + } + } + + private void postUpdateShiftKeyState() { + mHandler.removeMessages(MSG_UPDATE_SHIFT_STATE); + // TODO: Should remove this 300ms delay? + mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_UPDATE_SHIFT_STATE), 300); + } + + public void updateShiftKeyState(EditorInfo attr) { + InputConnection ic = getCurrentInputConnection(); + if (ic != null && attr != null && mKeyboardSwitcher.isAlphabetMode()) { + mKeyboardSwitcher.setShifted(mShiftKeyState.isMomentary() || mCapsLock + || getCursorCapsMode(ic, attr) != 0); + } + } + + private int getCursorCapsMode(InputConnection ic, EditorInfo attr) { + int caps = 0; + EditorInfo ei = getCurrentInputEditorInfo(); + if (mAutoCap && ei != null && ei.inputType != EditorInfo.TYPE_NULL) { + caps = ic.getCursorCapsMode(attr.inputType); + } + return caps; + } + + private void swapPunctuationAndSpace() { + final InputConnection ic = getCurrentInputConnection(); + if (ic == null) return; + CharSequence lastTwo = ic.getTextBeforeCursor(2, 0); + if (lastTwo != null && lastTwo.length() == 2 + && lastTwo.charAt(0) == KEYCODE_SPACE && isSentenceSeparator(lastTwo.charAt(1))) { + ic.beginBatchEdit(); + ic.deleteSurroundingText(2, 0); + ic.commitText(lastTwo.charAt(1) + " ", 1); + ic.endBatchEdit(); + updateShiftKeyState(getCurrentInputEditorInfo()); + mJustAddedAutoSpace = true; + } + } + + private void reswapPeriodAndSpace() { + final InputConnection ic = getCurrentInputConnection(); + if (ic == null) return; + CharSequence lastThree = ic.getTextBeforeCursor(3, 0); + if (lastThree != null && lastThree.length() == 3 + && lastThree.charAt(0) == KEYCODE_PERIOD + && lastThree.charAt(1) == KEYCODE_SPACE + && lastThree.charAt(2) == KEYCODE_PERIOD) { + ic.beginBatchEdit(); + ic.deleteSurroundingText(3, 0); + ic.commitText(" ..", 1); + ic.endBatchEdit(); + updateShiftKeyState(getCurrentInputEditorInfo()); + } + } + + private void doubleSpace() { + //if (!mAutoPunctuate) return; + if (mCorrectionMode == Suggest.CORRECTION_NONE) return; + final InputConnection ic = getCurrentInputConnection(); + if (ic == null) return; + CharSequence lastThree = ic.getTextBeforeCursor(3, 0); + if (lastThree != null && lastThree.length() == 3 + && Character.isLetterOrDigit(lastThree.charAt(0)) + && lastThree.charAt(1) == KEYCODE_SPACE && lastThree.charAt(2) == KEYCODE_SPACE) { + ic.beginBatchEdit(); + ic.deleteSurroundingText(2, 0); + ic.commitText(". ", 1); + ic.endBatchEdit(); + updateShiftKeyState(getCurrentInputEditorInfo()); + mJustAddedAutoSpace = true; + } + } + + private void maybeRemovePreviousPeriod(CharSequence text) { + final InputConnection ic = getCurrentInputConnection(); + if (ic == null) return; + + // When the text's first character is '.', remove the previous period + // if there is one. + CharSequence lastOne = ic.getTextBeforeCursor(1, 0); + if (lastOne != null && lastOne.length() == 1 + && lastOne.charAt(0) == KEYCODE_PERIOD + && text.charAt(0) == KEYCODE_PERIOD) { + ic.deleteSurroundingText(1, 0); + } + } + + private void removeTrailingSpace() { + final InputConnection ic = getCurrentInputConnection(); + if (ic == null) return; + + CharSequence lastOne = ic.getTextBeforeCursor(1, 0); + if (lastOne != null && lastOne.length() == 1 + && lastOne.charAt(0) == KEYCODE_SPACE) { + ic.deleteSurroundingText(1, 0); + } + } + + public boolean addWordToDictionary(String word) { + //mUserDictionary.addWord(word, 128); + // Suggestion strip should be updated after the operation of adding word to the + // user dictionary + postUpdateSuggestions(); + return true; + } + + private boolean isAlphabet(int code) { + if (Character.isLetter(code)) { + return true; + } else { + return false; + } + } + + private void showInputMethodPicker() { + ((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE)) + .showInputMethodPicker(); + } + + private void onOptionKeyPressed() { + if (!isShowingOptionDialog()) { + launchSettings(); + } + } + + private void onOptionKeyLongPressed() { + if (!isShowingOptionDialog()) { + if (LatinIMEUtil.hasMultipleEnabledIMEs(this)) { + showInputMethodPicker(); + } else { + launchSettings(); + } + } + } + + private boolean isShowingOptionDialog() { + return mOptionsDialog != null && mOptionsDialog.isShowing(); + } + + // Implementation of KeyboardViewListener + + public void onKey(int primaryCode, int[] keyCodes, int x, int y) { + long when = SystemClock.uptimeMillis(); + if (primaryCode != Keyboard.KEYCODE_DELETE || + when > mLastKeyTime + QUICK_PRESS) { + mDeleteCount = 0; + } + mLastKeyTime = when; + final boolean distinctMultiTouch = mKeyboardSwitcher.hasDistinctMultitouch(); + switch (primaryCode) { + case Keyboard.KEYCODE_DELETE: + handleBackspace(); + mDeleteCount++; + LatinImeLogger.logOnDelete(); + break; + case Keyboard.KEYCODE_SHIFT: + // Shift key is handled in onPress() when device has distinct multi-touch panel. + if (!distinctMultiTouch) + handleShift(); + break; + case Keyboard.KEYCODE_MODE_CHANGE: + // Symbol key is handled in onPress() when device has distinct multi-touch panel. + if (!distinctMultiTouch) + changeKeyboardMode(); + break; + case Keyboard.KEYCODE_CANCEL: + if (!isShowingOptionDialog()) { + handleClose(); + } + break; + case LatinKeyboardView.KEYCODE_OPTIONS: + onOptionKeyPressed(); + break; + case LatinKeyboardView.KEYCODE_KP2A: + onKp2aKeyPressed(); + break; + case LatinKeyboardView.KEYCODE_KP2A_USER: + onKp2aUserKeyPressed(); + break; + case LatinKeyboardView.KEYCODE_KP2A_PASSWORD: + onKp2aPasswordKeyPressed(); + break; + case LatinKeyboardView.KEYCODE_KP2A_ALPHA: + onKp2aAlphaKeyPressed(); + break; + case LatinKeyboardView.KEYCODE_KP2A_SWITCH: + onKp2aSwitchKeyboardPressed(); + break; + case LatinKeyboardView.KEYCODE_KP2A_LOCK: + onKp2aLockKeyPressed(); + break; + case LatinKeyboardView.KEYCODE_OPTIONS_LONGPRESS: + onOptionKeyLongPressed(); + break; + case LatinKeyboardView.KEYCODE_NEXT_LANGUAGE: + toggleLanguage(false, true); + break; + case LatinKeyboardView.KEYCODE_PREV_LANGUAGE: + toggleLanguage(false, false); + break; + case 9 /*Tab*/: + sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB); + break; + case KEYCODE_ENTER: + onEnterKey(); + //fall through + default: + if (primaryCode != KEYCODE_ENTER) { + mJustAddedAutoSpace = false; + } + RingCharBuffer.getInstance().push((char)primaryCode, x, y); + LatinImeLogger.logOnInputChar(); + if (isWordSeparator(primaryCode)) { + handleSeparator(primaryCode); + } else { + handleCharacter(primaryCode, keyCodes); + } + // Cancel the just reverted state + mJustRevertedSeparator = null; + } + mKeyboardSwitcher.onKey(primaryCode); + // Reset after any single keystroke + mEnteredText = null; + } + + private void onEnterKey() { + if ((mIsSendGoDone) && (mKeyboardSwitcher.getKeyboardMode() == KeyboardSwitcher.MODE_KP2A)) + { + if (mKp2aSwitchKeyboardOnSendGoDone) + { + keepass2android.kbbridge.ImeSwitcher.switchToPreviousKeyboard(this, false); + } + if (mKp2aLockOnSendGoDone) + { + onKp2aLockKeyPressed(); + } + } + + } + + private void onKp2aLockKeyPressed() { + + String action = getPackageName()+".lock_database"; + android.util.Log.i("KP2A", "sending broadcast with action "+action); + sendBroadcast(new Intent(action)); + + } + + private void onKp2aSwitchKeyboardPressed() { + showInputMethodPicker(); + + } + + private void onKp2aAlphaKeyPressed() { + mShowKp2aKeyboard = false; + updateKeyboardMode(getCurrentInputEditorInfo()); + } + + private void onKp2aPasswordKeyPressed() { + commitStringForTyping(findStringForTyping("Password")); + } + + private StringForTyping findStringForTyping(String key) { + + for (StringForTyping s: keepass2android.kbbridge.KeyboardData.availableFields) + { + if (key.equals(s.key)) + { + return s; + } + } + //found nothing: return empty struct: + return new StringForTyping(); + } + + private void onKp2aUserKeyPressed() { + commitStringForTyping(findStringForTyping("UserName")); + + } + + private void onKp2aKeyPressed() { + if ((mKeyboardSwitcher.getKeyboardMode() == KeyboardSwitcher.MODE_KP2A) + || (!mKp2aEnableSimpleKeyboard) + || (!keepass2android.kbbridge.KeyboardData.hasData())) + { + showKp2aDialog(); + return; + } + mShowKp2aKeyboard = true; + updateKeyboardMode(getCurrentInputEditorInfo()); + setCandidatesViewShown(false); + } + + private void showKp2aDialog() { + AlertDialog.Builder builder = new AlertDialog.Builder(this); + String title = "Keepass2Android"; + List availableFields = keepass2android.kbbridge.KeyboardData.availableFields; + + final EditorInfo attribute = getCurrentInputEditorInfo(); + Log.d("KP2AK", "hint: "+attribute.hintText); + Log.d("KP2AK", "field name: "+attribute.fieldName); + Log.d("KP2AK", "label: "+attribute.label); + attribute.dump(new Printer() { + + @Override + public void println(String x) { + Log.d("KP2AK", x); + + } + },""); + final ArrayList items = new ArrayList(); + for (StringForTyping entry : availableFields) + { + Log.d("KP2AK", entry.displayName); + items.add(entry.clone()); + } + + + + StringForTyping openOrChangeEntry = new StringForTyping(); + if (keepass2android.kbbridge.KeyboardData.entryName == null) + { + openOrChangeEntry.displayName = openOrChangeEntry.key = getString(R.string.open_entry); + } + else + { + openOrChangeEntry.displayName = openOrChangeEntry.key = getString(R.string.change_entry); + } + openOrChangeEntry.value = "KP2ASPECIAL_SelectEntryTask"; + items.add(openOrChangeEntry); + + + final String clientPackageName = attribute.packageName; + + if ((clientPackageName != null) && (clientPackageName != "")) + { + StringForTyping searchEntry = new StringForTyping(); + try + { + searchEntry.key = searchEntry.displayName + = getString(R.string.open_entry_for_app, clientPackageName); + } + catch (java.util.FormatFlagsConversionMismatchException e) //buggy crowdin support for Arabic? + { + android.util.Log.e("KP2A", "Please report this error to crocoapps@gmail.com"); + android.util.Log.e("KP2A", e.toString()); + + searchEntry.key = searchEntry.displayName + = "Search entry for app"; + } + + searchEntry.value = "KP2ASPECIAL_SearchUrlTask"; + items.add(searchEntry); + } + + + builder.setTitle(title); + + CharSequence[] itemNames = new CharSequence[items.size()]; + int i=0; + for (StringForTyping sft: items) + itemNames[i++] = sft.displayName; + + builder.setItems(itemNames, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int item) { + + Log.d("KP2AK", "clicked item: " + items.get(item).key); + + if (items.get(item).value.startsWith("KP2ASPECIAL")) { + //change entry + Log.d("KP2AK", "clicked item: " + items.get(item).value); + + String packageName = getApplicationContext().getPackageName(); + Intent startKp2aIntent = getPackageManager().getLaunchIntentForPackage(packageName); + if (startKp2aIntent != null) + { + startKp2aIntent.addCategory(Intent.CATEGORY_LAUNCHER); + startKp2aIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + String value = items.get(item).value; + String taskName = value.substring("KP2ASPECIAL_".length()); + startKp2aIntent.putExtra("KP2A_APPTASK", taskName); + if (taskName.equals("SearchUrlTask")) + { + startKp2aIntent.putExtra("UrlToSearch", "androidapp://"+clientPackageName); + } + startActivity(startKp2aIntent); + } else Log.w("KP2AK", "didn't find intent for "+packageName); + } else { + + StringForTyping theItem = items.get(item); + + commitStringForTyping(theItem); + + } + } + + }); + + builder.setNegativeButton(android.R.string.cancel, + new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + // User cancelled the dialog + } + }); + + // Create the AlertDialog + AlertDialog dialog = builder.create(); + Window window = dialog.getWindow(); + WindowManager.LayoutParams lp = window.getAttributes(); + LatinKeyboardView inputView = mKeyboardSwitcher.getInputView(); + lp.token = inputView.getWindowToken(); + lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; + window.setAttributes(lp); + window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); + + dialog.show(); + } + private void commitStringForTyping(StringForTyping theItem) { + + if ((mKp2aRememberAutoFill) && (!TextUtils.isEmpty(getCurrentInputEditorInfo().hintText))) + { + EditorInfo editorInfo = getCurrentInputEditorInfo(); + String key = editorInfo.packageName+"/"+keepass2android.kbbridge.KeyboardData.entryId+"/"+editorInfo.hintText; + SharedPreferences prefs = getApplicationContext().getSharedPreferences(KP2A_SAVED_FIELD_HINTS, MODE_PRIVATE); + + Editor edit = prefs.edit(); + + edit.putString(key, theItem.key); + edit.commit(); + } + + + + Log.d("KP2AK", "committing text for " + theItem.key); + commitKp2aString(theItem.value, getCurrentInputEditorInfo()); + } + + + public void onText(CharSequence text) { + InputConnection ic = getCurrentInputConnection(); + if (ic == null) return; + if (text == null) + { + Log.e("KP2AK", "text = null!"); + return; + } + abortCorrection(false); + ic.beginBatchEdit(); + if (mPredicting) { + commitTyped(ic); + } + maybeRemovePreviousPeriod(text); + ic.commitText(text, 1); + ic.endBatchEdit(); + updateShiftKeyState(getCurrentInputEditorInfo()); + mKeyboardSwitcher.onKey(0); // dummy key code. + mJustRevertedSeparator = null; + mJustAddedAutoSpace = false; + mEnteredText = text; + } + + public void onCancel() { + // User released a finger outside any key + mKeyboardSwitcher.onCancelInput(); + } + + private void handleBackspace() { + boolean deleteChar = false; + InputConnection ic = getCurrentInputConnection(); + if (ic == null) return; + + ic.beginBatchEdit(); + + if (mPredicting) { + final int length = mComposing.length(); + if (length > 0) { + mComposing.delete(length - 1, length); + mWord.deleteLast(); + ic.setComposingText(mComposing, 1); + if (mComposing.length() == 0) { + mPredicting = false; + } + postUpdateSuggestions(); + } else { + ic.deleteSurroundingText(1, 0); + } + } else { + deleteChar = true; + } + postUpdateShiftKeyState(); + TextEntryState.backspace(); + if (TextEntryState.getState() == TextEntryState.State.UNDO_COMMIT) { + revertLastWord(deleteChar); + ic.endBatchEdit(); + return; + } else if (mEnteredText != null && sameAsTextBeforeCursor(ic, mEnteredText)) { + ic.deleteSurroundingText(mEnteredText.length(), 0); + } else if (deleteChar) { + if (mCandidateView != null && mCandidateView.dismissAddToDictionaryHint()) { + // Go back to the suggestion mode if the user canceled the + // "Touch again to save". + // NOTE: In gerenal, we don't revert the word when backspacing + // from a manual suggestion pick. We deliberately chose a + // different behavior only in the case of picking the first + // suggestion (typed word). It's intentional to have made this + // inconsistent with backspacing after selecting other suggestions. + revertLastWord(deleteChar); + } else { + sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); + if (mDeleteCount > DELETE_ACCELERATE_AT) { + sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); + } + } + } + mJustRevertedSeparator = null; + ic.endBatchEdit(); + } + + private void resetShift() { + handleShiftInternal(true); + } + + private void handleShift() { + handleShiftInternal(false); + } + + private void handleShiftInternal(boolean forceNormal) { + mHandler.removeMessages(MSG_UPDATE_SHIFT_STATE); + KeyboardSwitcher switcher = mKeyboardSwitcher; + LatinKeyboardView inputView = switcher.getInputView(); + if (switcher.isAlphabetMode()) { + if (mCapsLock || forceNormal) { + mCapsLock = false; + switcher.setShifted(false); + } else if (inputView != null) { + if (inputView.isShifted()) { + mCapsLock = true; + switcher.setShiftLocked(true); + } else { + switcher.setShifted(true); + } + } + } else { + switcher.toggleShift(); + } + } + + private void abortCorrection(boolean force) { + if (force || TextEntryState.isCorrecting()) { + getCurrentInputConnection().finishComposingText(); + clearSuggestions(); + } + } + + private void handleCharacter(int primaryCode, int[] keyCodes) { + + if (mLastSelectionStart == mLastSelectionEnd && TextEntryState.isCorrecting()) { + abortCorrection(false); + } + + if (isAlphabet(primaryCode) && isPredictionOn() && !isCursorTouchingWord()) { + if (!mPredicting) { + mPredicting = true; + mComposing.setLength(0); + saveWordInHistory(mBestWord); + mWord.reset(); + } + } + if (mKeyboardSwitcher.getInputView().isShifted()) { + if (keyCodes == null || keyCodes[0] < Character.MIN_CODE_POINT + || keyCodes[0] > Character.MAX_CODE_POINT) { + return; + } + primaryCode = keyCodes[0]; + if (mKeyboardSwitcher.isAlphabetMode() && Character.isLowerCase(primaryCode)) { + // In some locales, such as Turkish, Character.toUpperCase() may return a wrong + // character because it doesn't take care of locale. + final String upperCaseString = new String(new int[] {primaryCode}, 0, 1) + .toUpperCase(mLanguageSwitcher.getInputLocale()); + if (upperCaseString.codePointCount(0, upperCaseString.length()) == 1) { + primaryCode = upperCaseString.codePointAt(0); + } else { + // Some keys, such as [eszett], have upper case as multi-characters. + onText(upperCaseString); + return; + } + } + } + if (mPredicting) { + if (mKeyboardSwitcher.getInputView().isShifted() + && mKeyboardSwitcher.isAlphabetMode() + && mComposing.length() == 0) { + mWord.setFirstCharCapitalized(true); + } + mComposing.append((char) primaryCode); + mWord.add(primaryCode, keyCodes); + InputConnection ic = getCurrentInputConnection(); + if (ic != null) { + // If it's the first letter, make note of auto-caps state + if (mWord.size() == 1) { + mWord.setAutoCapitalized( + getCursorCapsMode(ic, getCurrentInputEditorInfo()) != 0); + } + ic.setComposingText(mComposing, 1); + } + postUpdateSuggestions(); + } else { + sendKeyChar((char)primaryCode); + } + updateShiftKeyState(getCurrentInputEditorInfo()); + if (KP2AKeyboard.PERF_DEBUG) measureCps(); + TextEntryState.typedCharacter((char) primaryCode, isWordSeparator(primaryCode)); + } + + private void handleSeparator(int primaryCode) { + // Should dismiss the "Touch again to save" message when handling separator + if (mCandidateView != null && mCandidateView.dismissAddToDictionaryHint()) { + postUpdateSuggestions(); + } + + boolean pickedDefault = false; + // Handle separator + InputConnection ic = getCurrentInputConnection(); + if (ic != null) { + ic.beginBatchEdit(); + abortCorrection(false); + } + if (mPredicting) { + // In certain languages where single quote is a separator, it's better + // not to auto correct, but accept the typed word. For instance, + // in Italian dov' should not be expanded to dove' because the elision + // requires the last vowel to be removed. + if (mAutoCorrectOn && primaryCode != '\'' && + (mJustRevertedSeparator == null + || mJustRevertedSeparator.length() == 0 + || mJustRevertedSeparator.charAt(0) != primaryCode)) { + pickedDefault = pickDefaultSuggestion(); + // Picked the suggestion by the space key. We consider this + // as "added an auto space". + if (primaryCode == KEYCODE_SPACE) { + mJustAddedAutoSpace = true; + } + } else { + commitTyped(ic); + } + } + if (mJustAddedAutoSpace && primaryCode == KEYCODE_ENTER) { + removeTrailingSpace(); + mJustAddedAutoSpace = false; + } + sendKeyChar((char)primaryCode); + + // Handle the case of ". ." -> " .." with auto-space if necessary + // before changing the TextEntryState. + if (TextEntryState.getState() == TextEntryState.State.PUNCTUATION_AFTER_ACCEPTED + && primaryCode == KEYCODE_PERIOD) { + reswapPeriodAndSpace(); + } + + TextEntryState.typedCharacter((char) primaryCode, true); + if (TextEntryState.getState() == TextEntryState.State.PUNCTUATION_AFTER_ACCEPTED + && primaryCode != KEYCODE_ENTER) { + swapPunctuationAndSpace(); + } else if (isPredictionOn() && primaryCode == KEYCODE_SPACE) { + doubleSpace(); + } + if (pickedDefault) { + TextEntryState.backToAcceptedDefault(mWord.getTypedWord()); + } + updateShiftKeyState(getCurrentInputEditorInfo()); + if (ic != null) { + ic.endBatchEdit(); + } + } + + private void handleClose() { + commitTyped(getCurrentInputConnection()); + requestHideSelf(0); + if (mKeyboardSwitcher != null) { + LatinKeyboardView inputView = mKeyboardSwitcher.getInputView(); + if (inputView != null) { + inputView.closing(); + } + } + TextEntryState.endSession(); + } + + private void saveWordInHistory(CharSequence result) { + if (mWord.size() <= 1) { + mWord.reset(); + return; + } + // Skip if result is null. It happens in some edge case. + if (TextUtils.isEmpty(result)) { + return; + } + + // Make a copy of the CharSequence, since it is/could be a mutable CharSequence + final String resultCopy = result.toString(); + TypedWordAlternatives entry = new TypedWordAlternatives(resultCopy, + new WordComposer(mWord)); + mWordHistory.add(entry); + } + + private void postUpdateSuggestions() { + mHandler.removeMessages(MSG_UPDATE_SUGGESTIONS); + mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_UPDATE_SUGGESTIONS), 100); + } + + private void postUpdateOldSuggestions() { + mHandler.removeMessages(MSG_UPDATE_OLD_SUGGESTIONS); + mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_UPDATE_OLD_SUGGESTIONS), 300); + } + + private boolean isPredictionOn() { + return mPredictionOn; + } + + private boolean isCandidateStripVisible() { + return isPredictionOn() && mShowSuggestions; + } + + public void onCancelVoice() { + if (mRecognizing) { + switchToKeyboardView(); + } + } + + private void switchToKeyboardView() { + mHandler.post(new Runnable() { + public void run() { + mRecognizing = false; + if (mKeyboardSwitcher.getInputView() != null) { + setInputView(mKeyboardSwitcher.getInputView()); + } + setCandidatesViewShown(true); + updateInputViewShown(); + postUpdateSuggestions(); + }}); + } + + private void clearSuggestions() { + setSuggestions(null, false, false, false); + } + + private void setSuggestions( + List suggestions, + boolean completions, + boolean typedWordValid, + boolean haveMinimalSuggestion) { + + if (mIsShowingHint) { + setCandidatesView(mCandidateViewContainer); + mIsShowingHint = false; + } + + if (mCandidateView != null) { + mCandidateView.setSuggestions( + suggestions, completions, typedWordValid, haveMinimalSuggestion); + } + } + + private void updateSuggestions() { + LatinKeyboardView inputView = mKeyboardSwitcher.getInputView(); + ((LatinKeyboard) inputView.getKeyboard()).setPreferredLetters(null); + + // Check if we have a suggestion engine attached. + if ((mSuggest == null || !isPredictionOn())) { + return; + } + + if (!mPredicting) { + setNextSuggestions(); + return; + } + showSuggestions(mWord); + } + + private List getTypedSuggestions(WordComposer word) { + List stringList = mSuggest.getSuggestions( + mKeyboardSwitcher.getInputView(), word, false, null); + return stringList; + } + + private void showCorrections(WordAlternatives alternatives) { + List stringList = alternatives.getAlternatives(); + ((LatinKeyboard) mKeyboardSwitcher.getInputView().getKeyboard()).setPreferredLetters(null); + showSuggestions(stringList, alternatives.getOriginalWord(), false, false); + } + + private void showSuggestions(WordComposer word) { + // long startTime = System.currentTimeMillis(); // TIME MEASUREMENT! + // TODO Maybe need better way of retrieving previous word + CharSequence prevWord = EditingUtil.getPreviousWord(getCurrentInputConnection(), + mWordSeparators); + List stringList = mSuggest.getSuggestions( + mKeyboardSwitcher.getInputView(), word, false, prevWord); + // long stopTime = System.currentTimeMillis(); // TIME MEASUREMENT! + // Log.d("LatinIME","Suggest Total Time - " + (stopTime - startTime)); + + int[] nextLettersFrequencies = mSuggest.getNextLettersFrequencies(); + + ((LatinKeyboard) mKeyboardSwitcher.getInputView().getKeyboard()).setPreferredLetters( + nextLettersFrequencies); + + boolean correctionAvailable = !mInputTypeNoAutoCorrect && mSuggest.hasMinimalCorrection(); + //|| mCorrectionMode == mSuggest.CORRECTION_FULL; + CharSequence typedWord = word.getTypedWord(); + // If we're in basic correct + boolean typedWordValid = mSuggest.isValidWord(typedWord) || + (preferCapitalization() + && mSuggest.isValidWord(typedWord.toString().toLowerCase())); + if (mCorrectionMode == Suggest.CORRECTION_FULL + || mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM) { + correctionAvailable |= typedWordValid; + } + // Don't auto-correct words with multiple capital letter + correctionAvailable &= !word.isMostlyCaps(); + correctionAvailable &= !TextEntryState.isCorrecting(); + + showSuggestions(stringList, typedWord, typedWordValid, correctionAvailable); + } + + private void showSuggestions(List stringList, CharSequence typedWord, + boolean typedWordValid, boolean correctionAvailable) { + setSuggestions(stringList, false, typedWordValid, correctionAvailable); + if (stringList.size() > 0) { + if (correctionAvailable && !typedWordValid && stringList.size() > 1) { + mBestWord = stringList.get(1); + } else { + mBestWord = typedWord; + } + } else { + mBestWord = null; + } + setCandidatesViewShown(isCandidateStripVisible() || mCompletionOn); + } + + private boolean pickDefaultSuggestion() { + // Complete any pending candidate query first + if (mHandler.hasMessages(MSG_UPDATE_SUGGESTIONS)) { + mHandler.removeMessages(MSG_UPDATE_SUGGESTIONS); + updateSuggestions(); + } + if (mBestWord != null && mBestWord.length() > 0) { + TextEntryState.acceptedDefault(mWord.getTypedWord(), mBestWord); + mJustAccepted = true; + pickSuggestion(mBestWord, false); + // Add the word to the auto dictionary if it's not a known word + addToDictionaries(mBestWord, AutoDictionary.FREQUENCY_FOR_TYPED); + return true; + + } + return false; + } + + public void pickSuggestionManually(int index, CharSequence suggestion) { + List suggestions = mCandidateView.getSuggestions(); + + + + final boolean correcting = TextEntryState.isCorrecting(); + InputConnection ic = getCurrentInputConnection(); + if (ic != null) { + ic.beginBatchEdit(); + } + if (mCompletionOn && mCompletions != null && index >= 0 + && index < mCompletions.length) { + CompletionInfo ci = mCompletions[index]; + if (ic != null) { + ic.commitCompletion(ci); + } + mCommittedLength = suggestion.length(); + if (mCandidateView != null) { + mCandidateView.clear(); + } + updateShiftKeyState(getCurrentInputEditorInfo()); + if (ic != null) { + ic.endBatchEdit(); + } + return; + } + + // If this is a punctuation, apply it through the normal key press + if (suggestion.length() == 1 && (isWordSeparator(suggestion.charAt(0)) + || isSuggestedPunctuation(suggestion.charAt(0)))) { + // Word separators are suggested before the user inputs something. + // So, LatinImeLogger logs "" as a user's input. + LatinImeLogger.logOnManualSuggestion( + "", suggestion.toString(), index, suggestions); + final char primaryCode = suggestion.charAt(0); + onKey(primaryCode, new int[]{primaryCode}, LatinKeyboardBaseView.NOT_A_TOUCH_COORDINATE, + LatinKeyboardBaseView.NOT_A_TOUCH_COORDINATE); + if (ic != null) { + ic.endBatchEdit(); + } + return; + } + mJustAccepted = true; + pickSuggestion(suggestion, correcting); + // Add the word to the auto dictionary if it's not a known word + if (index == 0) { + addToDictionaries(suggestion, AutoDictionary.FREQUENCY_FOR_PICKED); + } else { + addToBigramDictionary(suggestion, 1); + } + LatinImeLogger.logOnManualSuggestion(mComposing.toString(), suggestion.toString(), + index, suggestions); + TextEntryState.acceptedSuggestion(mComposing.toString(), suggestion); + // Follow it with a space + if (mAutoSpace && !correcting) { + sendSpace(); + mJustAddedAutoSpace = true; + } + + final boolean showingAddToDictionaryHint = index == 0 && mCorrectionMode > 0 + && !mSuggest.isValidWord(suggestion) + && !mSuggest.isValidWord(suggestion.toString().toLowerCase()); + + if (!correcting) { + // Fool the state watcher so that a subsequent backspace will not do a revert, unless + // we just did a correction, in which case we need to stay in + // TextEntryState.State.PICKED_SUGGESTION state. + TextEntryState.typedCharacter((char) KEYCODE_SPACE, true); + setNextSuggestions(); + } else if (!showingAddToDictionaryHint) { + // If we're not showing the "Touch again to save", then show corrections again. + // In case the cursor position doesn't change, make sure we show the suggestions again. + clearSuggestions(); + postUpdateOldSuggestions(); + } + if (showingAddToDictionaryHint) { + mCandidateView.showAddToDictionaryHint(suggestion); + } + if (ic != null) { + ic.endBatchEdit(); + } + } + + private void rememberReplacedWord(CharSequence suggestion) { + + } + + /** + * Commits the chosen word to the text field and saves it for later + * retrieval. + * @param suggestion the suggestion picked by the user to be committed to + * the text field + * @param correcting whether this is due to a correction of an existing + * word. + */ + private void pickSuggestion(CharSequence suggestion, boolean correcting) { + final LatinKeyboardView inputView = mKeyboardSwitcher.getInputView(); + final Locale inputLocale = mLanguageSwitcher.getInputLocale(); + if (mCapsLock) { + suggestion = suggestion.toString().toUpperCase(inputLocale); + } else if (preferCapitalization() + || (mKeyboardSwitcher.isAlphabetMode() + && inputView.isShifted())) { + suggestion = suggestion.toString().toUpperCase(inputLocale).charAt(0) + + suggestion.subSequence(1, suggestion.length()).toString(); + } + InputConnection ic = getCurrentInputConnection(); + if (ic != null) { + rememberReplacedWord(suggestion); + ic.commitText(suggestion, 1); + } + saveWordInHistory(suggestion); + mPredicting = false; + mCommittedLength = suggestion.length(); + ((LatinKeyboard) inputView.getKeyboard()).setPreferredLetters(null); + // If we just corrected a word, then don't show punctuations + if (!correcting) { + setNextSuggestions(); + } + updateShiftKeyState(getCurrentInputEditorInfo()); + } + + /** + * Tries to apply any typed alternatives for the word if we have any cached alternatives, + * otherwise tries to find new corrections and completions for the word. + * @param touching The word that the cursor is touching, with position information + * @return true if an alternative was found, false otherwise. + */ + private boolean applyTypedAlternatives(EditingUtil.SelectedWord touching) { + // If we didn't find a match, search for result in typed word history + WordComposer foundWord = null; + WordAlternatives alternatives = null; + for (WordAlternatives entry : mWordHistory) { + if (TextUtils.equals(entry.getChosenWord(), touching.word)) { + if (entry instanceof TypedWordAlternatives) { + foundWord = ((TypedWordAlternatives) entry).word; + } + alternatives = entry; + break; + } + } + // If we didn't find a match, at least suggest completions + if (foundWord == null + && (mSuggest.isValidWord(touching.word) + || mSuggest.isValidWord(touching.word.toString().toLowerCase()))) { + foundWord = new WordComposer(); + for (int i = 0; i < touching.word.length(); i++) { + foundWord.add(touching.word.charAt(i), new int[] { + touching.word.charAt(i) + }); + } + foundWord.setFirstCharCapitalized(Character.isUpperCase(touching.word.charAt(0))); + } + // Found a match, show suggestions + if (foundWord != null || alternatives != null) { + if (alternatives == null) { + alternatives = new TypedWordAlternatives(touching.word, foundWord); + } + showCorrections(alternatives); + if (foundWord != null) { + mWord = new WordComposer(foundWord); + } else { + mWord.reset(); + } + return true; + } + return false; + } + + private void setOldSuggestions() { + + if (mCandidateView != null && mCandidateView.isShowingAddToDictionaryHint()) { + return; + } + InputConnection ic = getCurrentInputConnection(); + if (ic == null) return; + if (!mPredicting) { + // Extract the selected or touching text + EditingUtil.SelectedWord touching = EditingUtil.getWordAtCursorOrSelection(ic, + mLastSelectionStart, mLastSelectionEnd, mWordSeparators); + + if (touching != null && touching.word.length() > 1) { + ic.beginBatchEdit(); + + if (!applyTypedAlternatives(touching)) { + abortCorrection(true); + } else { + TextEntryState.selectedForCorrection(); + EditingUtil.underlineWord(ic, touching); + } + + ic.endBatchEdit(); + } else { + abortCorrection(true); + setNextSuggestions(); // Show the punctuation suggestions list + } + } else { + abortCorrection(true); + } + } + + private void setNextSuggestions() { + setSuggestions(mSuggestPuncList, false, false, false); + } + + private void addToDictionaries(CharSequence suggestion, int frequencyDelta) { + checkAddToDictionary(suggestion, frequencyDelta, false); + } + + private void addToBigramDictionary(CharSequence suggestion, int frequencyDelta) { + checkAddToDictionary(suggestion, frequencyDelta, true); + } + + /** + * Adds to the UserBigramDictionary and/or AutoDictionary + * @param addToBigramDictionary true if it should be added to bigram dictionary if possible + */ + private void checkAddToDictionary(CharSequence suggestion, int frequencyDelta, + boolean addToBigramDictionary) { + if (suggestion == null || suggestion.length() < 1) return; + // Only auto-add to dictionary if auto-correct is ON. Otherwise we'll be + // adding words in situations where the user or application really didn't + // want corrections enabled or learned. + if (!(mCorrectionMode == Suggest.CORRECTION_FULL + || mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM)) { + return; + } + if (suggestion != null) { + /*if (!addToBigramDictionary && mAutoDictionary.isValidWord(suggestion) + || (!mSuggest.isValidWord(suggestion.toString()) + && !mSuggest.isValidWord(suggestion.toString().toLowerCase()))) { + mAutoDictionary.addWord(suggestion.toString(), frequencyDelta); + } + + if (mUserBigramDictionary != null) { + CharSequence prevWord = EditingUtil.getPreviousWord(getCurrentInputConnection(), + mSentenceSeparators); + if (!TextUtils.isEmpty(prevWord)) { + mUserBigramDictionary.addBigrams(prevWord.toString(), suggestion.toString()); + } + }*/ + } + } + + private boolean isCursorTouchingWord() { + InputConnection ic = getCurrentInputConnection(); + if (ic == null) return false; + CharSequence toLeft = ic.getTextBeforeCursor(1, 0); + CharSequence toRight = ic.getTextAfterCursor(1, 0); + if (!TextUtils.isEmpty(toLeft) + && !isWordSeparator(toLeft.charAt(0)) + && !isSuggestedPunctuation(toLeft.charAt(0))) { + return true; + } + if (!TextUtils.isEmpty(toRight) + && !isWordSeparator(toRight.charAt(0)) + && !isSuggestedPunctuation(toRight.charAt(0))) { + return true; + } + return false; + } + + private boolean sameAsTextBeforeCursor(InputConnection ic, CharSequence text) { + CharSequence beforeText = ic.getTextBeforeCursor(text.length(), 0); + return TextUtils.equals(text, beforeText); + } + + public void revertLastWord(boolean deleteChar) { + final int length = mComposing.length(); + if (!mPredicting && length > 0) { + final InputConnection ic = getCurrentInputConnection(); + mPredicting = true; + mJustRevertedSeparator = ic.getTextBeforeCursor(1, 0); + if (deleteChar) ic.deleteSurroundingText(1, 0); + int toDelete = mCommittedLength; + CharSequence toTheLeft = ic.getTextBeforeCursor(mCommittedLength, 0); + if (toTheLeft != null && toTheLeft.length() > 0 + && isWordSeparator(toTheLeft.charAt(0))) { + toDelete--; + } + ic.deleteSurroundingText(toDelete, 0); + ic.setComposingText(mComposing, 1); + TextEntryState.backspace(); + postUpdateSuggestions(); + } else { + sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL); + mJustRevertedSeparator = null; + } + } + + protected String getWordSeparators() { + return mWordSeparators; + } + + public boolean isWordSeparator(int code) { + String separators = getWordSeparators(); + return separators.contains(String.valueOf((char)code)); + } + + private boolean isSentenceSeparator(int code) { + return mSentenceSeparators.contains(String.valueOf((char)code)); + } + + private void sendSpace() { + sendKeyChar((char)KEYCODE_SPACE); + updateShiftKeyState(getCurrentInputEditorInfo()); + //onKey(KEY_SPACE[0], KEY_SPACE); + } + + public boolean preferCapitalization() { + return mWord.isFirstCharCapitalized(); + } + + void toggleLanguage(boolean reset, boolean next) { + if (reset) { + mLanguageSwitcher.reset(); + } else { + if (next) { + mLanguageSwitcher.next(); + } else { + mLanguageSwitcher.prev(); + } + } + int currentKeyboardMode = mKeyboardSwitcher.getKeyboardMode(); + reloadKeyboards(); + mKeyboardSwitcher.makeKeyboards(true); + Log.d("KP2AK", "toggleLanguage -> setKM"); + mKeyboardSwitcher.setKeyboardMode(currentKeyboardMode, 0); + initSuggest(mLanguageSwitcher.getInputLanguage()); + mLanguageSwitcher.persist(); + updateShiftKeyState(getCurrentInputEditorInfo()); + } + + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, + String key) { + if (PREF_SELECTED_LANGUAGES.equals(key)) { + mLanguageSwitcher.loadLocales(sharedPreferences); + mRefreshKeyboardRequired = true; + } else if (PREF_RECORRECTION_ENABLED.equals(key)) { + mReCorrectionEnabled = sharedPreferences.getBoolean(PREF_RECORRECTION_ENABLED, + getResources().getBoolean(R.bool.default_recorrection_enabled)); + } + if (PREF_KP2A_REMEMBER_AUTO_FILL.equals(key)) + { + if (sharedPreferences.getBoolean(key, true) == false) + { + Log.d("KP2AK", "clearing saved field hints"); + SharedPreferences savedHints = getApplicationContext().getSharedPreferences(KP2A_SAVED_FIELD_HINTS, MODE_PRIVATE); + Editor edit = savedHints.edit(); + edit.clear(); + edit.commit(); + + } + } + } + + public void swipeRight() { + if (LatinKeyboardView.DEBUG_AUTO_PLAY) { + ClipboardManager cm = ((ClipboardManager)getSystemService(CLIPBOARD_SERVICE)); + CharSequence text = cm.getText(); + if (!TextUtils.isEmpty(text)) { + mKeyboardSwitcher.getInputView().startPlaying(text.toString()); + } + } + } + + public void swipeLeft() { + } + + public void swipeDown() { + handleClose(); + } + + public void swipeUp() { + //launchSettings(); + } + + public void onPress(int primaryCode) { + if (mKeyboardSwitcher.isVibrateAndSoundFeedbackRequired()) { + vibrate(); + playKeyClick(primaryCode); + } + final boolean distinctMultiTouch = mKeyboardSwitcher.hasDistinctMultitouch(); + if (distinctMultiTouch && primaryCode == Keyboard.KEYCODE_SHIFT) { + mShiftKeyState.onPress(); + handleShift(); + } else if (distinctMultiTouch && primaryCode == Keyboard.KEYCODE_MODE_CHANGE) { + changeKeyboardMode(); + mSymbolKeyState.onPress(); + mKeyboardSwitcher.setAutoModeSwitchStateMomentary(); + } else { + mShiftKeyState.onOtherKeyPressed(); + mSymbolKeyState.onOtherKeyPressed(); + } + } + + public void onRelease(int primaryCode) { + // Reset any drag flags in the keyboard + ((LatinKeyboard) mKeyboardSwitcher.getInputView().getKeyboard()).keyReleased(); + //vibrate(); + final boolean distinctMultiTouch = mKeyboardSwitcher.hasDistinctMultitouch(); + if (distinctMultiTouch && primaryCode == Keyboard.KEYCODE_SHIFT) { + if (mShiftKeyState.isMomentary()) + resetShift(); + mShiftKeyState.onRelease(); + } else if (distinctMultiTouch && primaryCode == Keyboard.KEYCODE_MODE_CHANGE) { + // Snap back to the previous keyboard mode if the user chords the mode change key and + // other key, then released the mode change key. + if (mKeyboardSwitcher.isInChordingAutoModeSwitchState()) + changeKeyboardMode(); + mSymbolKeyState.onRelease(); + } + } + + + + // receive ringer mode changes to detect silent mode + private BroadcastReceiver mReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + updateRingerMode(); + } + }; + + // update flags for silent mode + private void updateRingerMode() { + if (mAudioManager == null) { + mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); + } + if (mAudioManager != null) { + mSilentMode = (mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL); + } + } + + private void playKeyClick(int primaryCode) { + // if mAudioManager is null, we don't have the ringer state yet + // mAudioManager will be set by updateRingerMode + if (mAudioManager == null) { + if (mKeyboardSwitcher.getInputView() != null) { + updateRingerMode(); + } + } + if (mSoundOn && !mSilentMode) { + // FIXME: Volume and enable should come from UI settings + // FIXME: These should be triggered after auto-repeat logic + int sound = AudioManager.FX_KEYPRESS_STANDARD; + switch (primaryCode) { + case Keyboard.KEYCODE_DELETE: + sound = AudioManager.FX_KEYPRESS_DELETE; + break; + case KEYCODE_ENTER: + sound = AudioManager.FX_KEYPRESS_RETURN; + break; + case KEYCODE_SPACE: + sound = AudioManager.FX_KEYPRESS_SPACEBAR; + break; + } + mAudioManager.playSoundEffect(sound, FX_VOLUME); + } + } + + private void vibrate() { + if (!mVibrateOn) { + return; + } + if (mKeyboardSwitcher.getInputView() != null) { + mKeyboardSwitcher.getInputView().performHapticFeedback( + HapticFeedbackConstants.KEYBOARD_TAP, + HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); + } + } + + /* package */ void promoteToUserDictionary(String word, int frequency) { + //if (mUserDictionary.isValidWord(word)) return; + //mUserDictionary.addWord(word, frequency); + } + + /* package */ WordComposer getCurrentWord() { + return mWord; + } + + /* package */ boolean getPopupOn() { + return mPopupOn; + } + + private void updateCorrectionMode() { + mHasDictionary = mSuggest != null ? mSuggest.hasMainDictionary() : false; + mAutoCorrectOn = (mAutoCorrectEnabled || mQuickFixes) + && !mInputTypeNoAutoCorrect && mHasDictionary; + mCorrectionMode = (mAutoCorrectOn && mAutoCorrectEnabled) + ? Suggest.CORRECTION_FULL + : (mAutoCorrectOn ? Suggest.CORRECTION_BASIC : Suggest.CORRECTION_NONE); + mCorrectionMode = (mBigramSuggestionEnabled && mAutoCorrectOn && mAutoCorrectEnabled) + ? Suggest.CORRECTION_FULL_BIGRAM : mCorrectionMode; + if (mSuggest != null) { + mSuggest.setCorrectionMode(mCorrectionMode); + } + } + + private void updateAutoTextEnabled(Locale systemLocale) { + if (mSuggest == null) return; + boolean different = + !systemLocale.getLanguage().equalsIgnoreCase(mInputLocale.substring(0, 2)); + mSuggest.setAutoTextEnabled(!different && mQuickFixes); + } + + protected void launchSettings() { + launchSettings(LatinIMESettings.class); + } + + public void launchDebugSettings() { + launchSettings(LatinIMEDebugSettings.class); + } + + protected void launchSettings (Class settingsClass) { + handleClose(); + Intent intent = new Intent(); + intent.setClass(KP2AKeyboard.this, settingsClass); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + } + + private void loadSettings() { + // Get the settings preferences + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this); + mVibrateOn = sp.getBoolean(PREF_VIBRATE_ON, false); + mSoundOn = sp.getBoolean(PREF_SOUND_ON, false); + mPopupOn = sp.getBoolean(PREF_POPUP_ON, + mResources.getBoolean(R.bool.default_popup_preview)); + mAutoCap = sp.getBoolean(PREF_AUTO_CAP, true); + mQuickFixes = sp.getBoolean(PREF_QUICK_FIXES, true); + + mKp2aAutoFillOn = sp.getBoolean("kp2a_auto_fill", true); + mKp2aRememberAutoFill = sp.getBoolean(PREF_KP2A_REMEMBER_AUTO_FILL, true); + mKp2aEnableSimpleKeyboard = sp.getBoolean("kp2a_simple_keyboard", true); + mKp2aSwitchKeyboardOnSendGoDone = sp.getBoolean("kp2a_switch_on_sendgodone", false); + mKp2aLockOnSendGoDone = sp.getBoolean("kp2a_lock_on_sendgodone", false); + + + mShowSuggestions = sp.getBoolean(PREF_SHOW_SUGGESTIONS, true); + + mAutoCorrectEnabled = sp.getBoolean(PREF_AUTO_COMPLETE, + mResources.getBoolean(R.bool.enable_autocorrect)) & mShowSuggestions; + //mBigramSuggestionEnabled = sp.getBoolean( + // PREF_BIGRAM_SUGGESTIONS, true) & mShowSuggestions; + updateCorrectionMode(); + updateAutoTextEnabled(mResources.getConfiguration().locale); + mLanguageSwitcher.loadLocales(sp); + } + + private void initSuggestPuncList() { + mSuggestPuncList = new ArrayList(); + mSuggestPuncs = mResources.getString(R.string.suggested_punctuations); + if (mSuggestPuncs != null) { + for (int i = 0; i < mSuggestPuncs.length(); i++) { + mSuggestPuncList.add(mSuggestPuncs.subSequence(i, i + 1)); + } + } + } + + private boolean isSuggestedPunctuation(int code) { + return mSuggestPuncs.contains(String.valueOf((char)code)); + } + + private void showOptionsMenu() { + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setCancelable(true); + builder.setIcon(R.drawable.ic_dialog_keyboard); + builder.setNegativeButton(android.R.string.cancel, null); + CharSequence itemSettings = getString(R.string.english_ime_settings); + CharSequence itemInputMethod = getString(R.string.selectInputMethod); + builder.setItems(new CharSequence[] { + itemInputMethod, itemSettings}, + new DialogInterface.OnClickListener() { + + public void onClick(DialogInterface di, int position) { + di.dismiss(); + switch (position) { + case POS_SETTINGS: + launchSettings(); + break; + case POS_METHOD: + ((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE)) + .showInputMethodPicker(); + break; + } + } + }); + builder.setTitle(mResources.getString(R.string.english_ime_input_options)); + mOptionsDialog = builder.create(); + Window window = mOptionsDialog.getWindow(); + WindowManager.LayoutParams lp = window.getAttributes(); + lp.token = mKeyboardSwitcher.getInputView().getWindowToken(); + lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; + window.setAttributes(lp); + window.addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); + mOptionsDialog.show(); + } + + public void changeKeyboardMode() { + mKeyboardSwitcher.toggleSymbols(); + if (mCapsLock && mKeyboardSwitcher.isAlphabetMode()) { + mKeyboardSwitcher.setShiftLocked(mCapsLock); + } + + updateShiftKeyState(getCurrentInputEditorInfo()); + } + + public static ArrayList newArrayList(E... elements) { + int capacity = (elements.length * 110) / 100 + 5; + ArrayList list = new ArrayList(capacity); + Collections.addAll(list, elements); + return list; + } + + @Override + protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) { + super.dump(fd, fout, args); + + final Printer p = new PrintWriterPrinter(fout); + p.println("LatinIME state :"); + p.println(" Keyboard mode = " + mKeyboardSwitcher.getKeyboardMode()); + p.println(" mCapsLock=" + mCapsLock); + p.println(" mComposing=" + mComposing.toString()); + p.println(" mPredictionOn=" + mPredictionOn); + p.println(" mCorrectionMode=" + mCorrectionMode); + p.println(" mPredicting=" + mPredicting); + p.println(" mAutoCorrectOn=" + mAutoCorrectOn); + p.println(" mAutoSpace=" + mAutoSpace); + p.println(" mCompletionOn=" + mCompletionOn); + p.println(" TextEntryState.state=" + TextEntryState.getState()); + p.println(" mSoundOn=" + mSoundOn); + p.println(" mVibrateOn=" + mVibrateOn); + p.println(" mPopupOn=" + mPopupOn); + } + + // Characters per second measurement + + private long mLastCpsTime; + private static final int CPS_BUFFER_SIZE = 16; + private long[] mCpsIntervals = new long[CPS_BUFFER_SIZE]; + private int mCpsIndex; + + private void measureCps() { + long now = System.currentTimeMillis(); + if (mLastCpsTime == 0) mLastCpsTime = now - 100; // Initial + mCpsIntervals[mCpsIndex] = now - mLastCpsTime; + mLastCpsTime = now; + mCpsIndex = (mCpsIndex + 1) % CPS_BUFFER_SIZE; + long total = 0; + for (int i = 0; i < CPS_BUFFER_SIZE; i++) total += mCpsIntervals[i]; + System.out.println("CPS = " + ((CPS_BUFFER_SIZE * 1000f) / total)); + } + + public void onAutoCompletionStateChanged(boolean isAutoCompletion) { + mKeyboardSwitcher.onAutoCompletionStateChanged(isAutoCompletion); + } +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/KeyDetector.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/KeyDetector.java new file mode 100644 index 00000000..d43e685b --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/KeyDetector.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 keepass2android.softkeyboard; + +import android.inputmethodservice.Keyboard; +import android.inputmethodservice.Keyboard.Key; + +import java.util.Arrays; +import java.util.List; + +abstract class KeyDetector { + protected Keyboard mKeyboard; + + private Key[] mKeys; + + protected int mCorrectionX; + + protected int mCorrectionY; + + protected boolean mProximityCorrectOn; + + protected int mProximityThresholdSquare; + + public Key[] setKeyboard(Keyboard keyboard, float correctionX, float correctionY) { + if (keyboard == null) + throw new NullPointerException(); + mCorrectionX = (int)correctionX; + mCorrectionY = (int)correctionY; + mKeyboard = keyboard; + List keys = mKeyboard.getKeys(); + Key[] array = keys.toArray(new Key[keys.size()]); + mKeys = array; + return array; + } + + protected int getTouchX(int x) { + return x + mCorrectionX; + } + + protected int getTouchY(int y) { + return y + mCorrectionY; + } + + protected Key[] getKeys() { + if (mKeys == null) + throw new IllegalStateException("keyboard isn't set"); + // mKeyboard is guaranteed not to be null at setKeybaord() method if mKeys is not null + return mKeys; + } + + public void setProximityCorrectionEnabled(boolean enabled) { + mProximityCorrectOn = enabled; + } + + public boolean isProximityCorrectionEnabled() { + return mProximityCorrectOn; + } + + public void setProximityThreshold(int threshold) { + mProximityThresholdSquare = threshold * threshold; + } + + /** + * Allocates array that can hold all key indices returned by {@link #getKeyIndexAndNearbyCodes} + * method. The maximum size of the array should be computed by {@link #getMaxNearbyKeys}. + * + * @return Allocates and returns an array that can hold all key indices returned by + * {@link #getKeyIndexAndNearbyCodes} method. All elements in the returned array are + * initialized by {@link keepass2android.softkeyboard.LatinKeyboardView.NOT_A_KEY} + * value. + */ + public int[] newCodeArray() { + int[] codes = new int[getMaxNearbyKeys()]; + Arrays.fill(codes, LatinKeyboardBaseView.NOT_A_KEY); + return codes; + } + + /** + * Computes maximum size of the array that can contain all nearby key indices returned by + * {@link #getKeyIndexAndNearbyCodes}. + * + * @return Returns maximum size of the array that can contain all nearby key indices returned + * by {@link #getKeyIndexAndNearbyCodes}. + */ + abstract protected int getMaxNearbyKeys(); + + /** + * Finds all possible nearby key indices around a touch event point and returns the nearest key + * index. The algorithm to determine the nearby keys depends on the threshold set by + * {@link #setProximityThreshold(int)} and the mode set by + * {@link #setProximityCorrectionEnabled(boolean)}. + * + * @param x The x-coordinate of a touch point + * @param y The y-coordinate of a touch point + * @param allKeys All nearby key indices are returned in this array + * @return The nearest key index + */ + abstract public int getKeyIndexAndNearbyCodes(int x, int y, int[] allKeys); +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/KeyboardSwitcher.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/KeyboardSwitcher.java new file mode 100644 index 00000000..afed1204 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/KeyboardSwitcher.java @@ -0,0 +1,591 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package keepass2android.softkeyboard; + +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.preference.PreferenceManager; +import android.util.Log; +import android.view.InflateException; + +import java.lang.ref.SoftReference; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Locale; + +public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceChangeListener { + + public static final int MODE_NONE = 0; + public static final int MODE_TEXT = 1; + public static final int MODE_SYMBOLS = 2; + public static final int MODE_PHONE = 3; + public static final int MODE_URL = 4; + public static final int MODE_EMAIL = 5; + public static final int MODE_IM = 6; + public static final int MODE_WEB = 7; + public static final int MODE_KP2A = 8; + + // Main keyboard layouts without the settings key + public static final int KEYBOARDMODE_NORMAL = R.id.mode_normal; + public static final int KEYBOARDMODE_URL = R.id.mode_url; + public static final int KEYBOARDMODE_EMAIL = R.id.mode_email; + public static final int KEYBOARDMODE_IM = R.id.mode_im; + public static final int KEYBOARDMODE_WEB = R.id.mode_webentry; + // Main keyboard layouts with the settings key + public static final int KEYBOARDMODE_NORMAL_WITH_SETTINGS_KEY = + R.id.mode_normal_with_settings_key; + public static final int KEYBOARDMODE_URL_WITH_SETTINGS_KEY = + R.id.mode_url_with_settings_key; + public static final int KEYBOARDMODE_EMAIL_WITH_SETTINGS_KEY = + R.id.mode_email_with_settings_key; + public static final int KEYBOARDMODE_IM_WITH_SETTINGS_KEY = + R.id.mode_im_with_settings_key; + public static final int KEYBOARDMODE_WEB_WITH_SETTINGS_KEY = + R.id.mode_webentry_with_settings_key; + + // Symbols keyboard layout without the settings key + public static final int KEYBOARDMODE_SYMBOLS = R.id.mode_symbols; + // Symbols keyboard layout with the settings key + public static final int KEYBOARDMODE_SYMBOLS_WITH_SETTINGS_KEY = + R.id.mode_symbols_with_settings_key; + + public static final String DEFAULT_LAYOUT_ID = "4"; + public static final String PREF_KEYBOARD_LAYOUT = "pref_keyboard_layout_20100902"; + private static final int[] THEMES = new int [] { + R.layout.input_basic, R.layout.input_basic_highcontrast, R.layout.input_stone_normal, + R.layout.input_stone_bold, R.layout.input_gingerbread}; + + // Ids for each characters' color in the keyboard + private static final int CHAR_THEME_COLOR_WHITE = 0; + private static final int CHAR_THEME_COLOR_BLACK = 1; + + // Tables which contains resource ids for each character theme color + private static final int[] KBD_PHONE = new int[] {R.xml.kbd_phone, R.xml.kbd_phone_black}; + private static final int[] KBD_PHONE_SYMBOLS = new int[] { + R.xml.kbd_phone_symbols, R.xml.kbd_phone_symbols_black}; + private static final int[] KBD_SYMBOLS = new int[] { + R.xml.kbd_symbols, R.xml.kbd_symbols_black}; + private static final int[] KBD_SYMBOLS_SHIFT = new int[] { + R.xml.kbd_symbols_shift, R.xml.kbd_symbols_shift_black}; + private static final int[] KBD_QWERTY = new int[] {R.xml.kbd_qwerty, R.xml.kbd_qwerty_black}; + + private static final int[] KBD_KP2A = new int[] {R.xml.kbd_kp2a, R.xml.kbd_kp2a_black}; + + private LatinKeyboardView mInputView; + private static final int[] ALPHABET_MODES = { + KEYBOARDMODE_NORMAL, + KEYBOARDMODE_URL, + KEYBOARDMODE_EMAIL, + KEYBOARDMODE_IM, + KEYBOARDMODE_WEB, + KEYBOARDMODE_NORMAL_WITH_SETTINGS_KEY, + KEYBOARDMODE_URL_WITH_SETTINGS_KEY, + KEYBOARDMODE_EMAIL_WITH_SETTINGS_KEY, + KEYBOARDMODE_IM_WITH_SETTINGS_KEY, + KEYBOARDMODE_WEB_WITH_SETTINGS_KEY }; + + private KP2AKeyboard mInputMethodService; + + private KeyboardId mSymbolsId; + private KeyboardId mSymbolsShiftedId; + + private KeyboardId mCurrentId; + private final HashMap> mKeyboards = + new HashMap>(); + + private int mMode = MODE_NONE; /** One of the MODE_XXX values */ + private int mImeOptions; + private boolean mIsSymbols; + /** mIsAutoCompletionActive indicates that auto completed word will be input instead of + * what user actually typed. */ + private boolean mIsAutoCompletionActive; + private boolean mPreferSymbols; + + private static final int AUTO_MODE_SWITCH_STATE_ALPHA = 0; + private static final int AUTO_MODE_SWITCH_STATE_SYMBOL_BEGIN = 1; + private static final int AUTO_MODE_SWITCH_STATE_SYMBOL = 2; + // The following states are used only on the distinct multi-touch panel devices. + private static final int AUTO_MODE_SWITCH_STATE_MOMENTARY = 3; + private static final int AUTO_MODE_SWITCH_STATE_CHORDING = 4; + private int mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_ALPHA; + + // Indicates whether or not we have the settings key + private boolean mHasSettingsKey; + private static final int SETTINGS_KEY_MODE_AUTO = R.string.settings_key_mode_auto; + private static final int SETTINGS_KEY_MODE_ALWAYS_SHOW = R.string.settings_key_mode_always_show; + // NOTE: No need to have SETTINGS_KEY_MODE_ALWAYS_HIDE here because it's not being referred to + // in the source code now. + // Default is SETTINGS_KEY_MODE_AUTO. + private static final int DEFAULT_SETTINGS_KEY_MODE = SETTINGS_KEY_MODE_AUTO; + + private int mLastDisplayWidth; + private LanguageSwitcher mLanguageSwitcher; + private Locale mInputLocale; + + private int mLayoutId; + + private static final KeyboardSwitcher sInstance = new KeyboardSwitcher(); + + public static KeyboardSwitcher getInstance() { + return sInstance; + } + + private KeyboardSwitcher() { + // Intentional empty constructor for singleton. + } + + public static void init(KP2AKeyboard ims) { + sInstance.mInputMethodService = ims; + + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ims); + sInstance.mLayoutId = Integer.valueOf( + prefs.getString(PREF_KEYBOARD_LAYOUT, DEFAULT_LAYOUT_ID)); + sInstance.updateSettingsKeyState(prefs); + prefs.registerOnSharedPreferenceChangeListener(sInstance); + + sInstance.mSymbolsId = sInstance.makeSymbolsId(); + sInstance.mSymbolsShiftedId = sInstance.makeSymbolsShiftedId(); + } + + /** + * Sets the input locale, when there are multiple locales for input. + * If no locale switching is required, then the locale should be set to null. + * @param locale the current input locale, or null for default locale with no locale + * button. + */ + public void setLanguageSwitcher(LanguageSwitcher languageSwitcher) { + mLanguageSwitcher = languageSwitcher; + mInputLocale = mLanguageSwitcher.getInputLocale(); + } + + private KeyboardId makeSymbolsId() { + return new KeyboardId(KBD_SYMBOLS[getCharColorId()], mHasSettingsKey ? + KEYBOARDMODE_SYMBOLS_WITH_SETTINGS_KEY : KEYBOARDMODE_SYMBOLS, + false); + } + + private KeyboardId makeSymbolsShiftedId() { + return new KeyboardId(KBD_SYMBOLS_SHIFT[getCharColorId()], mHasSettingsKey ? + KEYBOARDMODE_SYMBOLS_WITH_SETTINGS_KEY : KEYBOARDMODE_SYMBOLS, + false); + } + + public void makeKeyboards(boolean forceCreate) { + mSymbolsId = makeSymbolsId(); + mSymbolsShiftedId = makeSymbolsShiftedId(); + + 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 = mInputMethodService.getMaxWidth(); + if (displayWidth == mLastDisplayWidth) return; + mLastDisplayWidth = displayWidth; + if (!forceCreate) mKeyboards.clear(); + } + + /** + * Represents the parameters necessary to construct a new LatinKeyboard, + * which also serve as a unique identifier for each keyboard type. + */ + private static class KeyboardId { + // TODO: should have locale and portrait/landscape orientation? + public final int mXml; + public final int mKeyboardMode; /** A KEYBOARDMODE_XXX value */ + public final boolean mEnableShiftLock; + + private final int mHashCode; + + public KeyboardId(int xml, int mode, boolean enableShiftLock) { + this.mXml = xml; + this.mKeyboardMode = mode; + this.mEnableShiftLock = enableShiftLock; + + this.mHashCode = Arrays.hashCode(new Object[] { + xml, mode, enableShiftLock + }); + } + + public KeyboardId(int xml) { + this(xml, 0, false); + } + + @Override + public boolean equals(Object other) { + return other instanceof KeyboardId && equals((KeyboardId) other); + } + + private boolean equals(KeyboardId other) { + return other.mXml == this.mXml + && other.mKeyboardMode == this.mKeyboardMode + && other.mEnableShiftLock == this.mEnableShiftLock + ; + } + + @Override + public int hashCode() { + return mHashCode; + } + } + + + public void setKeyboardMode(int mode, int imeOptions) { + Log.d("KP2AK", "Switcher.SetKeyboardMode: " + mode); + mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_ALPHA; + mPreferSymbols = mode == MODE_SYMBOLS; + if (mode == MODE_SYMBOLS) { + mode = MODE_TEXT; + } + try { + setKeyboardMode(mode, imeOptions, mPreferSymbols); + } catch (RuntimeException e) { + LatinImeLogger.logOnException(mode + "," + imeOptions + "," + mPreferSymbols, e); + } + } + + private void setKeyboardMode(int mode, int imeOptions, boolean isSymbols) { + if (mInputView == null) return; + mMode = mode; + mImeOptions = imeOptions; + mIsSymbols = isSymbols; + + mInputView.setPreviewEnabled(mInputMethodService.getPopupOn()); + KeyboardId id = getKeyboardId(mode, imeOptions, isSymbols); + LatinKeyboard keyboard = null; + keyboard = getKeyboard(id); + + if (mode == MODE_PHONE) { + mInputView.setPhoneKeyboard(keyboard); + } + + mCurrentId = id; + mInputView.setKeyboard(keyboard); + keyboard.setShifted(false); + keyboard.setShiftLocked(keyboard.isShiftLocked()); + keyboard.setImeOptions(mInputMethodService.getResources(), mMode, imeOptions); + keyboard.setColorOfSymbolIcons(mIsAutoCompletionActive, isBlackSym()); + // Update the settings key state because number of enabled IMEs could have been changed + updateSettingsKeyState(PreferenceManager.getDefaultSharedPreferences(mInputMethodService)); + } + + private LatinKeyboard getKeyboard(KeyboardId id) { + SoftReference ref = mKeyboards.get(id); + LatinKeyboard keyboard = (ref == null) ? null : ref.get(); + if (keyboard == null) { + Resources orig = mInputMethodService.getResources(); + Configuration conf = orig.getConfiguration(); + Locale saveLocale = conf.locale; + conf.locale = mInputLocale; + orig.updateConfiguration(conf, null); + keyboard = new LatinKeyboard(mInputMethodService, id.mXml, id.mKeyboardMode); + keyboard.setLanguageSwitcher(mLanguageSwitcher, mIsAutoCompletionActive, isBlackSym()); + + if (id.mEnableShiftLock) { + keyboard.enableShiftLock(); + } + mKeyboards.put(id, new SoftReference(keyboard)); + + conf.locale = saveLocale; + orig.updateConfiguration(conf, null); + } + return keyboard; + } + + private KeyboardId getKeyboardId(int mode, int imeOptions, boolean isSymbols) { + int charColorId = getCharColorId(); + if (isSymbols) { + if (mode == MODE_PHONE) { + return new KeyboardId(KBD_PHONE_SYMBOLS[charColorId]); + } else { + return new KeyboardId(KBD_SYMBOLS[charColorId], mHasSettingsKey ? + KEYBOARDMODE_SYMBOLS_WITH_SETTINGS_KEY : KEYBOARDMODE_SYMBOLS, + false); + } + } + // TODO: generalize for any KeyboardId + int keyboardRowsResId = KBD_QWERTY[charColorId]; + + switch (mode) { + case MODE_KP2A: + return new KeyboardId(KBD_KP2A[charColorId]); + case MODE_NONE: + LatinImeLogger.logOnWarning( + "getKeyboardId:" + mode + "," + imeOptions + "," + isSymbols); + /* fall through */ + case MODE_TEXT: + return new KeyboardId(keyboardRowsResId, mHasSettingsKey ? + KEYBOARDMODE_NORMAL_WITH_SETTINGS_KEY : KEYBOARDMODE_NORMAL, + true); + case MODE_SYMBOLS: + return new KeyboardId(KBD_SYMBOLS[charColorId], mHasSettingsKey ? + KEYBOARDMODE_SYMBOLS_WITH_SETTINGS_KEY : KEYBOARDMODE_SYMBOLS, + false); + case MODE_PHONE: + return new KeyboardId(KBD_PHONE[charColorId]); + case MODE_URL: + return new KeyboardId(keyboardRowsResId, mHasSettingsKey ? + KEYBOARDMODE_URL_WITH_SETTINGS_KEY : KEYBOARDMODE_URL, true); + case MODE_EMAIL: + return new KeyboardId(keyboardRowsResId, mHasSettingsKey ? + KEYBOARDMODE_EMAIL_WITH_SETTINGS_KEY : KEYBOARDMODE_EMAIL, true); + case MODE_IM: + return new KeyboardId(keyboardRowsResId, mHasSettingsKey ? + KEYBOARDMODE_IM_WITH_SETTINGS_KEY : KEYBOARDMODE_IM, true); + case MODE_WEB: + return new KeyboardId(keyboardRowsResId, mHasSettingsKey ? + KEYBOARDMODE_WEB_WITH_SETTINGS_KEY : KEYBOARDMODE_WEB, true); + } + return null; + } + + public int getKeyboardMode() { + return mMode; + } + + public boolean isAlphabetMode() { + if (mCurrentId == null) { + return false; + } + int currentMode = mCurrentId.mKeyboardMode; + for (Integer mode : ALPHABET_MODES) { + if (currentMode == mode) { + return true; + } + } + return false; + } + + public void setShifted(boolean shifted) { + if (mInputView != null) { + mInputView.setShifted(shifted); + } + } + + public void setShiftLocked(boolean shiftLocked) { + if (mInputView != null) { + mInputView.setShiftLocked(shiftLocked); + } + } + + public void toggleShift() { + if (isAlphabetMode()) + return; + if (mCurrentId.equals(mSymbolsId) || !mCurrentId.equals(mSymbolsShiftedId)) { + LatinKeyboard symbolsShiftedKeyboard = getKeyboard(mSymbolsShiftedId); + mCurrentId = mSymbolsShiftedId; + mInputView.setKeyboard(symbolsShiftedKeyboard); + // Symbol shifted keyboard has an ALT key that has a caps lock style indicator. To + // enable the indicator, we need to call enableShiftLock() and setShiftLocked(true). + // Thus we can keep the ALT key's Key.on value true while LatinKey.onRelease() is + // called. + symbolsShiftedKeyboard.enableShiftLock(); + symbolsShiftedKeyboard.setShiftLocked(true); + symbolsShiftedKeyboard.setImeOptions(mInputMethodService.getResources(), + mMode, mImeOptions); + } else { + LatinKeyboard symbolsKeyboard = getKeyboard(mSymbolsId); + mCurrentId = mSymbolsId; + mInputView.setKeyboard(symbolsKeyboard); + // Symbol keyboard has an ALT key that has a caps lock style indicator. To disable the + // indicator, we need to call enableShiftLock() and setShiftLocked(false). + symbolsKeyboard.enableShiftLock(); + symbolsKeyboard.setShifted(false); + symbolsKeyboard.setImeOptions(mInputMethodService.getResources(), mMode, mImeOptions); + } + } + + public void onCancelInput() { + // Snap back to the previous keyboard mode if the user cancels sliding input. + if (mAutoModeSwitchState == AUTO_MODE_SWITCH_STATE_MOMENTARY && getPointerCount() == 1) + mInputMethodService.changeKeyboardMode(); + } + + public void toggleSymbols() { + setKeyboardMode(mMode, mImeOptions, !mIsSymbols); + if (mIsSymbols && !mPreferSymbols) { + mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_SYMBOL_BEGIN; + } else { + mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_ALPHA; + } + } + + public boolean hasDistinctMultitouch() { + return mInputView != null && mInputView.hasDistinctMultitouch(); + } + + public void setAutoModeSwitchStateMomentary() { + mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_MOMENTARY; + } + + public boolean isInMomentaryAutoModeSwitchState() { + return mAutoModeSwitchState == AUTO_MODE_SWITCH_STATE_MOMENTARY; + } + + public boolean isInChordingAutoModeSwitchState() { + return mAutoModeSwitchState == AUTO_MODE_SWITCH_STATE_CHORDING; + } + + public boolean isVibrateAndSoundFeedbackRequired() { + return mInputView != null && !mInputView.isInSlidingKeyInput(); + } + + private int getPointerCount() { + return mInputView == null ? 0 : mInputView.getPointerCount(); + } + + /** + * Updates state machine to figure out when to automatically snap back to the previous mode. + */ + public void onKey(int key) { + // Switch back to alpha mode if user types one or more non-space/enter characters + // followed by a space/enter + switch (mAutoModeSwitchState) { + case AUTO_MODE_SWITCH_STATE_MOMENTARY: + // Only distinct multi touch devices can be in this state. + // On non-distinct multi touch devices, mode change key is handled by {@link onKey}, + // not by {@link onPress} and {@link onRelease}. So, on such devices, + // {@link mAutoModeSwitchState} starts from {@link AUTO_MODE_SWITCH_STATE_SYMBOL_BEGIN}, + // or {@link AUTO_MODE_SWITCH_STATE_ALPHA}, not from + // {@link AUTO_MODE_SWITCH_STATE_MOMENTARY}. + if (key == LatinKeyboard.KEYCODE_MODE_CHANGE) { + // Detected only the mode change key has been pressed, and then released. + if (mIsSymbols) { + mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_SYMBOL_BEGIN; + } else { + mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_ALPHA; + } + } else if (getPointerCount() == 1) { + // Snap back to the previous keyboard mode if the user pressed the mode change key + // and slid to other key, then released the finger. + // If the user cancels the sliding input, snapping back to the previous keyboard + // mode is handled by {@link #onCancelInput}. + mInputMethodService.changeKeyboardMode(); + } else { + // Chording input is being started. The keyboard mode will be snapped back to the + // previous mode in {@link onReleaseSymbol} when the mode change key is released. + mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_CHORDING; + } + break; + case AUTO_MODE_SWITCH_STATE_SYMBOL_BEGIN: + if (key != KP2AKeyboard.KEYCODE_SPACE && key != KP2AKeyboard.KEYCODE_ENTER && key >= 0) { + mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_SYMBOL; + } + break; + case AUTO_MODE_SWITCH_STATE_SYMBOL: + // Snap back to alpha keyboard mode if user types one or more non-space/enter + // characters followed by a space/enter. + if (key == KP2AKeyboard.KEYCODE_ENTER || key == KP2AKeyboard.KEYCODE_SPACE) { + mInputMethodService.changeKeyboardMode(); + } + break; + } + } + + public LatinKeyboardView getInputView() { + return mInputView; + } + + public void recreateInputView() { + changeLatinKeyboardView(mLayoutId, true); + } + + private void changeLatinKeyboardView(int newLayout, boolean forceReset) { + if (mLayoutId != newLayout || mInputView == null || forceReset) { + if (mInputView != null) { + mInputView.closing(); + } + if (THEMES.length <= newLayout) { + newLayout = Integer.valueOf(DEFAULT_LAYOUT_ID); + } + + LatinIMEUtil.GCUtils.getInstance().reset(); + boolean tryGC = true; + for (int i = 0; i < LatinIMEUtil.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) { + try { + mInputView = (LatinKeyboardView) mInputMethodService.getLayoutInflater( + ).inflate(THEMES[newLayout], null); + tryGC = false; + } catch (OutOfMemoryError e) { + tryGC = LatinIMEUtil.GCUtils.getInstance().tryGCOrWait( + mLayoutId + "," + newLayout, e); + } catch (InflateException e) { + tryGC = LatinIMEUtil.GCUtils.getInstance().tryGCOrWait( + mLayoutId + "," + newLayout, e); + } + } + mInputView.setOnKeyboardActionListener(mInputMethodService); + mLayoutId = newLayout; + } + mInputMethodService.mHandler.post(new Runnable() { + public void run() { + if (mInputView != null) { + mInputMethodService.setInputView(mInputView); + } + mInputMethodService.updateInputViewShown(); + }}); + } + + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + if (PREF_KEYBOARD_LAYOUT.equals(key)) { + changeLatinKeyboardView( + Integer.valueOf(sharedPreferences.getString(key, DEFAULT_LAYOUT_ID)), false); + } else if (LatinIMESettings.PREF_SETTINGS_KEY.equals(key)) { + updateSettingsKeyState(sharedPreferences); + recreateInputView(); + } + } + + public boolean isBlackSym () { + if (mInputView != null && mInputView.getSymbolColorScheme() == 1) { + return true; + } + return false; + } + + private int getCharColorId () { + if (isBlackSym()) { + return CHAR_THEME_COLOR_BLACK; + } else { + return CHAR_THEME_COLOR_WHITE; + } + } + + public void onAutoCompletionStateChanged(boolean isAutoCompletion) { + if (isAutoCompletion != mIsAutoCompletionActive) { + LatinKeyboardView keyboardView = getInputView(); + mIsAutoCompletionActive = isAutoCompletion; + keyboardView.invalidateKey(((LatinKeyboard) keyboardView.getKeyboard()) + .onAutoCompletionStateChanged(isAutoCompletion)); + } + } + + private void updateSettingsKeyState(SharedPreferences prefs) { + Resources resources = mInputMethodService.getResources(); + final String settingsKeyMode = prefs.getString(LatinIMESettings.PREF_SETTINGS_KEY, + resources.getString(DEFAULT_SETTINGS_KEY_MODE)); + // We show the settings key when 1) SETTINGS_KEY_MODE_ALWAYS_SHOW or + // 2) SETTINGS_KEY_MODE_AUTO and there are two or more enabled IMEs on the system + if (settingsKeyMode.equals(resources.getString(SETTINGS_KEY_MODE_ALWAYS_SHOW)) + || (settingsKeyMode.equals(resources.getString(SETTINGS_KEY_MODE_AUTO)) + && LatinIMEUtil.hasMultipleEnabledIMEs(mInputMethodService))) { + mHasSettingsKey = true; + } else { + mHasSettingsKey = false; + } + } +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/LanguageSwitcher.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/LanguageSwitcher.java new file mode 100644 index 00000000..844b7c4c --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/LanguageSwitcher.java @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 keepass2android.softkeyboard; + +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; +import android.preference.PreferenceManager; +import android.text.TextUtils; + +import java.util.Locale; + +/** + * Keeps track of list of selected input languages and the current + * input language that the user has selected. + */ +public class LanguageSwitcher { + + private Locale[] mLocales; + private KP2AKeyboard mIme; + private String[] mSelectedLanguageArray; + private String mSelectedLanguages; + private int mCurrentIndex = 0; + private String mDefaultInputLanguage; + private Locale mDefaultInputLocale; + private Locale mSystemLocale; + + public LanguageSwitcher(KP2AKeyboard ime) { + mIme = ime; + mLocales = new Locale[0]; + } + + public Locale[] getLocales() { + return mLocales; + } + + public int getLocaleCount() { + return mLocales.length; + } + + /** + * Loads the currently selected input languages from shared preferences. + * @param sp + * @return whether there was any change + */ + public boolean loadLocales(SharedPreferences sp) { + String selectedLanguages = sp.getString(KP2AKeyboard.PREF_SELECTED_LANGUAGES, null); + String currentLanguage = sp.getString(KP2AKeyboard.PREF_INPUT_LANGUAGE, null); + if (selectedLanguages == null || selectedLanguages.length() < 1) { + loadDefaults(); + if (mLocales.length == 0) { + return false; + } + mLocales = new Locale[0]; + return true; + } + if (selectedLanguages.equals(mSelectedLanguages)) { + return false; + } + mSelectedLanguageArray = selectedLanguages.split(","); + mSelectedLanguages = selectedLanguages; // Cache it for comparison later + constructLocales(); + mCurrentIndex = 0; + if (currentLanguage != null) { + // Find the index + mCurrentIndex = 0; + for (int i = 0; i < mLocales.length; i++) { + if (mSelectedLanguageArray[i].equals(currentLanguage)) { + mCurrentIndex = i; + break; + } + } + // If we didn't find the index, use the first one + } + return true; + } + + private void loadDefaults() { + mDefaultInputLocale = mIme.getResources().getConfiguration().locale; + String country = mDefaultInputLocale.getCountry(); + mDefaultInputLanguage = mDefaultInputLocale.getLanguage() + + (TextUtils.isEmpty(country) ? "" : "_" + country); + } + + private void constructLocales() { + mLocales = new Locale[mSelectedLanguageArray.length]; + for (int i = 0; i < mLocales.length; i++) { + final String lang = mSelectedLanguageArray[i]; + mLocales[i] = new Locale(lang.substring(0, 2), + lang.length() > 4 ? lang.substring(3, 5) : ""); + } + } + + /** + * Returns the currently selected input language code, or the display language code if + * no specific locale was selected for input. + */ + public String getInputLanguage() { + if (getLocaleCount() == 0) return mDefaultInputLanguage; + + return mSelectedLanguageArray[mCurrentIndex]; + } + + /** + * Returns the list of enabled language codes. + */ + public String[] getEnabledLanguages() { + return mSelectedLanguageArray; + } + + /** + * Returns the currently selected input locale, or the display locale if no specific + * locale was selected for input. + * @return + */ + public Locale getInputLocale() { + if (getLocaleCount() == 0) return mDefaultInputLocale; + + return mLocales[mCurrentIndex]; + } + + /** + * Returns the next input locale in the list. Wraps around to the beginning of the + * list if we're at the end of the list. + * @return + */ + public Locale getNextInputLocale() { + if (getLocaleCount() == 0) return mDefaultInputLocale; + + return mLocales[(mCurrentIndex + 1) % mLocales.length]; + } + + /** + * Sets the system locale (display UI) used for comparing with the input language. + * @param locale the locale of the system + */ + public void setSystemLocale(Locale locale) { + mSystemLocale = locale; + } + + /** + * Returns the system locale. + * @return the system locale + */ + public Locale getSystemLocale() { + return mSystemLocale; + } + + /** + * Returns the previous input locale in the list. Wraps around to the end of the + * list if we're at the beginning of the list. + * @return + */ + public Locale getPrevInputLocale() { + if (getLocaleCount() == 0) return mDefaultInputLocale; + + return mLocales[(mCurrentIndex - 1 + mLocales.length) % mLocales.length]; + } + + public void reset() { + mCurrentIndex = 0; + } + + public void next() { + mCurrentIndex++; + if (mCurrentIndex >= mLocales.length) mCurrentIndex = 0; // Wrap around + } + + public void prev() { + mCurrentIndex--; + if (mCurrentIndex < 0) mCurrentIndex = mLocales.length - 1; // Wrap around + } + + public void persist() { + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mIme); + Editor editor = sp.edit(); + editor.putString(KP2AKeyboard.PREF_INPUT_LANGUAGE, getInputLanguage()); + SharedPreferencesCompat.apply(editor); + } + + static String toTitleCase(String s, Locale locale) { + if (s.length() == 0) { + return s; + } + + return s.toUpperCase(locale).charAt(0) + s.substring(1); + } +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/LatinIMEBackupAgent.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/LatinIMEBackupAgent.java new file mode 100644 index 00000000..58618cef --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/LatinIMEBackupAgent.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package keepass2android.softkeyboard; + +import android.app.backup.BackupAgentHelper; +import android.app.backup.SharedPreferencesBackupHelper; + +/** + * Backs up the Latin IME shared preferences. + */ +public class LatinIMEBackupAgent extends BackupAgentHelper { + + @Override + public void onCreate() { + addHelper("shared_pref", new SharedPreferencesBackupHelper(this, + getPackageName() + "_preferences")); + } +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/LatinIMEDebugSettings.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/LatinIMEDebugSettings.java new file mode 100644 index 00000000..789030e7 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/LatinIMEDebugSettings.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package keepass2android.softkeyboard; + +import android.content.SharedPreferences; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager.NameNotFoundException; +import android.os.Bundle; +import android.preference.CheckBoxPreference; +import android.preference.PreferenceActivity; +import android.util.Log; + +public class LatinIMEDebugSettings extends PreferenceActivity + implements SharedPreferences.OnSharedPreferenceChangeListener { + + private static final String TAG = "LatinIMEDebugSettings"; + private static final String DEBUG_MODE_KEY = "debug_mode"; + + private CheckBoxPreference mDebugMode; + + @Override + protected void onCreate(Bundle icicle) { + super.onCreate(icicle); + addPreferencesFromResource(R.xml.prefs_for_debug); + SharedPreferences prefs = getPreferenceManager().getSharedPreferences(); + prefs.registerOnSharedPreferenceChangeListener(this); + + mDebugMode = (CheckBoxPreference) findPreference(DEBUG_MODE_KEY); + updateDebugMode(); + } + + public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { + if (key.equals(DEBUG_MODE_KEY)) { + if (mDebugMode != null) { + mDebugMode.setChecked(prefs.getBoolean(DEBUG_MODE_KEY, false)); + updateDebugMode(); + } + } + } + + private void updateDebugMode() { + if (mDebugMode == null) { + return; + } + boolean isDebugMode = mDebugMode.isChecked(); + String version = ""; + try { + PackageInfo info = getPackageManager().getPackageInfo(getPackageName(), 0); + version = "Version " + info.versionName; + } catch (NameNotFoundException e) { + Log.e(TAG, "Could not find version info."); + } + if (!isDebugMode) { + mDebugMode.setTitle(version); + mDebugMode.setSummary(""); + } else { + mDebugMode.setTitle(getResources().getString(R.string.prefs_debug_mode)); + mDebugMode.setSummary(version); + } + } +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/LatinIMESettings.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/LatinIMESettings.java new file mode 100644 index 00000000..bc94b9de --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/LatinIMESettings.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * Copyright (C) 2014 Philipp Crocoll + * Copyright (C) 2014 Wiktor Lawski + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 keepass2android.softkeyboard; + +import java.util.ArrayList; +import java.util.Locale; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.backup.BackupManager; +import android.content.DialogInterface; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.preference.CheckBoxPreference; +import android.preference.ListPreference; +import android.preference.PreferenceActivity; +import android.preference.PreferenceGroup; +import android.preference.PreferenceManager; +import android.speech.SpeechRecognizer; +import android.text.AutoText; +import android.util.Log; + +public class LatinIMESettings extends PreferenceActivity + implements SharedPreferences.OnSharedPreferenceChangeListener, + DialogInterface.OnDismissListener { + + private static final String QUICK_FIXES_KEY = "quick_fixes"; + private static final String PREDICTION_SETTINGS_KEY = "prediction_settings"; + + /* package */ static final String PREF_SETTINGS_KEY = "settings_key"; + + private static final String TAG = "LatinIMESettings"; + + + private CheckBoxPreference mQuickFixes; + private ListPreference mSettingsKeyPreference; + + private boolean mOkClicked = false; + + @Override + protected void onCreate(Bundle icicle) { + SharedPreferences prefs = + PreferenceManager.getDefaultSharedPreferences(this); + Design.updateTheme(this, prefs); + + super.onCreate(icicle); + addPreferencesFromResource(R.xml.prefs); + mQuickFixes = (CheckBoxPreference) findPreference(QUICK_FIXES_KEY); + mSettingsKeyPreference = (ListPreference) findPreference(PREF_SETTINGS_KEY); + prefs.registerOnSharedPreferenceChangeListener(this); + + + } + + @Override + protected void onResume() { + super.onResume(); + int autoTextSize = AutoText.getSize(getListView()); + if (autoTextSize < 1) { + ((PreferenceGroup) findPreference(PREDICTION_SETTINGS_KEY)) + .removePreference(mQuickFixes); + } + + + } + + @Override + protected void onDestroy() { + getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener( + this); + super.onDestroy(); + } + + public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { + (new BackupManager(this)).dataChanged(); + + } + + + + @Override + protected Dialog onCreateDialog(int id) { + switch (id) { + + default: + Log.e(TAG, "unknown dialog " + id); + return null; + } + } + + public void onDismiss(DialogInterface dialog) { + + } + +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/LatinIMEUtil.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/LatinIMEUtil.java new file mode 100644 index 00000000..070ff43b --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/LatinIMEUtil.java @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package keepass2android.softkeyboard; + +import android.view.inputmethod.InputMethodManager; + +import android.content.Context; +import android.os.AsyncTask; +import android.text.format.DateUtils; +import android.util.Log; + +public class LatinIMEUtil { + + /** + * Cancel an {@link AsyncTask}. + * + * @param mayInterruptIfRunning true if the thread executing this + * task should be interrupted; otherwise, in-progress tasks are allowed + * to complete. + */ + public static void cancelTask(AsyncTask task, boolean mayInterruptIfRunning) { + if (task != null && task.getStatus() != AsyncTask.Status.FINISHED) { + task.cancel(mayInterruptIfRunning); + } + } + + public static class GCUtils { + private static final String TAG = "GCUtils"; + public static final int GC_TRY_COUNT = 2; + // GC_TRY_LOOP_MAX is used for the hard limit of GC wait, + // GC_TRY_LOOP_MAX should be greater than GC_TRY_COUNT. + public static final int GC_TRY_LOOP_MAX = 5; + private static final long GC_INTERVAL = DateUtils.SECOND_IN_MILLIS; + private static GCUtils sInstance = new GCUtils(); + private int mGCTryCount = 0; + + public static GCUtils getInstance() { + return sInstance; + } + + public void reset() { + mGCTryCount = 0; + } + + public boolean tryGCOrWait(String metaData, Throwable t) { + if (mGCTryCount == 0) { + System.gc(); + } + if (++mGCTryCount > GC_TRY_COUNT) { + LatinImeLogger.logOnException(metaData, t); + return false; + } else { + try { + Thread.sleep(GC_INTERVAL); + return true; + } catch (InterruptedException e) { + Log.e(TAG, "Sleep was interrupted."); + LatinImeLogger.logOnException(metaData, t); + return false; + } + } + } + } + + public static boolean hasMultipleEnabledIMEs(Context context) { + return ((InputMethodManager) context.getSystemService( + Context.INPUT_METHOD_SERVICE)).getEnabledInputMethodList().size() > 1; + } + + /* package */ static class RingCharBuffer { + private static RingCharBuffer sRingCharBuffer = new RingCharBuffer(); + private static final char PLACEHOLDER_DELIMITER_CHAR = '\uFFFC'; + private static final int INVALID_COORDINATE = -2; + /* package */ static final int BUFSIZE = 20; + private Context mContext; + private boolean mEnabled = false; + private int mEnd = 0; + /* package */ int mLength = 0; + private char[] mCharBuf = new char[BUFSIZE]; + private int[] mXBuf = new int[BUFSIZE]; + private int[] mYBuf = new int[BUFSIZE]; + + private RingCharBuffer() { + } + public static RingCharBuffer getInstance() { + return sRingCharBuffer; + } + public static RingCharBuffer init(Context context, boolean enabled) { + sRingCharBuffer.mContext = context; + sRingCharBuffer.mEnabled = enabled; + return sRingCharBuffer; + } + private int normalize(int in) { + int ret = in % BUFSIZE; + return ret < 0 ? ret + BUFSIZE : ret; + } + public void push(char c, int x, int y) { + if (!mEnabled) return; + mCharBuf[mEnd] = c; + mXBuf[mEnd] = x; + mYBuf[mEnd] = y; + mEnd = normalize(mEnd + 1); + if (mLength < BUFSIZE) { + ++mLength; + } + } + public char pop() { + if (mLength < 1) { + return PLACEHOLDER_DELIMITER_CHAR; + } else { + mEnd = normalize(mEnd - 1); + --mLength; + return mCharBuf[mEnd]; + } + } + public char getLastChar() { + if (mLength < 1) { + return PLACEHOLDER_DELIMITER_CHAR; + } else { + return mCharBuf[normalize(mEnd - 1)]; + } + } + public int getPreviousX(char c, int back) { + int index = normalize(mEnd - 2 - back); + if (mLength <= back + || Character.toLowerCase(c) != Character.toLowerCase(mCharBuf[index])) { + return INVALID_COORDINATE; + } else { + return mXBuf[index]; + } + } + public int getPreviousY(char c, int back) { + int index = normalize(mEnd - 2 - back); + if (mLength <= back + || Character.toLowerCase(c) != Character.toLowerCase(mCharBuf[index])) { + return INVALID_COORDINATE; + } else { + return mYBuf[index]; + } + } + public String getLastString() { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < mLength; ++i) { + char c = mCharBuf[normalize(mEnd - 1 - i)]; + if (!((KP2AKeyboard)mContext).isWordSeparator(c)) { + sb.append(c); + } else { + break; + } + } + return sb.reverse().toString(); + } + public void reset() { + mLength = 0; + } + } +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/LatinImeLogger.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/LatinImeLogger.java new file mode 100644 index 00000000..1e347369 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/LatinImeLogger.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package keepass2android.softkeyboard; + +import keepass2android.softkeyboard.Dictionary.DataType; + +import android.content.Context; +import android.content.SharedPreferences; +import android.inputmethodservice.Keyboard; +import java.util.List; + +public class LatinImeLogger implements SharedPreferences.OnSharedPreferenceChangeListener { + + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + } + + public static void init(Context context) { + } + + public static void commit() { + } + + public static void onDestroy() { + } + + public static void logOnManualSuggestion( + String before, String after, int position, List suggestions) { + } + + public static void logOnAutoSuggestion(String before, String after) { + } + + public static void logOnAutoSuggestionCanceled() { + } + + public static void logOnDelete() { + } + + public static void logOnInputChar() { + } + + public static void logOnException(String metaData, Throwable e) { + } + + public static void logOnWarning(String warning) { + } + + public static void onStartSuggestion(CharSequence previousWords) { + } + + public static void onAddSuggestedWord(String word, int typeId, DataType dataType) { + } + + public static void onSetKeyboard(Keyboard kb) { + } + +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/LatinKeyboard.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/LatinKeyboard.java new file mode 100644 index 00000000..45bc65d9 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/LatinKeyboard.java @@ -0,0 +1,1013 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package keepass2android.softkeyboard; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.content.res.XmlResourceParser; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.Paint.Align; +import android.graphics.PixelFormat; +import android.graphics.PorterDuff; +import android.graphics.Rect; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.inputmethodservice.Keyboard; +import android.text.TextPaint; +import android.util.Log; +import android.view.ViewConfiguration; +import android.view.inputmethod.EditorInfo; + +import java.util.List; +import java.util.Locale; + +public class LatinKeyboard extends Keyboard { + + private static final boolean DEBUG_PREFERRED_LETTER = false; + private static final String TAG = "LatinKeyboard"; + private static final int OPACITY_FULLY_OPAQUE = 255; + private static final int SPACE_LED_LENGTH_PERCENT = 80; + + private Drawable mShiftLockIcon; + private Drawable mShiftLockPreviewIcon; + private Drawable mOldShiftIcon; + private Drawable mSpaceIcon; + private Drawable mSpaceAutoCompletionIndicator; + private Drawable mSpacePreviewIcon; + private Drawable mMicIcon; + private Drawable mMicPreviewIcon; + private Drawable m123MicIcon; + private Drawable m123MicPreviewIcon; + private final Drawable mButtonArrowLeftIcon; + private final Drawable mButtonArrowRightIcon; + private Key mShiftKey; + private Key mEnterKey; + private Key mF1Key; + private final Drawable mHintIcon; + private Key mSpaceKey; + private Key m123Key; + private final int NUMBER_HINT_COUNT = 10; + private Key[] mNumberHintKeys; + private Drawable[] mNumberHintIcons = new Drawable[NUMBER_HINT_COUNT]; + private final int[] mSpaceKeyIndexArray; + private int mSpaceDragStartX; + private int mSpaceDragLastDiff; + private Locale mLocale; + private LanguageSwitcher mLanguageSwitcher; + private final Resources mRes; + private final Context mContext; + private int mMode; + // Whether this keyboard has voice icon on it + private boolean mHasVoiceButton; + // Whether voice icon is enabled at all + + private final boolean mIsAlphaKeyboard; + private CharSequence m123Label; + private boolean mCurrentlyInSpace; + private SlidingLocaleDrawable mSlidingLocaleIcon; + private int[] mPrefLetterFrequencies; + private int mPrefLetter; + private int mPrefLetterX; + private int mPrefLetterY; + private int mPrefDistance; + + // TODO: generalize for any keyboardId + private boolean mIsBlackSym; + + // TODO: remove this attribute when either Keyboard.mDefaultVerticalGap or Key.parent becomes + // non-private. + private final int mVerticalGap; + + private static final int SHIFT_OFF = 0; + private static final int SHIFT_ON = 1; + private static final int SHIFT_LOCKED = 2; + + private int mShiftState = SHIFT_OFF; + + private static final float SPACEBAR_DRAG_THRESHOLD = 0.8f; + private static final float OVERLAP_PERCENTAGE_LOW_PROB = 0.70f; + private static final float OVERLAP_PERCENTAGE_HIGH_PROB = 0.85f; + // Minimum width of space key preview (proportional to keyboard width) + private static final float SPACEBAR_POPUP_MIN_RATIO = 0.4f; + // Height in space key the language name will be drawn. (proportional to space key height) + private static final float SPACEBAR_LANGUAGE_BASELINE = 0.6f; + // If the full language name needs to be smaller than this value to be drawn on space key, + // its short language name will be used instead. + private static final float MINIMUM_SCALE_OF_LANGUAGE_NAME = 0.8f; + + private static int sSpacebarVerticalCorrection; + + public LatinKeyboard(Context context, int xmlLayoutResId) { + this(context, xmlLayoutResId, 0); + } + + public LatinKeyboard(Context context, int xmlLayoutResId, int mode) { + super(context, xmlLayoutResId, mode); + final Resources res = context.getResources(); + mContext = context; + mMode = mode; + mRes = res; + mShiftLockIcon = res.getDrawable(R.drawable.sym_keyboard_shift_locked); + mShiftLockPreviewIcon = res.getDrawable(R.drawable.sym_keyboard_feedback_shift_locked); + setDefaultBounds(mShiftLockPreviewIcon); + mSpaceIcon = res.getDrawable(R.drawable.sym_keyboard_space); + mSpaceAutoCompletionIndicator = res.getDrawable(R.drawable.sym_keyboard_space_led); + mSpacePreviewIcon = res.getDrawable(R.drawable.sym_keyboard_feedback_space); + mMicIcon = res.getDrawable(R.drawable.sym_keyboard_mic); + mMicPreviewIcon = res.getDrawable(R.drawable.sym_keyboard_feedback_mic); + setDefaultBounds(mMicPreviewIcon); + mButtonArrowLeftIcon = res.getDrawable(R.drawable.sym_keyboard_language_arrows_left); + mButtonArrowRightIcon = res.getDrawable(R.drawable.sym_keyboard_language_arrows_right); + m123MicIcon = res.getDrawable(R.drawable.sym_keyboard_123_mic); + m123MicPreviewIcon = res.getDrawable(R.drawable.sym_keyboard_feedback_123_mic); + mHintIcon = res.getDrawable(R.drawable.hint_popup); + setDefaultBounds(m123MicPreviewIcon); + sSpacebarVerticalCorrection = res.getDimensionPixelOffset( + R.dimen.spacebar_vertical_correction); + mIsAlphaKeyboard = xmlLayoutResId == R.xml.kbd_qwerty + || xmlLayoutResId == R.xml.kbd_qwerty_black; + // The index of space key is available only after Keyboard constructor has finished. + mSpaceKeyIndexArray = new int[] { indexOf(KP2AKeyboard.KEYCODE_SPACE) }; + initializeNumberHintResources(context); + // TODO remove this initialization after cleanup + mVerticalGap = super.getVerticalGap(); + } + + private void initializeNumberHintResources(Context context) { + final Resources res = context.getResources(); + mNumberHintIcons[0] = res.getDrawable(R.drawable.keyboard_hint_0); + mNumberHintIcons[1] = res.getDrawable(R.drawable.keyboard_hint_1); + mNumberHintIcons[2] = res.getDrawable(R.drawable.keyboard_hint_2); + mNumberHintIcons[3] = res.getDrawable(R.drawable.keyboard_hint_3); + mNumberHintIcons[4] = res.getDrawable(R.drawable.keyboard_hint_4); + mNumberHintIcons[5] = res.getDrawable(R.drawable.keyboard_hint_5); + mNumberHintIcons[6] = res.getDrawable(R.drawable.keyboard_hint_6); + mNumberHintIcons[7] = res.getDrawable(R.drawable.keyboard_hint_7); + mNumberHintIcons[8] = res.getDrawable(R.drawable.keyboard_hint_8); + mNumberHintIcons[9] = res.getDrawable(R.drawable.keyboard_hint_9); + } + + @Override + protected Key createKeyFromXml(Resources res, Row parent, int x, int y, + XmlResourceParser parser) { + Key key = new LatinKey(res, parent, x, y, parser); + switch (key.codes[0]) { + case KP2AKeyboard.KEYCODE_ENTER: + mEnterKey = key; + break; + case LatinKeyboardView.KEYCODE_F1: + mF1Key = key; + break; + case KP2AKeyboard.KEYCODE_SPACE: + mSpaceKey = key; + break; + case KEYCODE_MODE_CHANGE: + m123Key = key; + m123Label = key.label; + break; + } + + // For number hints on the upper-right corner of key + if (mNumberHintKeys == null) { + // NOTE: This protected method is being called from the base class constructor before + // mNumberHintKeys gets initialized. + mNumberHintKeys = new Key[NUMBER_HINT_COUNT]; + } + int hintNumber = -1; + if (LatinKeyboardBaseView.isNumberAtLeftmostPopupChar(key)) { + hintNumber = key.popupCharacters.charAt(0) - '0'; + } else if (LatinKeyboardBaseView.isNumberAtRightmostPopupChar(key)) { + hintNumber = key.popupCharacters.charAt(key.popupCharacters.length() - 1) - '0'; + } + if (hintNumber >= 0 && hintNumber <= 9) { + mNumberHintKeys[hintNumber] = key; + } + + return key; + } + + void setImeOptions(Resources res, int mode, int options) { + mMode = mode; + // TODO should clean up this method + if (mEnterKey != null) { + // Reset some of the rarely used attributes. + mEnterKey.popupCharacters = null; + mEnterKey.popupResId = 0; + mEnterKey.text = null; + switch (options&(EditorInfo.IME_MASK_ACTION|EditorInfo.IME_FLAG_NO_ENTER_ACTION)) { + case EditorInfo.IME_ACTION_GO: + mEnterKey.iconPreview = null; + mEnterKey.icon = null; + mEnterKey.label = res.getText(R.string.label_go_key); + break; + case EditorInfo.IME_ACTION_NEXT: + mEnterKey.iconPreview = null; + mEnterKey.icon = null; + mEnterKey.label = res.getText(R.string.label_next_key); + break; + case EditorInfo.IME_ACTION_DONE: + mEnterKey.iconPreview = null; + mEnterKey.icon = null; + mEnterKey.label = res.getText(R.string.label_done_key); + break; + case EditorInfo.IME_ACTION_SEARCH: + mEnterKey.iconPreview = res.getDrawable( + R.drawable.sym_keyboard_feedback_search); + mEnterKey.icon = res.getDrawable(mIsBlackSym ? + R.drawable.sym_bkeyboard_search : R.drawable.sym_keyboard_search); + mEnterKey.label = null; + break; + case EditorInfo.IME_ACTION_SEND: + mEnterKey.iconPreview = null; + mEnterKey.icon = null; + mEnterKey.label = res.getText(R.string.label_send_key); + break; + default: + if (mode == KeyboardSwitcher.MODE_IM) { + mEnterKey.icon = mHintIcon; + mEnterKey.iconPreview = null; + mEnterKey.label = ":-)"; + mEnterKey.text = ":-) "; + mEnterKey.popupResId = R.xml.popup_smileys; + } else { + mEnterKey.iconPreview = res.getDrawable( + R.drawable.sym_keyboard_feedback_return); + mEnterKey.icon = res.getDrawable(mIsBlackSym ? + R.drawable.sym_bkeyboard_return : R.drawable.sym_keyboard_return); + mEnterKey.label = null; + } + break; + } + // Set the initial size of the preview icon + if (mEnterKey.iconPreview != null) { + setDefaultBounds(mEnterKey.iconPreview); + } + } + } + + void enableShiftLock() { + int index = getShiftKeyIndex(); + if (index >= 0) { + mShiftKey = getKeys().get(index); + if (mShiftKey instanceof LatinKey) { + ((LatinKey)mShiftKey).enableShiftLock(); + } + mOldShiftIcon = mShiftKey.icon; + } + } + + void setShiftLocked(boolean shiftLocked) { + if (mShiftKey != null) { + if (shiftLocked) { + mShiftKey.on = true; + mShiftKey.icon = mShiftLockIcon; + mShiftState = SHIFT_LOCKED; + } else { + mShiftKey.on = false; + mShiftKey.icon = mShiftLockIcon; + mShiftState = SHIFT_ON; + } + } + } + + boolean isShiftLocked() { + return mShiftState == SHIFT_LOCKED; + } + + @Override + public boolean setShifted(boolean shiftState) { + boolean shiftChanged = false; + if (mShiftKey != null) { + if (shiftState == false) { + shiftChanged = mShiftState != SHIFT_OFF; + mShiftState = SHIFT_OFF; + mShiftKey.on = false; + mShiftKey.icon = mOldShiftIcon; + } else { + if (mShiftState == SHIFT_OFF) { + shiftChanged = mShiftState == SHIFT_OFF; + mShiftState = SHIFT_ON; + mShiftKey.icon = mShiftLockIcon; + } + } + } else { + return super.setShifted(shiftState); + } + return shiftChanged; + } + + @Override + public boolean isShifted() { + if (mShiftKey != null) { + return mShiftState != SHIFT_OFF; + } else { + return super.isShifted(); + } + } + + /* package */ boolean isAlphaKeyboard() { + return mIsAlphaKeyboard; + } + + public void setColorOfSymbolIcons(boolean isAutoCompletion, boolean isBlack) { + mIsBlackSym = isBlack; + if (isBlack) { + mShiftLockIcon = mRes.getDrawable(R.drawable.sym_bkeyboard_shift_locked); + mSpaceIcon = mRes.getDrawable(R.drawable.sym_bkeyboard_space); + mMicIcon = mRes.getDrawable(R.drawable.sym_bkeyboard_mic); + m123MicIcon = mRes.getDrawable(R.drawable.sym_bkeyboard_123_mic); + } else { + mShiftLockIcon = mRes.getDrawable(R.drawable.sym_keyboard_shift_locked); + mSpaceIcon = mRes.getDrawable(R.drawable.sym_keyboard_space); + mMicIcon = mRes.getDrawable(R.drawable.sym_keyboard_mic); + m123MicIcon = mRes.getDrawable(R.drawable.sym_keyboard_123_mic); + } + updateDynamicKeys(); + if (mSpaceKey != null) { + updateSpaceBarForLocale(isAutoCompletion, isBlack); + } + updateNumberHintKeys(); + } + + private void setDefaultBounds(Drawable drawable) { + drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); + } + + + private void updateDynamicKeys() { + update123Key(); + updateF1Key(); + } + + private void update123Key() { + // Update KEYCODE_MODE_CHANGE key only on alphabet mode, not on symbol mode. + if (m123Key != null && mIsAlphaKeyboard) { + + m123Key.icon = null; + m123Key.iconPreview = null; + m123Key.label = m123Label; + + } + } + + private void updateF1Key() { + // Update KEYCODE_F1 key. Please note that some keyboard layouts have no F1 key. + if (mF1Key == null) + return; + + if (mIsAlphaKeyboard) { + if (mMode == KeyboardSwitcher.MODE_URL) { + setNonMicF1Key(mF1Key, "/", R.xml.popup_slash); + } else if (mMode == KeyboardSwitcher.MODE_EMAIL) { + setNonMicF1Key(mF1Key, "@", R.xml.popup_at); + } else { + setNonMicF1Key(mF1Key, ",", R.xml.popup_comma); + + } + } else { // Symbols keyboard + setNonMicF1Key(mF1Key, ",", R.xml.popup_comma); + } + } + private void setNonMicF1Key(Key key, String label, int popupResId) { + key.label = label; + key.codes = new int[] { label.charAt(0) }; + key.popupResId = popupResId; + key.icon = mHintIcon; + key.iconPreview = null; + } + + public boolean isF1Key(Key key) { + return key == mF1Key; + } + + public static boolean hasPuncOrSmileysPopup(Key key) { + return key.popupResId == R.xml.popup_punctuation || key.popupResId == R.xml.popup_smileys; + } + + /** + * @return a key which should be invalidated. + */ + public Key onAutoCompletionStateChanged(boolean isAutoCompletion) { + updateSpaceBarForLocale(isAutoCompletion, mIsBlackSym); + return mSpaceKey; + } + + private void updateNumberHintKeys() { + for (int i = 0; i < mNumberHintKeys.length; ++i) { + if (mNumberHintKeys[i] != null) { + mNumberHintKeys[i].icon = mNumberHintIcons[i]; + } + } + } + + public boolean isLanguageSwitchEnabled() { + return mLocale != null; + } + + private void updateSpaceBarForLocale(boolean isAutoCompletion, boolean isBlack) { + // If application locales are explicitly selected. + try + { + if (mLocale != null) { + mSpaceKey.icon = new BitmapDrawable(mRes, + drawSpaceBar(OPACITY_FULLY_OPAQUE, isAutoCompletion, isBlack)); + } else { + // sym_keyboard_space_led can be shared with Black and White symbol themes. + if (isAutoCompletion) { + mSpaceKey.icon = new BitmapDrawable(mRes, + drawSpaceBar(OPACITY_FULLY_OPAQUE, isAutoCompletion, isBlack)); + } else { + mSpaceKey.icon = isBlack ? mRes.getDrawable(R.drawable.sym_bkeyboard_space) + : mRes.getDrawable(R.drawable.sym_keyboard_space); + } + } + } + catch (NullPointerException e) + { + //this exception was reported through Google Play. I need further info to resolve. + android.util.Log.e("KP2A", "Please report this error to crocoapps@gmail.com"); + android.util.Log.e("KP2A", e.toString()); + android.util.Log.e("KP2A", ((mSpaceKey==null) ? "1" : "0") + + ((mRes==null) ? "1" : "0")); + } + + } + + // Compute width of text with specified text size using paint. + private static int getTextWidth(Paint paint, String text, float textSize, Rect bounds) { + paint.setTextSize(textSize); + paint.getTextBounds(text, 0, text.length(), bounds); + return bounds.width(); + } + + // Overlay two images: mainIcon and hintIcon. + private Bitmap drawSynthesizedSettingsHintImage( + int width, int height, Drawable mainIcon, Drawable hintIcon) { + if (mainIcon == null || hintIcon == null) + return null; + Rect hintIconPadding = new Rect(0, 0, 0, 0); + hintIcon.getPadding(hintIconPadding); + final Bitmap buffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + final Canvas canvas = new Canvas(buffer); + canvas.drawColor(mRes.getColor(R.color.latinkeyboard_transparent), PorterDuff.Mode.CLEAR); + + // Draw main icon at the center of the key visual + // Assuming the hintIcon shares the same padding with the key's background drawable + final int drawableX = (width + hintIconPadding.left - hintIconPadding.right + - mainIcon.getIntrinsicWidth()) / 2; + final int drawableY = (height + hintIconPadding.top - hintIconPadding.bottom + - mainIcon.getIntrinsicHeight()) / 2; + setDefaultBounds(mainIcon); + canvas.translate(drawableX, drawableY); + mainIcon.draw(canvas); + canvas.translate(-drawableX, -drawableY); + + // Draw hint icon fully in the key + hintIcon.setBounds(0, 0, width, height); + hintIcon.draw(canvas); + return buffer; + } + + // Layout local language name and left and right arrow on space bar. + private static String layoutSpaceBar(Paint paint, Locale locale, Drawable lArrow, + Drawable rArrow, int width, int height, float origTextSize, + boolean allowVariableTextSize) { + final float arrowWidth = lArrow.getIntrinsicWidth(); + final float arrowHeight = lArrow.getIntrinsicHeight(); + final float maxTextWidth = width - (arrowWidth + arrowWidth); + final Rect bounds = new Rect(); + + // Estimate appropriate language name text size to fit in maxTextWidth. + String language = LanguageSwitcher.toTitleCase(locale.getDisplayLanguage(locale), locale); + int textWidth = getTextWidth(paint, language, origTextSize, bounds); + // Assuming text width and text size are proportional to each other. + float textSize = origTextSize * Math.min(maxTextWidth / textWidth, 1.0f); + + final boolean useShortName; + if (allowVariableTextSize) { + textWidth = getTextWidth(paint, language, textSize, bounds); + // If text size goes too small or text does not fit, use short name + useShortName = textSize / origTextSize < MINIMUM_SCALE_OF_LANGUAGE_NAME + || textWidth > maxTextWidth; + } else { + useShortName = textWidth > maxTextWidth; + textSize = origTextSize; + } + if (useShortName) { + language = LanguageSwitcher.toTitleCase(locale.getLanguage(), locale); + textWidth = getTextWidth(paint, language, origTextSize, bounds); + textSize = origTextSize * Math.min(maxTextWidth / textWidth, 1.0f); + } + paint.setTextSize(textSize); + + // Place left and right arrow just before and after language text. + final float baseline = height * SPACEBAR_LANGUAGE_BASELINE; + final int top = (int)(baseline - arrowHeight); + final float remains = (width - textWidth) / 2; + lArrow.setBounds((int)(remains - arrowWidth), top, (int)remains, (int)baseline); + rArrow.setBounds((int)(remains + textWidth), top, (int)(remains + textWidth + arrowWidth), + (int)baseline); + + return language; + } + + private Bitmap drawSpaceBar(int opacity, boolean isAutoCompletion, boolean isBlack) { + final int width = mSpaceKey.width; + final int height = mSpaceIcon.getIntrinsicHeight(); + final Bitmap buffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + final Canvas canvas = new Canvas(buffer); + canvas.drawColor(mRes.getColor(R.color.latinkeyboard_transparent), PorterDuff.Mode.CLEAR); + + // If application locales are explicitly selected. + if (mLocale != null) { + final Paint paint = new Paint(); + paint.setAlpha(opacity); + paint.setAntiAlias(true); + paint.setTextAlign(Align.CENTER); + + final boolean allowVariableTextSize = true; + final String language = layoutSpaceBar(paint, mLanguageSwitcher.getInputLocale(), + mButtonArrowLeftIcon, mButtonArrowRightIcon, width, height, + getTextSizeFromTheme(android.R.style.TextAppearance_Small, 14), + allowVariableTextSize); + + // Draw language text with shadow + final int shadowColor = mRes.getColor(isBlack + ? R.color.latinkeyboard_bar_language_shadow_black + : R.color.latinkeyboard_bar_language_shadow_white); + final float baseline = height * SPACEBAR_LANGUAGE_BASELINE; + final float descent = paint.descent(); + paint.setColor(shadowColor); + canvas.drawText(language, width / 2, baseline - descent - 1, paint); + paint.setColor(mRes.getColor(R.color.latinkeyboard_bar_language_text)); + canvas.drawText(language, width / 2, baseline - descent, paint); + + // Put arrows that are already layed out on either side of the text + if (mLanguageSwitcher.getLocaleCount() > 1) { + mButtonArrowLeftIcon.draw(canvas); + mButtonArrowRightIcon.draw(canvas); + } + } + + // Draw the spacebar icon at the bottom + if (isAutoCompletion) { + final int iconWidth = width * SPACE_LED_LENGTH_PERCENT / 100; + final int iconHeight = mSpaceAutoCompletionIndicator.getIntrinsicHeight(); + int x = (width - iconWidth) / 2; + int y = height - iconHeight; + mSpaceAutoCompletionIndicator.setBounds(x, y, x + iconWidth, y + iconHeight); + mSpaceAutoCompletionIndicator.draw(canvas); + } else { + final int iconWidth = mSpaceIcon.getIntrinsicWidth(); + final int iconHeight = mSpaceIcon.getIntrinsicHeight(); + int x = (width - iconWidth) / 2; + int y = height - iconHeight; + mSpaceIcon.setBounds(x, y, x + iconWidth, y + iconHeight); + mSpaceIcon.draw(canvas); + } + return buffer; + } + + private void updateLocaleDrag(int diff) { + if (mSlidingLocaleIcon == null) { + final int width = Math.max(mSpaceKey.width, + (int)(getMinWidth() * SPACEBAR_POPUP_MIN_RATIO)); + final int height = mSpacePreviewIcon.getIntrinsicHeight(); + mSlidingLocaleIcon = new SlidingLocaleDrawable(mSpacePreviewIcon, width, height); + mSlidingLocaleIcon.setBounds(0, 0, width, height); + mSpaceKey.iconPreview = mSlidingLocaleIcon; + } + mSlidingLocaleIcon.setDiff(diff); + if (Math.abs(diff) == Integer.MAX_VALUE) { + mSpaceKey.iconPreview = mSpacePreviewIcon; + } else { + mSpaceKey.iconPreview = mSlidingLocaleIcon; + } + mSpaceKey.iconPreview.invalidateSelf(); + } + + public int getLanguageChangeDirection() { + if (mSpaceKey == null || mLanguageSwitcher.getLocaleCount() < 2 + || Math.abs(mSpaceDragLastDiff) < mSpaceKey.width * SPACEBAR_DRAG_THRESHOLD ) { + return 0; // No change + } + return mSpaceDragLastDiff > 0 ? 1 : -1; + } + + public void setLanguageSwitcher(LanguageSwitcher switcher, boolean isAutoCompletion, + boolean isBlackSym) { + mLanguageSwitcher = switcher; + Locale locale = mLanguageSwitcher.getLocaleCount() > 0 + ? mLanguageSwitcher.getInputLocale() + : null; + // If the language count is 1 and is the same as the system language, don't show it. + if (locale != null + && mLanguageSwitcher.getLocaleCount() == 1 + && mLanguageSwitcher.getSystemLocale().getLanguage() + .equalsIgnoreCase(locale.getLanguage())) { + locale = null; + } + mLocale = locale; + setColorOfSymbolIcons(isAutoCompletion, isBlackSym); + } + + public Locale getInputLocale() { + return (mLocale != null) ? mLocale : mLanguageSwitcher.getSystemLocale(); + } + + boolean isCurrentlyInSpace() { + return mCurrentlyInSpace; + } + + void setPreferredLetters(int[] frequencies) { + mPrefLetterFrequencies = frequencies; + mPrefLetter = 0; + } + + void keyReleased() { + mCurrentlyInSpace = false; + mSpaceDragLastDiff = 0; + mPrefLetter = 0; + mPrefLetterX = 0; + mPrefLetterY = 0; + mPrefDistance = Integer.MAX_VALUE; + if (mSpaceKey != null) { + updateLocaleDrag(Integer.MAX_VALUE); + } + } + + /** + * Does the magic of locking the touch gesture into the spacebar when + * switching input languages. + */ + boolean isInside(LatinKey key, int x, int y) { + final int code = key.codes[0]; + if (code == KEYCODE_SHIFT || + code == KEYCODE_DELETE) { + y -= key.height / 10; + if (code == KEYCODE_SHIFT) x += key.width / 6; + if (code == KEYCODE_DELETE) x -= key.width / 6; + } else if (code == KP2AKeyboard.KEYCODE_SPACE) { + y += LatinKeyboard.sSpacebarVerticalCorrection; + if (mLanguageSwitcher.getLocaleCount() > 1) { + if (mCurrentlyInSpace) { + int diff = x - mSpaceDragStartX; + if (Math.abs(diff - mSpaceDragLastDiff) > 0) { + updateLocaleDrag(diff); + } + mSpaceDragLastDiff = diff; + return true; + } else { + boolean insideSpace = key.isInsideSuper(x, y); + if (insideSpace) { + mCurrentlyInSpace = true; + mSpaceDragStartX = x; + updateLocaleDrag(0); + } + return insideSpace; + } + } + } else if (mPrefLetterFrequencies != null) { + // New coordinate? Reset + if (mPrefLetterX != x || mPrefLetterY != y) { + mPrefLetter = 0; + mPrefDistance = Integer.MAX_VALUE; + } + // Handle preferred next letter + final int[] pref = mPrefLetterFrequencies; + if (mPrefLetter > 0) { + if (DEBUG_PREFERRED_LETTER) { + if (mPrefLetter == code && !key.isInsideSuper(x, y)) { + Log.d(TAG, "CORRECTED !!!!!!"); + } + } + return mPrefLetter == code; + } else { + final boolean inside = key.isInsideSuper(x, y); + int[] nearby = getNearestKeys(x, y); + List nearbyKeys = getKeys(); + if (inside) { + // If it's a preferred letter + if (inPrefList(code, pref)) { + // Check if its frequency is much lower than a nearby key + mPrefLetter = code; + mPrefLetterX = x; + mPrefLetterY = y; + for (int i = 0; i < nearby.length; i++) { + Key k = nearbyKeys.get(nearby[i]); + if (k != key && inPrefList(k.codes[0], pref)) { + final int dist = distanceFrom(k, x, y); + if (dist < (int) (k.width * OVERLAP_PERCENTAGE_LOW_PROB) && + (pref[k.codes[0]] > pref[mPrefLetter] * 3)) { + mPrefLetter = k.codes[0]; + mPrefDistance = dist; + if (DEBUG_PREFERRED_LETTER) { + Log.d(TAG, "CORRECTED ALTHOUGH PREFERRED !!!!!!"); + } + break; + } + } + } + + return mPrefLetter == code; + } + } + + // Get the surrounding keys and intersect with the preferred list + // For all in the intersection + // if distance from touch point is within a reasonable distance + // make this the pref letter + // If no pref letter + // return inside; + // else return thiskey == prefletter; + + for (int i = 0; i < nearby.length; i++) { + Key k = nearbyKeys.get(nearby[i]); + if (inPrefList(k.codes[0], pref)) { + final int dist = distanceFrom(k, x, y); + if (dist < (int) (k.width * OVERLAP_PERCENTAGE_HIGH_PROB) + && dist < mPrefDistance) { + mPrefLetter = k.codes[0]; + mPrefLetterX = x; + mPrefLetterY = y; + mPrefDistance = dist; + } + } + } + // Didn't find any + if (mPrefLetter == 0) { + return inside; + } else { + return mPrefLetter == code; + } + } + } + + // Lock into the spacebar + if (mCurrentlyInSpace) return false; + + return key.isInsideSuper(x, y); + } + + private boolean inPrefList(int code, int[] pref) { + if (code < pref.length && code >= 0) return pref[code] > 0; + return false; + } + + private int distanceFrom(Key k, int x, int y) { + if (y > k.y && y < k.y + k.height) { + return Math.abs(k.x + k.width / 2 - x); + } else { + return Integer.MAX_VALUE; + } + } + + @Override + public int[] getNearestKeys(int x, int y) { + if (mCurrentlyInSpace) { + return mSpaceKeyIndexArray; + } else { + // Avoid dead pixels at edges of the keyboard + return super.getNearestKeys(Math.max(0, Math.min(x, getMinWidth() - 1)), + Math.max(0, Math.min(y, getHeight() - 1))); + } + } + + private int indexOf(int code) { + List keys = getKeys(); + int count = keys.size(); + for (int i = 0; i < count; i++) { + if (keys.get(i).codes[0] == code) return i; + } + return -1; + } + + private int getTextSizeFromTheme(int style, int defValue) { + TypedArray array = mContext.getTheme().obtainStyledAttributes( + style, new int[] { android.R.attr.textSize }); + int textSize = array.getDimensionPixelSize(array.getResourceId(0, 0), defValue); + return textSize; + } + + // TODO LatinKey could be static class + class LatinKey extends Keyboard.Key { + + // functional normal state (with properties) + private final int[] KEY_STATE_FUNCTIONAL_NORMAL = { + android.R.attr.state_single + }; + + // functional pressed state (with properties) + private final int[] KEY_STATE_FUNCTIONAL_PRESSED = { + android.R.attr.state_single, + android.R.attr.state_pressed + }; + + private boolean mShiftLockEnabled; + + public LatinKey(Resources res, Keyboard.Row parent, int x, int y, + XmlResourceParser parser) { + super(res, parent, x, y, parser); + if (popupCharacters != null && popupCharacters.length() == 0) { + // If there is a keyboard with no keys specified in popupCharacters + popupResId = 0; + } + } + + private void enableShiftLock() { + mShiftLockEnabled = true; + } + + // sticky is used for shift key. If a key is not sticky and is modifier, + // the key will be treated as functional. + private boolean isFunctionalKey() { + return !sticky && modifier; + } + + @Override + public void onReleased(boolean inside) { + if (!mShiftLockEnabled) { + super.onReleased(inside); + } else { + pressed = !pressed; + } + } + + /** + * Overriding this method so that we can reduce the target area for certain keys. + */ + @Override + public boolean isInside(int x, int y) { + // TODO This should be done by parent.isInside(this, x, y) + // if Key.parent were protected. + boolean result = LatinKeyboard.this.isInside(this, x, y); + return result; + } + + boolean isInsideSuper(int x, int y) { + return super.isInside(x, y); + } + + @Override + public int[] getCurrentDrawableState() { + if (isFunctionalKey()) { + if (pressed) { + return KEY_STATE_FUNCTIONAL_PRESSED; + } else { + return KEY_STATE_FUNCTIONAL_NORMAL; + } + } + return super.getCurrentDrawableState(); + } + + @Override + public int squaredDistanceFrom(int x, int y) { + // We should count vertical gap between rows to calculate the center of this Key. + final int verticalGap = LatinKeyboard.this.mVerticalGap; + final int xDist = this.x + width / 2 - x; + final int yDist = this.y + (height + verticalGap) / 2 - y; + return xDist * xDist + yDist * yDist; + } + } + + /** + * Animation to be displayed on the spacebar preview popup when switching + * languages by swiping the spacebar. It draws the current, previous and + * next languages and moves them by the delta of touch movement on the spacebar. + */ + class SlidingLocaleDrawable extends Drawable { + + private final int mWidth; + private final int mHeight; + private final Drawable mBackground; + private final TextPaint mTextPaint; + private final int mMiddleX; + private final Drawable mLeftDrawable; + private final Drawable mRightDrawable; + private final int mThreshold; + private int mDiff; + private boolean mHitThreshold; + private String mCurrentLanguage; + private String mNextLanguage; + private String mPrevLanguage; + + @SuppressLint("ResourceAsColor") + public SlidingLocaleDrawable(Drawable background, int width, int height) { + mBackground = background; + setDefaultBounds(mBackground); + mWidth = width; + mHeight = height; + mTextPaint = new TextPaint(); + mTextPaint.setTextSize(getTextSizeFromTheme(android.R.style.TextAppearance_Medium, 18)); + + mTextPaint.setColor(R.color.latinkeyboard_transparent); + mTextPaint.setTextAlign(Align.CENTER); + mTextPaint.setAlpha(OPACITY_FULLY_OPAQUE); + mTextPaint.setAntiAlias(true); + mMiddleX = (mWidth - mBackground.getIntrinsicWidth()) / 2; + mLeftDrawable = + mRes.getDrawable(R.drawable.sym_keyboard_feedback_language_arrows_left); + mRightDrawable = + mRes.getDrawable(R.drawable.sym_keyboard_feedback_language_arrows_right); + mThreshold = ViewConfiguration.get(mContext).getScaledTouchSlop(); + } + + private void setDiff(int diff) { + if (diff == Integer.MAX_VALUE) { + mHitThreshold = false; + mCurrentLanguage = null; + return; + } + mDiff = diff; + if (mDiff > mWidth) mDiff = mWidth; + if (mDiff < -mWidth) mDiff = -mWidth; + if (Math.abs(mDiff) > mThreshold) mHitThreshold = true; + invalidateSelf(); + } + + private String getLanguageName(Locale locale) { + return LanguageSwitcher.toTitleCase(locale.getDisplayLanguage(locale), locale); + } + + @Override + public void draw(Canvas canvas) { + canvas.save(); + if (mHitThreshold) { + Paint paint = mTextPaint; + final int width = mWidth; + final int height = mHeight; + final int diff = mDiff; + final Drawable lArrow = mLeftDrawable; + final Drawable rArrow = mRightDrawable; + canvas.clipRect(0, 0, width, height); + if (mCurrentLanguage == null) { + final LanguageSwitcher languageSwitcher = mLanguageSwitcher; + mCurrentLanguage = getLanguageName(languageSwitcher.getInputLocale()); + mNextLanguage = getLanguageName(languageSwitcher.getNextInputLocale()); + mPrevLanguage = getLanguageName(languageSwitcher.getPrevInputLocale()); + } + // Draw language text with shadow + final float baseline = mHeight * SPACEBAR_LANGUAGE_BASELINE - paint.descent(); + paint.setColor(mRes.getColor(R.color.latinkeyboard_feedback_language_text)); + canvas.drawText(mCurrentLanguage, width / 2 + diff, baseline, paint); + canvas.drawText(mNextLanguage, diff - width / 2, baseline, paint); + canvas.drawText(mPrevLanguage, diff + width + width / 2, baseline, paint); + + setDefaultBounds(lArrow); + rArrow.setBounds(width - rArrow.getIntrinsicWidth(), 0, width, + rArrow.getIntrinsicHeight()); + lArrow.draw(canvas); + rArrow.draw(canvas); + } + if (mBackground != null) { + canvas.translate(mMiddleX, 0); + mBackground.draw(canvas); + } + canvas.restore(); + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSLUCENT; + } + + @Override + public void setAlpha(int alpha) { + // Ignore + } + + @Override + public void setColorFilter(ColorFilter cf) { + // Ignore + } + + @Override + public int getIntrinsicWidth() { + return mWidth; + } + + @Override + public int getIntrinsicHeight() { + return mHeight; + } + } +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/LatinKeyboardBaseView.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/LatinKeyboardBaseView.java new file mode 100644 index 00000000..acad23d0 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/LatinKeyboardBaseView.java @@ -0,0 +1,1503 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package keepass2android.softkeyboard; + +import android.content.Context; +import android.content.pm.PackageManager; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Paint.Align; +import android.graphics.PorterDuff; +import android.graphics.Rect; +import android.graphics.Region.Op; +import android.graphics.Typeface; +import android.graphics.drawable.Drawable; +import android.inputmethodservice.Keyboard; +import android.inputmethodservice.Keyboard.Key; +import android.os.Handler; +import android.os.Message; +import android.os.SystemClock; +import android.util.AttributeSet; +import android.util.Log; +import android.util.TypedValue; +import android.view.GestureDetector; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup.LayoutParams; +import android.widget.PopupWindow; +import android.widget.TextView; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; +import java.util.WeakHashMap; + +/** + * A view that renders a virtual {@link LatinKeyboard}. It handles rendering of keys and + * detecting key presses and touch movements. + * + * TODO: References to LatinKeyboard in this class should be replaced with ones to its base class. + * + * @attr ref R.styleable#LatinKeyboardBaseView_keyBackground + * @attr ref R.styleable#LatinKeyboardBaseView_keyPreviewLayout + * @attr ref R.styleable#LatinKeyboardBaseView_keyPreviewOffset + * @attr ref R.styleable#LatinKeyboardBaseView_labelTextSize + * @attr ref R.styleable#LatinKeyboardBaseView_keyTextSize + * @attr ref R.styleable#LatinKeyboardBaseView_keyTextColor + * @attr ref R.styleable#LatinKeyboardBaseView_verticalCorrection + * @attr ref R.styleable#LatinKeyboardBaseView_popupLayout + */ +public class LatinKeyboardBaseView extends View implements PointerTracker.UIProxy { + private static final String TAG = "LatinKeyboardBaseView"; + private static final boolean DEBUG = false; + + public static final int NOT_A_TOUCH_COORDINATE = -1; + + public interface OnKeyboardActionListener { + + /** + * Called when the user presses a key. This is sent before the + * {@link #onKey} is called. For keys that repeat, this is only + * called once. + * + * @param primaryCode + * the unicode of the key being pressed. If the touch is + * not on a valid key, the value will be zero. + */ + void onPress(int primaryCode); + + /** + * Called when the user releases a key. This is sent after the + * {@link #onKey} is called. For keys that repeat, this is only + * called once. + * + * @param primaryCode + * the code of the key that was released + */ + void onRelease(int primaryCode); + + /** + * Send a key press to the listener. + * + * @param primaryCode + * this is the key that was pressed + * @param keyCodes + * the codes for all the possible alternative keys with + * the primary code being the first. If the primary key + * code is a single character such as an alphabet or + * number or symbol, the alternatives will include other + * characters that may be on the same key or adjacent + * keys. These codes are useful to correct for + * accidental presses of a key adjacent to the intended + * key. + * @param x + * x-coordinate pixel of touched event. If onKey is not called by onTouchEvent, + * the value should be NOT_A_TOUCH_COORDINATE. + * @param y + * y-coordinate pixel of touched event. If onKey is not called by onTouchEvent, + * the value should be NOT_A_TOUCH_COORDINATE. + */ + void onKey(int primaryCode, int[] keyCodes, int x, int y); + + /** + * Sends a sequence of characters to the listener. + * + * @param text + * the sequence of characters to be displayed. + */ + void onText(CharSequence text); + + /** + * Called when user released a finger outside any key. + */ + void onCancel(); + + /** + * Called when the user quickly moves the finger from right to + * left. + */ + void swipeLeft(); + + /** + * Called when the user quickly moves the finger from left to + * right. + */ + void swipeRight(); + + /** + * Called when the user quickly moves the finger from up to down. + */ + void swipeDown(); + + /** + * Called when the user quickly moves the finger from down to up. + */ + void swipeUp(); + } + + // Timing constants + private final int mKeyRepeatInterval; + + // Miscellaneous constants + /* package */ static final int NOT_A_KEY = -1; + private static final int[] LONG_PRESSABLE_STATE_SET = { android.R.attr.state_long_pressable }; + private static final int NUMBER_HINT_VERTICAL_ADJUSTMENT_PIXEL = -1; + + // XML attribute + private int mKeyTextSize; + private int mKeyTextColor; + private Typeface mKeyTextStyle = Typeface.DEFAULT; + private int mLabelTextSize; + private int mSymbolColorScheme = 0; + private int mShadowColor; + private float mShadowRadius; + private Drawable mKeyBackground; + private float mBackgroundDimAmount; + private float mKeyHysteresisDistance; + private float mVerticalCorrection; + private int mPreviewOffset; + private int mPreviewHeight; + private int mPopupLayout; + + // Main keyboard + private Keyboard mKeyboard; + private Key[] mKeys; + // TODO this attribute should be gotten from Keyboard. + private int mKeyboardVerticalGap; + + // Key preview popup + private TextView mPreviewText; + private PopupWindow mPreviewPopup; + private int mPreviewTextSizeLarge; + private int[] mOffsetInWindow; + private int mOldPreviewKeyIndex = NOT_A_KEY; + private boolean mShowPreview = true; + private boolean mShowTouchPoints = true; + private int mPopupPreviewOffsetX; + private int mPopupPreviewOffsetY; + private int mWindowY; + private int mPopupPreviewDisplayedY; + private final int mDelayBeforePreview; + private final int mDelayAfterPreview; + + // Popup mini keyboard + private PopupWindow mMiniKeyboardPopup; + private LatinKeyboardBaseView mMiniKeyboard; + private View mMiniKeyboardParent; + private final WeakHashMap mMiniKeyboardCache = new WeakHashMap(); + private int mMiniKeyboardOriginX; + private int mMiniKeyboardOriginY; + private long mMiniKeyboardPopupTime; + private int[] mWindowOffset; + private final float mMiniKeyboardSlideAllowance; + private int mMiniKeyboardTrackerId; + + /** Listener for {@link OnKeyboardActionListener}. */ + private OnKeyboardActionListener mKeyboardActionListener; + + private final ArrayList mPointerTrackers = new ArrayList(); + + // TODO: Let the PointerTracker class manage this pointer queue + private final PointerQueue mPointerQueue = new PointerQueue(); + + private final boolean mHasDistinctMultitouch; + private int mOldPointerCount = 1; + + protected KeyDetector mKeyDetector = new ProximityKeyDetector(); + + // Swipe gesture detector + private GestureDetector mGestureDetector; + private final SwipeTracker mSwipeTracker = new SwipeTracker(); + private final int mSwipeThreshold; + private final boolean mDisambiguateSwipe; + + // Drawing + /** Whether the keyboard bitmap needs to be redrawn before it's blitted. **/ + private boolean mDrawPending; + /** The dirty region in the keyboard bitmap */ + private final Rect mDirtyRect = new Rect(); + /** The keyboard bitmap for faster updates */ + private Bitmap mBuffer; + /** Notes if the keyboard just changed, so that we could possibly reallocate the mBuffer. */ + private boolean mKeyboardChanged; + private Key mInvalidatedKey; + /** The canvas for the above mutable keyboard bitmap */ + private Canvas mCanvas; + private final Paint mPaint; + private final Rect mPadding; + private final Rect mClipRegion = new Rect(0, 0, 0, 0); + // This map caches key label text height in pixel as value and key label text size as map key. + private final HashMap mTextHeightCache = new HashMap(); + // Distance from horizontal center of the key, proportional to key label text height. + private final float KEY_LABEL_VERTICAL_ADJUSTMENT_FACTOR = 0.55f; + private final String KEY_LABEL_HEIGHT_REFERENCE_CHAR = "H"; + + private final UIHandler mHandler = new UIHandler(); + + class UIHandler extends Handler { + private static final int MSG_POPUP_PREVIEW = 1; + private static final int MSG_DISMISS_PREVIEW = 2; + private static final int MSG_REPEAT_KEY = 3; + private static final int MSG_LONGPRESS_KEY = 4; + + private boolean mInKeyRepeat; + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_POPUP_PREVIEW: + showKey(msg.arg1, (PointerTracker)msg.obj); + break; + case MSG_DISMISS_PREVIEW: + mPreviewPopup.dismiss(); + break; + case MSG_REPEAT_KEY: { + final PointerTracker tracker = (PointerTracker)msg.obj; + tracker.repeatKey(msg.arg1); + startKeyRepeatTimer(mKeyRepeatInterval, msg.arg1, tracker); + break; + } + case MSG_LONGPRESS_KEY: { + final PointerTracker tracker = (PointerTracker)msg.obj; + openPopupIfRequired(msg.arg1, tracker); + break; + } + } + } + + public void popupPreview(long delay, int keyIndex, PointerTracker tracker) { + removeMessages(MSG_POPUP_PREVIEW); + if (mPreviewPopup.isShowing() && mPreviewText.getVisibility() == VISIBLE) { + // Show right away, if it's already visible and finger is moving around + showKey(keyIndex, tracker); + } else { + sendMessageDelayed(obtainMessage(MSG_POPUP_PREVIEW, keyIndex, 0, tracker), + delay); + } + } + + public void cancelPopupPreview() { + removeMessages(MSG_POPUP_PREVIEW); + } + + public void dismissPreview(long delay) { + if (mPreviewPopup.isShowing()) { + sendMessageDelayed(obtainMessage(MSG_DISMISS_PREVIEW), delay); + } + } + + public void cancelDismissPreview() { + removeMessages(MSG_DISMISS_PREVIEW); + } + + public void startKeyRepeatTimer(long delay, int keyIndex, PointerTracker tracker) { + mInKeyRepeat = true; + sendMessageDelayed(obtainMessage(MSG_REPEAT_KEY, keyIndex, 0, tracker), delay); + } + + public void cancelKeyRepeatTimer() { + mInKeyRepeat = false; + removeMessages(MSG_REPEAT_KEY); + } + + public boolean isInKeyRepeat() { + return mInKeyRepeat; + } + + public void startLongPressTimer(long delay, int keyIndex, PointerTracker tracker) { + removeMessages(MSG_LONGPRESS_KEY); + sendMessageDelayed(obtainMessage(MSG_LONGPRESS_KEY, keyIndex, 0, tracker), delay); + } + + public void cancelLongPressTimer() { + removeMessages(MSG_LONGPRESS_KEY); + } + + public void cancelKeyTimers() { + cancelKeyRepeatTimer(); + cancelLongPressTimer(); + } + + public void cancelAllMessages() { + cancelKeyTimers(); + cancelPopupPreview(); + cancelDismissPreview(); + } + } + + static class PointerQueue { + private LinkedList mQueue = new LinkedList(); + + public void add(PointerTracker tracker) { + mQueue.add(tracker); + } + + public int lastIndexOf(PointerTracker tracker) { + LinkedList queue = mQueue; + for (int index = queue.size() - 1; index >= 0; index--) { + PointerTracker t = queue.get(index); + if (t == tracker) + return index; + } + return -1; + } + + public void releaseAllPointersOlderThan(PointerTracker tracker, long eventTime) { + LinkedList queue = mQueue; + int oldestPos = 0; + for (PointerTracker t = queue.get(oldestPos); t != tracker; t = queue.get(oldestPos)) { + if (t.isModifier()) { + oldestPos++; + } else { + t.onUpEvent(t.getLastX(), t.getLastY(), eventTime); + t.setAlreadyProcessed(); + queue.remove(oldestPos); + } + } + } + + public void releaseAllPointersExcept(PointerTracker tracker, long eventTime) { + for (PointerTracker t : mQueue) { + if (t == tracker) + continue; + t.onUpEvent(t.getLastX(), t.getLastY(), eventTime); + t.setAlreadyProcessed(); + } + mQueue.clear(); + if (tracker != null) + mQueue.add(tracker); + } + + public void remove(PointerTracker tracker) { + mQueue.remove(tracker); + } + + public boolean isInSlidingKeyInput() { + for (final PointerTracker tracker : mQueue) { + if (tracker.isInSlidingKeyInput()) + return true; + } + return false; + } + } + + public LatinKeyboardBaseView(Context context, AttributeSet attrs) { + this(context, attrs, R.attr.keyboardViewStyle); + } + + public LatinKeyboardBaseView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + TypedArray a = context.obtainStyledAttributes( + attrs, R.styleable.LatinKeyboardBaseView, defStyle, R.style.LatinKeyboardBaseView); + LayoutInflater inflate = + (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + int previewLayout = 0; + int keyTextSize = 0; + + int n = a.getIndexCount(); + + for (int i = 0; i < n; i++) { + int attr = a.getIndex(i); + + if (attr == R.styleable.LatinKeyboardBaseView_keyBackground) + mKeyBackground = a.getDrawable(attr); + else if (attr == R.styleable.LatinKeyboardBaseView_keyHysteresisDistance) + mKeyHysteresisDistance = a.getDimensionPixelOffset(attr, 0); + else if (attr == R.styleable.LatinKeyboardBaseView_verticalCorrection) + mVerticalCorrection = a.getDimensionPixelOffset(attr, 0); + else if (attr == R.styleable.LatinKeyboardBaseView_keyPreviewLayout) + previewLayout = a.getResourceId(attr, 0); + else if (attr == R.styleable.LatinKeyboardBaseView_keyPreviewOffset) + mPreviewOffset = a.getDimensionPixelOffset(attr, 0); + else if (attr == R.styleable.LatinKeyboardBaseView_keyPreviewHeight) + mPreviewHeight = a.getDimensionPixelSize(attr, 80); + else if (attr == R.styleable.LatinKeyboardBaseView_keyTextSize) + mKeyTextSize = a.getDimensionPixelSize(attr, 18); + else if (attr == R.styleable.LatinKeyboardBaseView_keyTextColor) + mKeyTextColor = a.getColor(attr, 0xFF000000); + else if (attr == R.styleable.LatinKeyboardBaseView_labelTextSize) + mLabelTextSize = a.getDimensionPixelSize(attr, 14); + else if (attr == R.styleable.LatinKeyboardBaseView_popupLayout) + mPopupLayout = a.getResourceId(attr, 0); + else if (attr == R.styleable.LatinKeyboardBaseView_shadowColor) + mShadowColor = a.getColor(attr, 0); + else if (attr == R.styleable.LatinKeyboardBaseView_shadowRadius) + mShadowRadius = a.getFloat(attr, 0f); + // TODO: Use Theme (android.R.styleable.Theme_backgroundDimAmount) + else if (attr == R.styleable.LatinKeyboardBaseView_backgroundDimAmount) + mBackgroundDimAmount = a.getFloat(attr, 0.5f); + //case android.R.styleable. + else if (attr == R.styleable.LatinKeyboardBaseView_keyTextStyle) { + int textStyle = a.getInt(attr, 0); + switch (textStyle) { + case 0: + mKeyTextStyle = Typeface.DEFAULT; + break; + case 1: + mKeyTextStyle = Typeface.DEFAULT_BOLD; + break; + default: + mKeyTextStyle = Typeface.defaultFromStyle(textStyle); + break; + } + + } + else if (attr == R.styleable.LatinKeyboardBaseView_symbolColorScheme) + mSymbolColorScheme = a.getInt(attr, 0); + + } + + final Resources res = getResources(); + + mPreviewPopup = new PopupWindow(context); + if (previewLayout != 0) { + mPreviewText = (TextView) inflate.inflate(previewLayout, null); + mPreviewTextSizeLarge = (int) res.getDimension(R.dimen.key_preview_text_size_large); + mPreviewPopup.setContentView(mPreviewText); + mPreviewPopup.setBackgroundDrawable(null); + } else { + mShowPreview = false; + } + mPreviewPopup.setTouchable(false); + mPreviewPopup.setAnimationStyle(R.style.KeyPreviewAnimation); + mDelayBeforePreview = res.getInteger(R.integer.config_delay_before_preview); + mDelayAfterPreview = res.getInteger(R.integer.config_delay_after_preview); + + mMiniKeyboardParent = this; + mMiniKeyboardPopup = new PopupWindow(context); + mMiniKeyboardPopup.setBackgroundDrawable(null); + mMiniKeyboardPopup.setAnimationStyle(R.style.MiniKeyboardAnimation); + + mPaint = new Paint(); + mPaint.setAntiAlias(true); + mPaint.setTextSize(keyTextSize); + mPaint.setTextAlign(Align.CENTER); + mPaint.setAlpha(255); + + mPadding = new Rect(0, 0, 0, 0); + mKeyBackground.getPadding(mPadding); + + mSwipeThreshold = (int) (500 * res.getDisplayMetrics().density); + // TODO: Refer frameworks/base/core/res/res/values/config.xml + mDisambiguateSwipe = res.getBoolean(R.bool.config_swipeDisambiguation); + mMiniKeyboardSlideAllowance = res.getDimension(R.dimen.mini_keyboard_slide_allowance); + + GestureDetector.SimpleOnGestureListener listener = + new GestureDetector.SimpleOnGestureListener() { + @Override + public boolean onFling(MotionEvent me1, MotionEvent me2, float velocityX, + float velocityY) { + final float absX = Math.abs(velocityX); + final float absY = Math.abs(velocityY); + float deltaX = me2.getX() - me1.getX(); + float deltaY = me2.getY() - me1.getY(); + int travelX = getWidth() / 2; // Half the keyboard width + int travelY = getHeight() / 2; // Half the keyboard height + mSwipeTracker.computeCurrentVelocity(1000); + final float endingVelocityX = mSwipeTracker.getXVelocity(); + final float endingVelocityY = mSwipeTracker.getYVelocity(); + if (velocityX > mSwipeThreshold && absY < absX && deltaX > travelX) { + if (mDisambiguateSwipe && endingVelocityX >= velocityX / 4) { + swipeRight(); + return true; + } + } else if (velocityX < -mSwipeThreshold && absY < absX && deltaX < -travelX) { + if (mDisambiguateSwipe && endingVelocityX <= velocityX / 4) { + swipeLeft(); + return true; + } + } else if (velocityY < -mSwipeThreshold && absX < absY && deltaY < -travelY) { + if (mDisambiguateSwipe && endingVelocityY <= velocityY / 4) { + swipeUp(); + return true; + } + } else if (velocityY > mSwipeThreshold && absX < absY / 2 && deltaY > travelY) { + if (mDisambiguateSwipe && endingVelocityY >= velocityY / 4) { + swipeDown(); + return true; + } + } + return false; + } + }; + + final boolean ignoreMultitouch = true; + mGestureDetector = new GestureDetector(getContext(), listener, null, ignoreMultitouch); + mGestureDetector.setIsLongpressEnabled(false); + + mHasDistinctMultitouch = context.getPackageManager() + .hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT); + mKeyRepeatInterval = res.getInteger(R.integer.config_key_repeat_interval); + } + + public void setOnKeyboardActionListener(OnKeyboardActionListener listener) { + mKeyboardActionListener = listener; + for (PointerTracker tracker : mPointerTrackers) { + tracker.setOnKeyboardActionListener(listener); + } + } + + /** + * Returns the {@link OnKeyboardActionListener} object. + * @return the listener attached to this keyboard + */ + protected OnKeyboardActionListener getOnKeyboardActionListener() { + return mKeyboardActionListener; + } + + /** + * Attaches a keyboard to this view. The keyboard can be switched at any time and the + * view will re-layout itself to accommodate the keyboard. + * @see Keyboard + * @see #getKeyboard() + * @param keyboard the keyboard to display in this view + */ + public void setKeyboard(Keyboard keyboard) { + if (mKeyboard != null) { + dismissKeyPreview(); + } + // Remove any pending messages, except dismissing preview + mHandler.cancelKeyTimers(); + mHandler.cancelPopupPreview(); + mKeyboard = keyboard; + LatinImeLogger.onSetKeyboard(keyboard); + mKeys = mKeyDetector.setKeyboard(keyboard, -getPaddingLeft(), + -getPaddingTop() + mVerticalCorrection); + mKeyboardVerticalGap = (int)getResources().getDimension(R.dimen.key_bottom_gap); + for (PointerTracker tracker : mPointerTrackers) { + tracker.setKeyboard(mKeys, mKeyHysteresisDistance); + } + requestLayout(); + // Hint to reallocate the buffer if the size changed + mKeyboardChanged = true; + invalidateAllKeys(); + computeProximityThreshold(keyboard); + mMiniKeyboardCache.clear(); + } + + /** + * Returns the current keyboard being displayed by this view. + * @return the currently attached keyboard + * @see #setKeyboard(Keyboard) + */ + public Keyboard getKeyboard() { + return mKeyboard; + } + + /** + * Return whether the device has distinct multi-touch panel. + * @return true if the device has distinct multi-touch panel. + */ + public boolean hasDistinctMultitouch() { + return mHasDistinctMultitouch; + } + + /** + * Sets the state of the shift key of the keyboard, if any. + * @param shifted whether or not to enable the state of the shift key + * @return true if the shift key state changed, false if there was no change + */ + public boolean setShifted(boolean shifted) { + if (mKeyboard != null) { + if (mKeyboard.setShifted(shifted)) { + // The whole keyboard probably needs to be redrawn + invalidateAllKeys(); + return true; + } + } + return false; + } + + /** + * Returns the state of the shift key of the keyboard, if any. + * @return true if the shift is in a pressed state, false otherwise. If there is + * no shift key on the keyboard or there is no keyboard attached, it returns false. + */ + public boolean isShifted() { + if (mKeyboard != null) { + return mKeyboard.isShifted(); + } + return false; + } + + /** + * Enables or disables the key feedback popup. This is a popup that shows a magnified + * version of the depressed key. By default the preview is enabled. + * @param previewEnabled whether or not to enable the key feedback popup + * @see #isPreviewEnabled() + */ + public void setPreviewEnabled(boolean previewEnabled) { + mShowPreview = previewEnabled; + } + + /** + * Returns the enabled state of the key feedback popup. + * @return whether or not the key feedback popup is enabled + * @see #setPreviewEnabled(boolean) + */ + public boolean isPreviewEnabled() { + return mShowPreview; + } + + public int getSymbolColorScheme() { + return mSymbolColorScheme; + } + + public void setPopupParent(View v) { + mMiniKeyboardParent = v; + } + + public void setPopupOffset(int x, int y) { + mPopupPreviewOffsetX = x; + mPopupPreviewOffsetY = y; + mPreviewPopup.dismiss(); + } + + /** + * When enabled, calls to {@link OnKeyboardActionListener#onKey} will include key + * codes for adjacent keys. When disabled, only the primary key code will be + * reported. + * @param enabled whether or not the proximity correction is enabled + */ + public void setProximityCorrectionEnabled(boolean enabled) { + mKeyDetector.setProximityCorrectionEnabled(enabled); + } + + /** + * Returns true if proximity correction is enabled. + */ + public boolean isProximityCorrectionEnabled() { + return mKeyDetector.isProximityCorrectionEnabled(); + } + + protected Locale getKeyboardLocale() { + if (mKeyboard instanceof LatinKeyboard) { + return ((LatinKeyboard)mKeyboard).getInputLocale(); + } else { + return getContext().getResources().getConfiguration().locale; + } + } + + protected CharSequence adjustCase(CharSequence label) { + if (mKeyboard.isShifted() && label != null && label.length() < 3 + && Character.isLowerCase(label.charAt(0))) { + return label.toString().toUpperCase(getKeyboardLocale()); + } + return label; + } + + @Override + public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + // Round up a little + if (mKeyboard == null) { + setMeasuredDimension( + getPaddingLeft() + getPaddingRight(), getPaddingTop() + getPaddingBottom()); + } else { + int width = mKeyboard.getMinWidth() + getPaddingLeft() + getPaddingRight(); + if (MeasureSpec.getSize(widthMeasureSpec) < width + 10) { + width = MeasureSpec.getSize(widthMeasureSpec); + } + setMeasuredDimension( + width, mKeyboard.getHeight() + getPaddingTop() + getPaddingBottom()); + } + } + + /** + * Compute the average distance between adjacent keys (horizontally and vertically) + * and square it to get the proximity threshold. We use a square here and in computing + * the touch distance from a key's center to avoid taking a square root. + * @param keyboard + */ + private void computeProximityThreshold(Keyboard keyboard) { + if (keyboard == null) return; + final Key[] keys = mKeys; + if (keys == null) return; + int length = keys.length; + int dimensionSum = 0; + for (int i = 0; i < length; i++) { + Key key = keys[i]; + dimensionSum += Math.min(key.width, key.height + mKeyboardVerticalGap) + key.gap; + } + if (dimensionSum < 0 || length == 0) return; + mKeyDetector.setProximityThreshold((int) (dimensionSum * 1.4f / length)); + } + + @Override + public void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + // Release the buffer, if any and it will be reallocated on the next draw + mBuffer = null; + } + + @Override + public void onDraw(Canvas canvas) { + super.onDraw(canvas); + if (mDrawPending || mBuffer == null || mKeyboardChanged) { + onBufferDraw(); + } + canvas.drawBitmap(mBuffer, 0, 0, null); + } + + private void onBufferDraw() { + if (mBuffer == null || mKeyboardChanged) { + if (mBuffer == null || mKeyboardChanged && + (mBuffer.getWidth() != getWidth() || mBuffer.getHeight() != getHeight())) { + // Make sure our bitmap is at least 1x1 + final int width = Math.max(1, getWidth()); + final int height = Math.max(1, getHeight()); + mBuffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + mCanvas = new Canvas(mBuffer); + } + invalidateAllKeys(); + mKeyboardChanged = false; + } + final Canvas canvas = mCanvas; + canvas.clipRect(mDirtyRect, Op.REPLACE); + + if (mKeyboard == null) return; + + final Paint paint = mPaint; + final Drawable keyBackground = mKeyBackground; + final Rect clipRegion = mClipRegion; + final Rect padding = mPadding; + final int kbdPaddingLeft = getPaddingLeft(); + final int kbdPaddingTop = getPaddingTop(); + final Key[] keys = mKeys; + final Key invalidKey = mInvalidatedKey; + + paint.setColor(mKeyTextColor); + boolean drawSingleKey = false; + if (invalidKey != null && canvas.getClipBounds(clipRegion)) { + // TODO we should use Rect.inset and Rect.contains here. + // Is clipRegion completely contained within the invalidated key? + if (invalidKey.x + kbdPaddingLeft - 1 <= clipRegion.left && + invalidKey.y + kbdPaddingTop - 1 <= clipRegion.top && + invalidKey.x + invalidKey.width + kbdPaddingLeft + 1 >= clipRegion.right && + invalidKey.y + invalidKey.height + kbdPaddingTop + 1 >= clipRegion.bottom) { + drawSingleKey = true; + } + } + canvas.drawColor(0x00000000, PorterDuff.Mode.CLEAR); + final int keyCount = keys.length; + for (int i = 0; i < keyCount; i++) { + final Key key = keys[i]; + if (drawSingleKey && invalidKey != key) { + continue; + } + int[] drawableState = key.getCurrentDrawableState(); + keyBackground.setState(drawableState); + + // Switch the character to uppercase if shift is pressed + String label = key.label == null? null : adjustCase(key.label).toString(); + + final Rect bounds = keyBackground.getBounds(); + if (key.width != bounds.right || key.height != bounds.bottom) { + keyBackground.setBounds(0, 0, key.width, key.height); + } + canvas.translate(key.x + kbdPaddingLeft, key.y + kbdPaddingTop); + keyBackground.draw(canvas); + + boolean shouldDrawIcon = true; + if (label != null) { + // For characters, use large font. For labels like "Done", use small font. + final int labelSize; + if (label.length() > 1 && key.codes.length < 2) { + labelSize = mLabelTextSize; + paint.setTypeface(Typeface.DEFAULT_BOLD); + } else { + labelSize = mKeyTextSize; + paint.setTypeface(mKeyTextStyle); + } + paint.setTextSize(labelSize); + + Integer labelHeightValue = mTextHeightCache.get(labelSize); + final int labelHeight; + if (labelHeightValue != null) { + labelHeight = labelHeightValue; + } else { + Rect textBounds = new Rect(); + paint.getTextBounds(KEY_LABEL_HEIGHT_REFERENCE_CHAR, 0, 1, textBounds); + labelHeight = textBounds.height(); + mTextHeightCache.put(labelSize, labelHeight); + } + + // Draw a drop shadow for the text + paint.setShadowLayer(mShadowRadius, 0, 0, mShadowColor); + final int centerX = (key.width + padding.left - padding.right) / 2; + final int centerY = (key.height + padding.top - padding.bottom) / 2; + final float baseline = centerY + + labelHeight * KEY_LABEL_VERTICAL_ADJUSTMENT_FACTOR; + canvas.drawText(label, centerX, baseline, paint); + // Turn off drop shadow + paint.setShadowLayer(0, 0, 0, 0); + + // Usually don't draw icon if label is not null, but we draw icon for the number + // hint and popup hint. + shouldDrawIcon = shouldDrawLabelAndIcon(key); + } + if (key.icon != null && shouldDrawIcon) { + // Special handing for the upper-right number hint icons + final int drawableWidth; + final int drawableHeight; + final int drawableX; + final int drawableY; + if (shouldDrawIconFully(key)) { + drawableWidth = key.width; + drawableHeight = key.height; + drawableX = 0; + drawableY = NUMBER_HINT_VERTICAL_ADJUSTMENT_PIXEL; + } else { + drawableWidth = key.icon.getIntrinsicWidth(); + drawableHeight = key.icon.getIntrinsicHeight(); + drawableX = (key.width + padding.left - padding.right - drawableWidth) / 2; + drawableY = (key.height + padding.top - padding.bottom - drawableHeight) / 2; + } + canvas.translate(drawableX, drawableY); + key.icon.setBounds(0, 0, drawableWidth, drawableHeight); + key.icon.draw(canvas); + canvas.translate(-drawableX, -drawableY); + } + canvas.translate(-key.x - kbdPaddingLeft, -key.y - kbdPaddingTop); + } + mInvalidatedKey = null; + // Overlay a dark rectangle to dim the keyboard + if (mMiniKeyboard != null) { + paint.setColor((int) (mBackgroundDimAmount * 0xFF) << 24); + canvas.drawRect(0, 0, getWidth(), getHeight(), paint); + } + + if (DEBUG) { + if (mShowTouchPoints) { + for (PointerTracker tracker : mPointerTrackers) { + int startX = tracker.getStartX(); + int startY = tracker.getStartY(); + int lastX = tracker.getLastX(); + int lastY = tracker.getLastY(); + paint.setAlpha(128); + paint.setColor(0xFFFF0000); + canvas.drawCircle(startX, startY, 3, paint); + canvas.drawLine(startX, startY, lastX, lastY, paint); + paint.setColor(0xFF0000FF); + canvas.drawCircle(lastX, lastY, 3, paint); + paint.setColor(0xFF00FF00); + canvas.drawCircle((startX + lastX) / 2, (startY + lastY) / 2, 2, paint); + } + } + } + + mDrawPending = false; + mDirtyRect.setEmpty(); + } + + // TODO: clean up this method. + private void dismissKeyPreview() { + for (PointerTracker tracker : mPointerTrackers) + tracker.updateKey(NOT_A_KEY); + showPreview(NOT_A_KEY, null); + } + + public void showPreview(int keyIndex, PointerTracker tracker) { + int oldKeyIndex = mOldPreviewKeyIndex; + mOldPreviewKeyIndex = keyIndex; + final boolean isLanguageSwitchEnabled = (mKeyboard instanceof LatinKeyboard) + && ((LatinKeyboard)mKeyboard).isLanguageSwitchEnabled(); + // We should re-draw popup preview when 1) we need to hide the preview, 2) we will show + // the space key preview and 3) pointer moves off the space key to other letter key, we + // should hide the preview of the previous key. + final boolean hidePreviewOrShowSpaceKeyPreview = (tracker == null) + || tracker.isSpaceKey(keyIndex) || tracker.isSpaceKey(oldKeyIndex); + // If key changed and preview is on or the key is space (language switch is enabled) + if (oldKeyIndex != keyIndex + && (mShowPreview + || (hidePreviewOrShowSpaceKeyPreview && isLanguageSwitchEnabled))) { + if (keyIndex == NOT_A_KEY) { + mHandler.cancelPopupPreview(); + mHandler.dismissPreview(mDelayAfterPreview); + } else if (tracker != null) { + mHandler.popupPreview(mDelayBeforePreview, keyIndex, tracker); + } + } + } + + private void showKey(final int keyIndex, PointerTracker tracker) { + Key key = tracker.getKey(keyIndex); + if (key == null) + return; + // Should not draw hint icon in key preview + if (key.icon != null && !shouldDrawLabelAndIcon(key)) { + mPreviewText.setCompoundDrawables(null, null, null, + key.iconPreview != null ? key.iconPreview : key.icon); + mPreviewText.setText(null); + } else { + mPreviewText.setCompoundDrawables(null, null, null, null); + mPreviewText.setText(adjustCase(tracker.getPreviewText(key))); + if (key.label.length() > 1 && key.codes.length < 2) { + mPreviewText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mKeyTextSize); + mPreviewText.setTypeface(Typeface.DEFAULT_BOLD); + } else { + mPreviewText.setTextSize(TypedValue.COMPLEX_UNIT_PX, mPreviewTextSizeLarge); + mPreviewText.setTypeface(mKeyTextStyle); + } + } + mPreviewText.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), + MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); + int popupWidth = Math.max(mPreviewText.getMeasuredWidth(), key.width + + mPreviewText.getPaddingLeft() + mPreviewText.getPaddingRight()); + final int popupHeight = mPreviewHeight; + LayoutParams lp = mPreviewText.getLayoutParams(); + if (lp != null) { + lp.width = popupWidth; + lp.height = popupHeight; + } + + int popupPreviewX = key.x - (popupWidth - key.width) / 2; + int popupPreviewY = key.y - popupHeight + mPreviewOffset; + + mHandler.cancelDismissPreview(); + if (mOffsetInWindow == null) { + mOffsetInWindow = new int[2]; + getLocationInWindow(mOffsetInWindow); + mOffsetInWindow[0] += mPopupPreviewOffsetX; // Offset may be zero + mOffsetInWindow[1] += mPopupPreviewOffsetY; // Offset may be zero + int[] windowLocation = new int[2]; + getLocationOnScreen(windowLocation); + mWindowY = windowLocation[1]; + } + // Set the preview background state + mPreviewText.getBackground().setState( + key.popupResId != 0 ? LONG_PRESSABLE_STATE_SET : EMPTY_STATE_SET); + popupPreviewX += mOffsetInWindow[0]; + popupPreviewY += mOffsetInWindow[1]; + + // If the popup cannot be shown above the key, put it on the side + if (popupPreviewY + mWindowY < 0) { + // If the key you're pressing is on the left side of the keyboard, show the popup on + // the right, offset by enough to see at least one key to the left/right. + if (key.x + key.width <= getWidth() / 2) { + popupPreviewX += (int) (key.width * 2.5); + } else { + popupPreviewX -= (int) (key.width * 2.5); + } + popupPreviewY += popupHeight; + } + + if (mPreviewPopup.isShowing()) { + mPreviewPopup.update(popupPreviewX, popupPreviewY, popupWidth, popupHeight); + } else { + mPreviewPopup.setWidth(popupWidth); + mPreviewPopup.setHeight(popupHeight); + mPreviewPopup.showAtLocation(mMiniKeyboardParent, Gravity.NO_GRAVITY, + popupPreviewX, popupPreviewY); + } + // Record popup preview position to display mini-keyboard later at the same positon + mPopupPreviewDisplayedY = popupPreviewY; + mPreviewText.setVisibility(VISIBLE); + } + + /** + * Requests a redraw of the entire keyboard. Calling {@link #invalidate} is not sufficient + * because the keyboard renders the keys to an off-screen buffer and an invalidate() only + * draws the cached buffer. + * @see #invalidateKey(Key) + */ + public void invalidateAllKeys() { + mDirtyRect.union(0, 0, getWidth(), getHeight()); + mDrawPending = true; + invalidate(); + } + + /** + * Invalidates a key so that it will be redrawn on the next repaint. Use this method if only + * one key is changing it's content. Any changes that affect the position or size of the key + * may not be honored. + * @param key key in the attached {@link Keyboard}. + * @see #invalidateAllKeys + */ + public void invalidateKey(Key key) { + if (key == null) + return; + mInvalidatedKey = key; + // TODO we should clean up this and record key's region to use in onBufferDraw. + mDirtyRect.union(key.x + getPaddingLeft(), key.y + getPaddingTop(), + key.x + key.width + getPaddingLeft(), key.y + key.height + getPaddingTop()); + onBufferDraw(); + invalidate(key.x + getPaddingLeft(), key.y + getPaddingTop(), + key.x + key.width + getPaddingLeft(), key.y + key.height + getPaddingTop()); + } + + private boolean openPopupIfRequired(int keyIndex, PointerTracker tracker) { + // Check if we have a popup layout specified first. + if (mPopupLayout == 0) { + return false; + } + + Key popupKey = tracker.getKey(keyIndex); + if (popupKey == null) + return false; + boolean result = onLongPress(popupKey); + if (result) { + dismissKeyPreview(); + mMiniKeyboardTrackerId = tracker.mPointerId; + // Mark this tracker "already processed" and remove it from the pointer queue + tracker.setAlreadyProcessed(); + mPointerQueue.remove(tracker); + } + return result; + } + + private View inflateMiniKeyboardContainer(Key popupKey) { + int popupKeyboardId = popupKey.popupResId; + LayoutInflater inflater = (LayoutInflater)getContext().getSystemService( + Context.LAYOUT_INFLATER_SERVICE); + View container = inflater.inflate(mPopupLayout, null); + if (container == null) + throw new NullPointerException(); + + LatinKeyboardBaseView miniKeyboard = + (LatinKeyboardBaseView)container.findViewById(R.id.LatinKeyboardBaseView); + miniKeyboard.setOnKeyboardActionListener(new OnKeyboardActionListener() { + public void onKey(int primaryCode, int[] keyCodes, int x, int y) { + mKeyboardActionListener.onKey(primaryCode, keyCodes, x, y); + dismissPopupKeyboard(); + } + + public void onText(CharSequence text) { + mKeyboardActionListener.onText(text); + dismissPopupKeyboard(); + } + + public void onCancel() { + mKeyboardActionListener.onCancel(); + dismissPopupKeyboard(); + } + + public void swipeLeft() { + } + public void swipeRight() { + } + public void swipeUp() { + } + public void swipeDown() { + } + public void onPress(int primaryCode) { + mKeyboardActionListener.onPress(primaryCode); + } + public void onRelease(int primaryCode) { + mKeyboardActionListener.onRelease(primaryCode); + } + }); + // Override default ProximityKeyDetector. + miniKeyboard.mKeyDetector = new MiniKeyboardKeyDetector(mMiniKeyboardSlideAllowance); + // Remove gesture detector on mini-keyboard + miniKeyboard.mGestureDetector = null; + + Keyboard keyboard; + if (popupKey.popupCharacters != null) { + keyboard = new Keyboard(getContext(), popupKeyboardId, popupKey.popupCharacters, + -1, getPaddingLeft() + getPaddingRight()); + } else { + keyboard = new Keyboard(getContext(), popupKeyboardId); + } + miniKeyboard.setKeyboard(keyboard); + miniKeyboard.setPopupParent(this); + + container.measure(MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST), + MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.AT_MOST)); + + return container; + } + + private static boolean isOneRowKeys(List keys) { + if (keys.size() == 0) return false; + final int edgeFlags = keys.get(0).edgeFlags; + // HACK: The first key of mini keyboard which was inflated from xml and has multiple rows, + // does not have both top and bottom edge flags on at the same time. On the other hand, + // the first key of mini keyboard that was created with popupCharacters must have both top + // and bottom edge flags on. + // When you want to use one row mini-keyboard from xml file, make sure that the row has + // both top and bottom edge flags set. + return (edgeFlags & Keyboard.EDGE_TOP) != 0 && (edgeFlags & Keyboard.EDGE_BOTTOM) != 0; + } + + /** + * Called when a key is long pressed. By default this will open any popup keyboard associated + * with this key through the attributes popupLayout and popupCharacters. + * @param popupKey the key that was long pressed + * @return true if the long press is handled, false otherwise. Subclasses should call the + * method on the base class if the subclass doesn't wish to handle the call. + */ + protected boolean onLongPress(Key popupKey) { + // TODO if popupKey.popupCharacters has only one letter, send it as key without opening + // mini keyboard. + + if (popupKey.popupResId == 0) + return false; + + View container = mMiniKeyboardCache.get(popupKey); + if (container == null) { + container = inflateMiniKeyboardContainer(popupKey); + mMiniKeyboardCache.put(popupKey, container); + } + mMiniKeyboard = (LatinKeyboardBaseView)container.findViewById(R.id.LatinKeyboardBaseView); + if (mWindowOffset == null) { + mWindowOffset = new int[2]; + getLocationInWindow(mWindowOffset); + } + + // Get width of a key in the mini popup keyboard = "miniKeyWidth". + // On the other hand, "popupKey.width" is width of the pressed key on the main keyboard. + // We adjust the position of mini popup keyboard with the edge key in it: + // a) When we have the leftmost key in popup keyboard directly above the pressed key + // Right edges of both keys should be aligned for consistent default selection + // b) When we have the rightmost key in popup keyboard directly above the pressed key + // Left edges of both keys should be aligned for consistent default selection + final List miniKeys = mMiniKeyboard.getKeyboard().getKeys(); + final int miniKeyWidth = miniKeys.size() > 0 ? miniKeys.get(0).width : 0; + + // HACK: Have the leftmost number in the popup characters right above the key + boolean isNumberAtLeftmost = + hasMultiplePopupChars(popupKey) && isNumberAtLeftmostPopupChar(popupKey); + int popupX = popupKey.x + mWindowOffset[0]; + popupX += getPaddingLeft(); + if (isNumberAtLeftmost) { + popupX += popupKey.width - miniKeyWidth; // adjustment for a) described above + popupX -= container.getPaddingLeft(); + } else { + popupX += miniKeyWidth; // adjustment for b) described above + popupX -= container.getMeasuredWidth(); + popupX += container.getPaddingRight(); + } + int popupY = popupKey.y + mWindowOffset[1]; + popupY += getPaddingTop(); + popupY -= container.getMeasuredHeight(); + popupY += container.getPaddingBottom(); + final int x = popupX; + final int y = mShowPreview && isOneRowKeys(miniKeys) ? mPopupPreviewDisplayedY : popupY; + + int adjustedX = x; + if (x < 0) { + adjustedX = 0; + } else if (x > (getMeasuredWidth() - container.getMeasuredWidth())) { + adjustedX = getMeasuredWidth() - container.getMeasuredWidth(); + } + mMiniKeyboardOriginX = adjustedX + container.getPaddingLeft() - mWindowOffset[0]; + mMiniKeyboardOriginY = y + container.getPaddingTop() - mWindowOffset[1]; + mMiniKeyboard.setPopupOffset(adjustedX, y); + mMiniKeyboard.setShifted(isShifted()); + // Mini keyboard needs no pop-up key preview displayed. + mMiniKeyboard.setPreviewEnabled(false); + mMiniKeyboardPopup.setContentView(container); + mMiniKeyboardPopup.setWidth(container.getMeasuredWidth()); + mMiniKeyboardPopup.setHeight(container.getMeasuredHeight()); + mMiniKeyboardPopup.showAtLocation(this, Gravity.NO_GRAVITY, x, y); + + // Inject down event on the key to mini keyboard. + long eventTime = SystemClock.uptimeMillis(); + mMiniKeyboardPopupTime = eventTime; + MotionEvent downEvent = generateMiniKeyboardMotionEvent(MotionEvent.ACTION_DOWN, popupKey.x + + popupKey.width / 2, popupKey.y + popupKey.height / 2, eventTime); + mMiniKeyboard.onTouchEvent(downEvent); + downEvent.recycle(); + + invalidateAllKeys(); + return true; + } + + private static boolean hasMultiplePopupChars(Key key) { + if (key.popupCharacters != null && key.popupCharacters.length() > 1) { + return true; + } + return false; + } + + private boolean shouldDrawIconFully(Key key) { + return isNumberAtEdgeOfPopupChars(key) || isLatinF1Key(key) + || LatinKeyboard.hasPuncOrSmileysPopup(key); + } + + private boolean shouldDrawLabelAndIcon(Key key) { + return isNumberAtEdgeOfPopupChars(key) || isNonMicLatinF1Key(key) + || LatinKeyboard.hasPuncOrSmileysPopup(key); + } + + private boolean isLatinF1Key(Key key) { + return (mKeyboard instanceof LatinKeyboard) && ((LatinKeyboard)mKeyboard).isF1Key(key); + } + + private boolean isNonMicLatinF1Key(Key key) { + return isLatinF1Key(key) && key.label != null; + } + + private static boolean isNumberAtEdgeOfPopupChars(Key key) { + return isNumberAtLeftmostPopupChar(key) || isNumberAtRightmostPopupChar(key); + } + + /* package */ static boolean isNumberAtLeftmostPopupChar(Key key) { + if (key.popupCharacters != null && key.popupCharacters.length() > 0 + && isAsciiDigit(key.popupCharacters.charAt(0))) { + return true; + } + return false; + } + + /* package */ static boolean isNumberAtRightmostPopupChar(Key key) { + if (key.popupCharacters != null && key.popupCharacters.length() > 0 + && isAsciiDigit(key.popupCharacters.charAt(key.popupCharacters.length() - 1))) { + return true; + } + return false; + } + + private static boolean isAsciiDigit(char c) { + return (c < 0x80) && Character.isDigit(c); + } + + private MotionEvent generateMiniKeyboardMotionEvent(int action, int x, int y, long eventTime) { + return MotionEvent.obtain(mMiniKeyboardPopupTime, eventTime, action, + x - mMiniKeyboardOriginX, y - mMiniKeyboardOriginY, 0); + } + + private PointerTracker getPointerTracker(final int id) { + final ArrayList pointers = mPointerTrackers; + final Key[] keys = mKeys; + final OnKeyboardActionListener listener = mKeyboardActionListener; + + // Create pointer trackers until we can get 'id+1'-th tracker, if needed. + for (int i = pointers.size(); i <= id; i++) { + final PointerTracker tracker = + new PointerTracker(i, mHandler, mKeyDetector, this, getResources()); + if (keys != null) + tracker.setKeyboard(keys, mKeyHysteresisDistance); + if (listener != null) + tracker.setOnKeyboardActionListener(listener); + pointers.add(tracker); + } + + return pointers.get(id); + } + + public boolean isInSlidingKeyInput() { + if (mMiniKeyboard != null) { + return mMiniKeyboard.isInSlidingKeyInput(); + } else { + return mPointerQueue.isInSlidingKeyInput(); + } + } + + public int getPointerCount() { + return mOldPointerCount; + } + + @Override + public boolean onTouchEvent(MotionEvent me) { + final int action = me.getActionMasked(); + final int pointerCount = me.getPointerCount(); + final int oldPointerCount = mOldPointerCount; + mOldPointerCount = pointerCount; + + // TODO: cleanup this code into a multi-touch to single-touch event converter class? + // If the device does not have distinct multi-touch support panel, ignore all multi-touch + // events except a transition from/to single-touch. + if (!mHasDistinctMultitouch && pointerCount > 1 && oldPointerCount > 1) { + return true; + } + + // Track the last few movements to look for spurious swipes. + mSwipeTracker.addMovement(me); + + // Gesture detector must be enabled only when mini-keyboard is not on the screen. + if (mMiniKeyboard == null + && mGestureDetector != null && mGestureDetector.onTouchEvent(me)) { + dismissKeyPreview(); + mHandler.cancelKeyTimers(); + return true; + } + + final long eventTime = me.getEventTime(); + final int index = me.getActionIndex(); + final int id = me.getPointerId(index); + final int x = (int)me.getX(index); + final int y = (int)me.getY(index); + + // Needs to be called after the gesture detector gets a turn, as it may have + // displayed the mini keyboard + if (mMiniKeyboard != null) { + final int miniKeyboardPointerIndex = me.findPointerIndex(mMiniKeyboardTrackerId); + if (miniKeyboardPointerIndex >= 0 && miniKeyboardPointerIndex < pointerCount) { + final int miniKeyboardX = (int)me.getX(miniKeyboardPointerIndex); + final int miniKeyboardY = (int)me.getY(miniKeyboardPointerIndex); + MotionEvent translated = generateMiniKeyboardMotionEvent(action, + miniKeyboardX, miniKeyboardY, eventTime); + mMiniKeyboard.onTouchEvent(translated); + translated.recycle(); + } + return true; + } + + if (mHandler.isInKeyRepeat()) { + // It will keep being in the key repeating mode while the key is being pressed. + if (action == MotionEvent.ACTION_MOVE) { + return true; + } + final PointerTracker tracker = getPointerTracker(id); + // Key repeating timer will be canceled if 2 or more keys are in action, and current + // event (UP or DOWN) is non-modifier key. + if (pointerCount > 1 && !tracker.isModifier()) { + mHandler.cancelKeyRepeatTimer(); + } + // Up event will pass through. + } + + // TODO: cleanup this code into a multi-touch to single-touch event converter class? + // Translate mutli-touch event to single-touch events on the device that has no distinct + // multi-touch panel. + if (!mHasDistinctMultitouch) { + // Use only main (id=0) pointer tracker. + PointerTracker tracker = getPointerTracker(0); + if (pointerCount == 1 && oldPointerCount == 2) { + // Multi-touch to single touch transition. + // Send a down event for the latest pointer. + tracker.onDownEvent(x, y, eventTime); + } else if (pointerCount == 2 && oldPointerCount == 1) { + // Single-touch to multi-touch transition. + // Send an up event for the last pointer. + tracker.onUpEvent(tracker.getLastX(), tracker.getLastY(), eventTime); + } else if (pointerCount == 1 && oldPointerCount == 1) { + tracker.onTouchEvent(action, x, y, eventTime); + } else { + Log.w(TAG, "Unknown touch panel behavior: pointer count is " + pointerCount + + " (old " + oldPointerCount + ")"); + } + return true; + } + + if (action == MotionEvent.ACTION_MOVE) { + for (int i = 0; i < pointerCount; i++) { + PointerTracker tracker = getPointerTracker(me.getPointerId(i)); + tracker.onMoveEvent((int)me.getX(i), (int)me.getY(i), eventTime); + } + } else { + PointerTracker tracker = getPointerTracker(id); + switch (action) { + case MotionEvent.ACTION_DOWN: + case MotionEvent.ACTION_POINTER_DOWN: + onDownEvent(tracker, x, y, eventTime); + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_POINTER_UP: + onUpEvent(tracker, x, y, eventTime); + break; + case MotionEvent.ACTION_CANCEL: + onCancelEvent(tracker, x, y, eventTime); + break; + } + } + + return true; + } + + private void onDownEvent(PointerTracker tracker, int x, int y, long eventTime) { + if (tracker.isOnModifierKey(x, y)) { + // Before processing a down event of modifier key, all pointers already being tracked + // should be released. + mPointerQueue.releaseAllPointersExcept(null, eventTime); + } + tracker.onDownEvent(x, y, eventTime); + mPointerQueue.add(tracker); + } + + private void onUpEvent(PointerTracker tracker, int x, int y, long eventTime) { + if (tracker.isModifier()) { + // Before processing an up event of modifier key, all pointers already being tracked + // should be released. + mPointerQueue.releaseAllPointersExcept(tracker, eventTime); + } else { + int index = mPointerQueue.lastIndexOf(tracker); + if (index >= 0) { + mPointerQueue.releaseAllPointersOlderThan(tracker, eventTime); + } else { + Log.w(TAG, "onUpEvent: corresponding down event not found for pointer " + + tracker.mPointerId); + } + } + tracker.onUpEvent(x, y, eventTime); + mPointerQueue.remove(tracker); + } + + private void onCancelEvent(PointerTracker tracker, int x, int y, long eventTime) { + tracker.onCancelEvent(x, y, eventTime); + mPointerQueue.remove(tracker); + } + + protected void swipeRight() { + mKeyboardActionListener.swipeRight(); + } + + protected void swipeLeft() { + mKeyboardActionListener.swipeLeft(); + } + + protected void swipeUp() { + mKeyboardActionListener.swipeUp(); + } + + protected void swipeDown() { + mKeyboardActionListener.swipeDown(); + } + + public void closing() { + mPreviewPopup.dismiss(); + mHandler.cancelAllMessages(); + + dismissPopupKeyboard(); + mBuffer = null; + mCanvas = null; + mMiniKeyboardCache.clear(); + } + + @Override + public void onDetachedFromWindow() { + super.onDetachedFromWindow(); + closing(); + } + + private void dismissPopupKeyboard() { + if (mMiniKeyboardPopup.isShowing()) { + mMiniKeyboardPopup.dismiss(); + mMiniKeyboard = null; + mMiniKeyboardOriginX = 0; + mMiniKeyboardOriginY = 0; + invalidateAllKeys(); + } + } + + public boolean handleBack() { + if (mMiniKeyboardPopup.isShowing()) { + dismissPopupKeyboard(); + return true; + } + return false; + } +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/LatinKeyboardView.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/LatinKeyboardView.java new file mode 100644 index 00000000..edc87fe0 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/LatinKeyboardView.java @@ -0,0 +1,385 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package keepass2android.softkeyboard; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.inputmethodservice.Keyboard; +import android.inputmethodservice.Keyboard.Key; +import android.os.Handler; +import android.os.Message; +import android.os.SystemClock; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.view.MotionEvent; + +import java.util.List; + +public class LatinKeyboardView extends LatinKeyboardBaseView { + + static final int KEYCODE_OPTIONS = -100; + static final int KEYCODE_OPTIONS_LONGPRESS = -101; + static final int KEYCODE_F1 = -103; + static final int KEYCODE_NEXT_LANGUAGE = -104; + static final int KEYCODE_PREV_LANGUAGE = -105; + static final int KEYCODE_KP2A = -200; + static final int KEYCODE_KP2A_USER = -201; + static final int KEYCODE_KP2A_PASSWORD = -202; + static final int KEYCODE_KP2A_ALPHA = -203; + static final int KEYCODE_KP2A_SWITCH = -204; + static final int KEYCODE_KP2A_LOCK = -205; + + private Keyboard mPhoneKeyboard; + + /** Whether we've started dropping move events because we found a big jump */ + private boolean mDroppingEvents; + /** + * Whether multi-touch disambiguation needs to be disabled if a real multi-touch event has + * occured + */ + private boolean mDisableDisambiguation; + /** The distance threshold at which we start treating the touch session as a multi-touch */ + private int mJumpThresholdSquare = Integer.MAX_VALUE; + /** The y coordinate of the last row */ + private int mLastRowY; + + public LatinKeyboardView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public LatinKeyboardView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + public void setPhoneKeyboard(Keyboard phoneKeyboard) { + mPhoneKeyboard = phoneKeyboard; + } + + @Override + public void setPreviewEnabled(boolean previewEnabled) { + if (getKeyboard() == mPhoneKeyboard) { + // Phone keyboard never shows popup preview (except language switch). + super.setPreviewEnabled(false); + } else { + super.setPreviewEnabled(previewEnabled); + } + } + + @Override + public void setKeyboard(Keyboard newKeyboard) { + final Keyboard oldKeyboard = getKeyboard(); + if (oldKeyboard instanceof LatinKeyboard) { + // Reset old keyboard state before switching to new keyboard. + ((LatinKeyboard)oldKeyboard).keyReleased(); + } + super.setKeyboard(newKeyboard); + // One-seventh of the keyboard width seems like a reasonable threshold + mJumpThresholdSquare = newKeyboard.getMinWidth() / 7; + mJumpThresholdSquare *= mJumpThresholdSquare; + // Assuming there are 4 rows, this is the coordinate of the last row + mLastRowY = (newKeyboard.getHeight() * 3) / 4; + setKeyboardLocal(newKeyboard); + } + + @Override + protected boolean onLongPress(Key key) { + int primaryCode = key.codes[0]; + if (primaryCode == KEYCODE_OPTIONS) { + return invokeOnKey(KEYCODE_OPTIONS_LONGPRESS); + } else if (primaryCode == '0' && getKeyboard() == mPhoneKeyboard) { + // Long pressing on 0 in phone number keypad gives you a '+'. + return invokeOnKey('+'); + } else { + return super.onLongPress(key); + } + } + + private boolean invokeOnKey(int primaryCode) { + getOnKeyboardActionListener().onKey(primaryCode, null, + LatinKeyboardBaseView.NOT_A_TOUCH_COORDINATE, + LatinKeyboardBaseView.NOT_A_TOUCH_COORDINATE); + return true; + } + + @Override + protected CharSequence adjustCase(CharSequence label) { + Keyboard keyboard = getKeyboard(); + if (keyboard.isShifted() + && keyboard instanceof LatinKeyboard + && ((LatinKeyboard) keyboard).isAlphaKeyboard() + && !TextUtils.isEmpty(label) && label.length() < 3 + && Character.isLowerCase(label.charAt(0))) { + return label.toString().toUpperCase(getKeyboardLocale()); + } + return label; + } + + public boolean setShiftLocked(boolean shiftLocked) { + Keyboard keyboard = getKeyboard(); + if (keyboard instanceof LatinKeyboard) { + ((LatinKeyboard)keyboard).setShiftLocked(shiftLocked); + invalidateAllKeys(); + return true; + } + return false; + } + + /** + * This function checks to see if we need to handle any sudden jumps in the pointer location + * that could be due to a multi-touch being treated as a move by the firmware or hardware. + * Once a sudden jump is detected, all subsequent move events are discarded + * until an UP is received.

+ * When a sudden jump is detected, an UP event is simulated at the last position and when + * the sudden moves subside, a DOWN event is simulated for the second key. + * @param me the motion event + * @return true if the event was consumed, so that it doesn't continue to be handled by + * KeyboardView. + */ + private boolean handleSuddenJump(MotionEvent me) { + final int action = me.getAction(); + final int x = (int) me.getX(); + final int y = (int) me.getY(); + boolean result = false; + + // Real multi-touch event? Stop looking for sudden jumps + if (me.getPointerCount() > 1) { + mDisableDisambiguation = true; + } + if (mDisableDisambiguation) { + // If UP, reset the multi-touch flag + if (action == MotionEvent.ACTION_UP) mDisableDisambiguation = false; + return false; + } + + switch (action) { + case MotionEvent.ACTION_DOWN: + // Reset the "session" + mDroppingEvents = false; + mDisableDisambiguation = false; + break; + case MotionEvent.ACTION_MOVE: + // Is this a big jump? + final int distanceSquare = (mLastX - x) * (mLastX - x) + (mLastY - y) * (mLastY - y); + // Check the distance and also if the move is not entirely within the bottom row + // If it's only in the bottom row, it might be an intentional slide gesture + // for language switching + if (distanceSquare > mJumpThresholdSquare + && (mLastY < mLastRowY || y < mLastRowY)) { + // If we're not yet dropping events, start dropping and send an UP event + if (!mDroppingEvents) { + mDroppingEvents = true; + // Send an up event + MotionEvent translated = MotionEvent.obtain(me.getEventTime(), me.getEventTime(), + MotionEvent.ACTION_UP, + mLastX, mLastY, me.getMetaState()); + super.onTouchEvent(translated); + translated.recycle(); + } + result = true; + } else if (mDroppingEvents) { + // If moves are small and we're already dropping events, continue dropping + result = true; + } + break; + case MotionEvent.ACTION_UP: + if (mDroppingEvents) { + // Send a down event first, as we dropped a bunch of sudden jumps and assume that + // the user is releasing the touch on the second key. + MotionEvent translated = MotionEvent.obtain(me.getEventTime(), me.getEventTime(), + MotionEvent.ACTION_DOWN, + x, y, me.getMetaState()); + super.onTouchEvent(translated); + translated.recycle(); + mDroppingEvents = false; + // Let the up event get processed as well, result = false + } + break; + } + // Track the previous coordinate + mLastX = x; + mLastY = y; + return result; + } + + @Override + public boolean onTouchEvent(MotionEvent me) { + LatinKeyboard keyboard = (LatinKeyboard) getKeyboard(); + if (DEBUG_LINE) { + mLastX = (int) me.getX(); + mLastY = (int) me.getY(); + invalidate(); + } + + // If there was a sudden jump, return without processing the actual motion event. + if (handleSuddenJump(me)) + return true; + + // Reset any bounding box controls in the keyboard + if (me.getAction() == MotionEvent.ACTION_DOWN) { + keyboard.keyReleased(); + } + + if (me.getAction() == MotionEvent.ACTION_UP) { + int languageDirection = keyboard.getLanguageChangeDirection(); + if (languageDirection != 0) { + getOnKeyboardActionListener().onKey( + languageDirection == 1 ? KEYCODE_NEXT_LANGUAGE : KEYCODE_PREV_LANGUAGE, + null, mLastX, mLastY); + me.setAction(MotionEvent.ACTION_CANCEL); + keyboard.keyReleased(); + return super.onTouchEvent(me); + } + } + + return super.onTouchEvent(me); + } + + /**************************** INSTRUMENTATION *******************************/ + + static final boolean DEBUG_AUTO_PLAY = false; + static final boolean DEBUG_LINE = false; + private static final int MSG_TOUCH_DOWN = 1; + private static final int MSG_TOUCH_UP = 2; + + Handler mHandler2; + + private String mStringToPlay; + private int mStringIndex; + private boolean mDownDelivered; + private Key[] mAsciiKeys = new Key[256]; + private boolean mPlaying; + private int mLastX; + private int mLastY; + private Paint mPaint; + + private void setKeyboardLocal(Keyboard k) { + if (DEBUG_AUTO_PLAY) { + findKeys(); + if (mHandler2 == null) { + mHandler2 = new Handler() { + @Override + public void handleMessage(Message msg) { + removeMessages(MSG_TOUCH_DOWN); + removeMessages(MSG_TOUCH_UP); + if (mPlaying == false) return; + + switch (msg.what) { + case MSG_TOUCH_DOWN: + if (mStringIndex >= mStringToPlay.length()) { + mPlaying = false; + return; + } + char c = mStringToPlay.charAt(mStringIndex); + while (c > 255 || mAsciiKeys[c] == null) { + mStringIndex++; + if (mStringIndex >= mStringToPlay.length()) { + mPlaying = false; + return; + } + c = mStringToPlay.charAt(mStringIndex); + } + int x = mAsciiKeys[c].x + 10; + int y = mAsciiKeys[c].y + 26; + MotionEvent me = MotionEvent.obtain(SystemClock.uptimeMillis(), + SystemClock.uptimeMillis(), + MotionEvent.ACTION_DOWN, x, y, 0); + LatinKeyboardView.this.dispatchTouchEvent(me); + me.recycle(); + sendEmptyMessageDelayed(MSG_TOUCH_UP, 500); // Deliver up in 500ms if nothing else + // happens + mDownDelivered = true; + break; + case MSG_TOUCH_UP: + char cUp = mStringToPlay.charAt(mStringIndex); + int x2 = mAsciiKeys[cUp].x + 10; + int y2 = mAsciiKeys[cUp].y + 26; + mStringIndex++; + + MotionEvent me2 = MotionEvent.obtain(SystemClock.uptimeMillis(), + SystemClock.uptimeMillis(), + MotionEvent.ACTION_UP, x2, y2, 0); + LatinKeyboardView.this.dispatchTouchEvent(me2); + me2.recycle(); + sendEmptyMessageDelayed(MSG_TOUCH_DOWN, 500); // Deliver up in 500ms if nothing else + // happens + mDownDelivered = false; + break; + } + } + }; + + } + } + } + + private void findKeys() { + List keys = getKeyboard().getKeys(); + // Get the keys on this keyboard + for (int i = 0; i < keys.size(); i++) { + int code = keys.get(i).codes[0]; + if (code >= 0 && code <= 255) { + mAsciiKeys[code] = keys.get(i); + } + } + } + + public void startPlaying(String s) { + if (DEBUG_AUTO_PLAY) { + if (s == null) return; + mStringToPlay = s.toLowerCase(); + mPlaying = true; + mDownDelivered = false; + mStringIndex = 0; + mHandler2.sendEmptyMessageDelayed(MSG_TOUCH_DOWN, 10); + } + } + + @Override + public void draw(Canvas c) { + LatinIMEUtil.GCUtils.getInstance().reset(); + boolean tryGC = true; + for (int i = 0; i < LatinIMEUtil.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) { + try { + super.draw(c); + tryGC = false; + } catch (OutOfMemoryError e) { + tryGC = LatinIMEUtil.GCUtils.getInstance().tryGCOrWait("LatinKeyboardView", e); + } + } + if (DEBUG_AUTO_PLAY) { + if (mPlaying) { + mHandler2.removeMessages(MSG_TOUCH_DOWN); + mHandler2.removeMessages(MSG_TOUCH_UP); + if (mDownDelivered) { + mHandler2.sendEmptyMessageDelayed(MSG_TOUCH_UP, 20); + } else { + mHandler2.sendEmptyMessageDelayed(MSG_TOUCH_DOWN, 20); + } + } + } + if (DEBUG_LINE) { + if (mPaint == null) { + mPaint = new Paint(); + mPaint.setColor(0x80FFFFFF); + mPaint.setAntiAlias(false); + } + c.drawLine(mLastX, 0, mLastX, getHeight(), mPaint); + c.drawLine(0, mLastY, getWidth(), mLastY, mPaint); + } + } +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/MiniKeyboardKeyDetector.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/MiniKeyboardKeyDetector.java new file mode 100644 index 00000000..00ee995b --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/MiniKeyboardKeyDetector.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 keepass2android.softkeyboard; + +import android.inputmethodservice.Keyboard.Key; + +class MiniKeyboardKeyDetector extends KeyDetector { + private static final int MAX_NEARBY_KEYS = 1; + + private final int mSlideAllowanceSquare; + private final int mSlideAllowanceSquareTop; + + public MiniKeyboardKeyDetector(float slideAllowance) { + super(); + mSlideAllowanceSquare = (int)(slideAllowance * slideAllowance); + // Top slide allowance is slightly longer (sqrt(2) times) than other edges. + mSlideAllowanceSquareTop = mSlideAllowanceSquare * 2; + } + + @Override + protected int getMaxNearbyKeys() { + return MAX_NEARBY_KEYS; + } + + @Override + public int getKeyIndexAndNearbyCodes(int x, int y, int[] allKeys) { + final Key[] keys = getKeys(); + final int touchX = getTouchX(x); + final int touchY = getTouchY(y); + int closestKeyIndex = LatinKeyboardBaseView.NOT_A_KEY; + int closestKeyDist = (y < 0) ? mSlideAllowanceSquareTop : mSlideAllowanceSquare; + final int keyCount = keys.length; + for (int i = 0; i < keyCount; i++) { + final Key key = keys[i]; + int dist = key.squaredDistanceFrom(touchX, touchY); + if (dist < closestKeyDist) { + closestKeyIndex = i; + closestKeyDist = dist; + } + } + if (allKeys != null && closestKeyIndex != LatinKeyboardBaseView.NOT_A_KEY) + allKeys[0] = keys[closestKeyIndex].codes[0]; + return closestKeyIndex; + } +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/ModifierKeyState.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/ModifierKeyState.java new file mode 100644 index 00000000..5da00d2e --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/ModifierKeyState.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 keepass2android.softkeyboard; + +class ModifierKeyState { + private static final int RELEASING = 0; + private static final int PRESSING = 1; + private static final int MOMENTARY = 2; + + private int mState = RELEASING; + + public void onPress() { + mState = PRESSING; + } + + public void onRelease() { + mState = RELEASING; + } + + public void onOtherKeyPressed() { + if (mState == PRESSING) + mState = MOMENTARY; + } + + public boolean isMomentary() { + return mState == MOMENTARY; + } +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/PluginManager.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/PluginManager.java new file mode 100644 index 00000000..f24328f8 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/PluginManager.java @@ -0,0 +1,259 @@ +package keepass2android.softkeyboard; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.xmlpull.v1.XmlPullParserException; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.res.Resources; +import android.content.res.XmlResourceParser; +import android.util.Log; + +public class PluginManager extends BroadcastReceiver { + private static String TAG = "PCKeyboard"; + private static String HK_INTENT_DICT = "org.pocketworkstation.DICT"; + private static String SOFTKEYBOARD_INTENT_DICT = "com.menny.android.anysoftkeyboard.DICTIONARY"; + private KP2AKeyboard mIME; + + // Apparently anysoftkeyboard doesn't use ISO 639-1 language codes for its locales? + // Add exceptions as needed. + private static Map SOFTKEYBOARD_LANG_MAP = new HashMap(); + static { + SOFTKEYBOARD_LANG_MAP.put("dk", "da"); + } + + PluginManager(KP2AKeyboard ime) { + super(); + mIME = ime; + } + + private static Map mPluginDicts = + new HashMap(); + + static interface DictPluginSpec { + BinaryDictionary getDict(Context context); + } + + static private abstract class DictPluginSpecBase + implements DictPluginSpec { + String mPackageName; + + Resources getResources(Context context) { + PackageManager packageManager = context.getPackageManager(); + Resources res = null; + try { + ApplicationInfo appInfo = packageManager.getApplicationInfo(mPackageName, 0); + res = packageManager.getResourcesForApplication(appInfo); + } catch (NameNotFoundException e) { + Log.i(TAG, "couldn't get resources"); + } + return res; + } + + abstract InputStream[] getStreams(Resources res); + + public BinaryDictionary getDict(Context context) { + Resources res = getResources(context); + if (res == null) return null; + + InputStream[] dicts = getStreams(res); + if (dicts == null) return null; + BinaryDictionary dict = new BinaryDictionary( + context, dicts, Suggest.DIC_MAIN); + if (dict.getSize() == 0) return null; + //Log.i(TAG, "dict size=" + dict.getSize()); + return dict; + } + } + + static private class DictPluginSpecHK + extends DictPluginSpecBase { + + int[] mRawIds; + + public DictPluginSpecHK(String pkg, int[] ids) { + mPackageName = pkg; + mRawIds = ids; + } + + @Override + InputStream[] getStreams(Resources res) { + if (mRawIds == null || mRawIds.length == 0) return null; + InputStream[] streams = new InputStream[mRawIds.length]; + for (int i = 0; i < mRawIds.length; ++i) { + streams[i] = res.openRawResource(mRawIds[i]); + } + return streams; + } + } + + static private class DictPluginSpecSoftKeyboard + extends DictPluginSpecBase { + + String mAssetName; + + public DictPluginSpecSoftKeyboard(String pkg, String asset) { + mPackageName = pkg; + mAssetName = asset; + } + + @Override + InputStream[] getStreams(Resources res) { + if (mAssetName == null) return null; + try { + InputStream in = res.getAssets().open(mAssetName); + return new InputStream[] {in}; + } catch (IOException e) { + Log.e(TAG, "Dictionary asset loading failure"); + return null; + } + } + } + + @Override + public void onReceive(Context context, Intent intent) { + Log.i(TAG, "Package information changed, updating dictionaries."); + getPluginDictionaries(context); + Log.i(TAG, "Finished updating dictionaries."); + mIME.toggleLanguage(true, true); + } + + static void getSoftKeyboardDictionaries(PackageManager packageManager) { + Intent dictIntent = new Intent(SOFTKEYBOARD_INTENT_DICT); + List dictPacks = packageManager.queryBroadcastReceivers( + dictIntent, PackageManager.GET_RECEIVERS); + for (ResolveInfo ri : dictPacks) { + ApplicationInfo appInfo = ri.activityInfo.applicationInfo; + String pkgName = appInfo.packageName; + boolean success = false; + try { + Resources res = packageManager.getResourcesForApplication(appInfo); + Log.i("KP2AK", "Found dictionary plugin package: " + pkgName); + int dictId = res.getIdentifier("dictionaries", "xml", pkgName); + if (dictId == 0) continue; + XmlResourceParser xrp = res.getXml(dictId); + + String assetName = null; + String lang = null; + try { + int current = xrp.getEventType(); + while (current != XmlResourceParser.END_DOCUMENT) { + if (current == XmlResourceParser.START_TAG) { + String tag = xrp.getName(); + if (tag != null) { + if (tag.equals("Dictionary")) { + lang = xrp.getAttributeValue(null, "locale"); + String convLang = SOFTKEYBOARD_LANG_MAP.get(lang); + if (convLang != null) lang = convLang; + String type = xrp.getAttributeValue(null, "type"); + if (type == null || type.equals("raw") || type.equals("binary")) { + assetName = xrp.getAttributeValue(null, "dictionaryAssertName"); // sic + } else { + Log.w(TAG, "Unsupported AnySoftKeyboard dict type " + type); + } + //Log.i(TAG, "asset=" + assetName + " lang=" + lang); + } + } + } + xrp.next(); + current = xrp.getEventType(); + } + } catch (XmlPullParserException e) { + Log.e(TAG, "Dictionary XML parsing failure"); + } catch (IOException e) { + Log.e(TAG, "Dictionary XML IOException"); + } + + if (assetName == null || lang == null) continue; + DictPluginSpec spec = new DictPluginSpecSoftKeyboard(pkgName, assetName); + mPluginDicts.put(lang, spec); + Log.i("KP2AK", "Found plugin dictionary: lang=" + lang + ", pkg=" + pkgName); + success = true; + } catch (NameNotFoundException e) { + Log.i("KP2AK", "bad"); + } finally { + if (!success) { + Log.i("KP2AK", "failed to load plugin dictionary spec from " + pkgName); + } + } + } + } + + static void getHKDictionaries(PackageManager packageManager) { + Intent dictIntent = new Intent(HK_INTENT_DICT); + List dictPacks = packageManager.queryIntentActivities(dictIntent, 0); + for (ResolveInfo ri : dictPacks) { + ApplicationInfo appInfo = ri.activityInfo.applicationInfo; + String pkgName = appInfo.packageName; + boolean success = false; + try { + Resources res = packageManager.getResourcesForApplication(appInfo); + Log.i("KP2AK", "Found dictionary plugin package: " + pkgName); + int langId = res.getIdentifier("dict_language", "string", pkgName); + if (langId == 0) continue; + String lang = res.getString(langId); + int[] rawIds = null; + + // Try single-file version first + int rawId = res.getIdentifier("main", "raw", pkgName); + if (rawId != 0) { + rawIds = new int[] { rawId }; + } else { + // try multi-part version + int parts = 0; + List ids = new ArrayList(); + while (true) { + int id = res.getIdentifier("main" + parts, "raw", pkgName); + if (id == 0) break; + ids.add(id); + ++parts; + } + if (parts == 0) continue; // no parts found + rawIds = new int[parts]; + for (int i = 0; i < parts; ++i) rawIds[i] = ids.get(i); + } + DictPluginSpec spec = new DictPluginSpecHK(pkgName, rawIds); + mPluginDicts.put(lang, spec); + Log.i("KP2AK", "Found plugin dictionary: lang=" + lang + ", pkg=" + pkgName); + success = true; + } catch (NameNotFoundException e) { + Log.i("KP2AK", "bad"); + } finally { + if (!success) { + Log.i("KP2AK", "failed to load plugin dictionary spec from " + pkgName); + } + } + } + } + + static void getPluginDictionaries(Context context) { + mPluginDicts.clear(); + PackageManager packageManager = context.getPackageManager(); + getSoftKeyboardDictionaries(packageManager); + getHKDictionaries(packageManager); + } + + static BinaryDictionary getDictionary(Context context, String lang) { + Log.i("KP2AK", "Looking for plugin dictionary for lang=" + lang); + DictPluginSpec spec = mPluginDicts.get(lang); + if (spec == null) spec = mPluginDicts.get(lang.substring(0, 2)); + if (spec == null) { + Log.i("KP2AK", "No plugin found."); + return null; + } + BinaryDictionary dict = spec.getDict(context); + Log.i("KP2AK", "Found plugin dictionary for " + lang + (dict == null ? " is null" : ", size=" + dict.getSize())); + return dict; + } +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/PointerTracker.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/PointerTracker.java new file mode 100644 index 00000000..54ca0c2e --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/PointerTracker.java @@ -0,0 +1,581 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 keepass2android.softkeyboard; + +import keepass2android.softkeyboard.LatinKeyboardBaseView.OnKeyboardActionListener; +import keepass2android.softkeyboard.LatinKeyboardBaseView.UIHandler; + +import android.content.res.Resources; +import android.inputmethodservice.Keyboard; +import android.inputmethodservice.Keyboard.Key; +import android.util.Log; +import android.view.MotionEvent; + +public class PointerTracker { + private static final String TAG = "PointerTracker"; + private static final boolean DEBUG = false; + private static final boolean DEBUG_MOVE = false; + + public interface UIProxy { + public void invalidateKey(Key key); + public void showPreview(int keyIndex, PointerTracker tracker); + public boolean hasDistinctMultitouch(); + } + + public final int mPointerId; + + // Timing constants + private final int mDelayBeforeKeyRepeatStart; + private final int mLongPressKeyTimeout; + private final int mMultiTapKeyTimeout; + + // Miscellaneous constants + private static final int NOT_A_KEY = LatinKeyboardBaseView.NOT_A_KEY; + private static final int[] KEY_DELETE = { Keyboard.KEYCODE_DELETE }; + + private final UIProxy mProxy; + private final UIHandler mHandler; + private final KeyDetector mKeyDetector; + private OnKeyboardActionListener mListener; + private final KeyboardSwitcher mKeyboardSwitcher; + private final boolean mHasDistinctMultitouch; + + private Key[] mKeys; + private int mKeyHysteresisDistanceSquared = -1; + + private final KeyState mKeyState; + + // true if keyboard layout has been changed. + private boolean mKeyboardLayoutHasBeenChanged; + + // true if event is already translated to a key action (long press or mini-keyboard) + private boolean mKeyAlreadyProcessed; + + // true if this pointer is repeatable key + private boolean mIsRepeatableKey; + + // true if this pointer is in sliding key input + private boolean mIsInSlidingKeyInput; + + // For multi-tap + private int mLastSentIndex; + private int mTapCount; + private long mLastTapTime; + private boolean mInMultiTap; + private final StringBuilder mPreviewLabel = new StringBuilder(1); + + // pressed key + private int mPreviousKey = NOT_A_KEY; + + // This class keeps track of a key index and a position where this pointer is. + private static class KeyState { + private final KeyDetector mKeyDetector; + + // The position and time at which first down event occurred. + private int mStartX; + private int mStartY; + private long mDownTime; + + // The current key index where this pointer is. + private int mKeyIndex = NOT_A_KEY; + // The position where mKeyIndex was recognized for the first time. + private int mKeyX; + private int mKeyY; + + // Last pointer position. + private int mLastX; + private int mLastY; + + public KeyState(KeyDetector keyDetecor) { + mKeyDetector = keyDetecor; + } + + public int getKeyIndex() { + return mKeyIndex; + } + + public int getKeyX() { + return mKeyX; + } + + public int getKeyY() { + return mKeyY; + } + + public int getStartX() { + return mStartX; + } + + public int getStartY() { + return mStartY; + } + + public long getDownTime() { + return mDownTime; + } + + public int getLastX() { + return mLastX; + } + + public int getLastY() { + return mLastY; + } + + public int onDownKey(int x, int y, long eventTime) { + mStartX = x; + mStartY = y; + mDownTime = eventTime; + + return onMoveToNewKey(onMoveKeyInternal(x, y), x, y); + } + + private int onMoveKeyInternal(int x, int y) { + mLastX = x; + mLastY = y; + return mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null); + } + + public int onMoveKey(int x, int y) { + return onMoveKeyInternal(x, y); + } + + public int onMoveToNewKey(int keyIndex, int x, int y) { + mKeyIndex = keyIndex; + mKeyX = x; + mKeyY = y; + return keyIndex; + } + + public int onUpKey(int x, int y) { + return onMoveKeyInternal(x, y); + } + } + + public PointerTracker(int id, UIHandler handler, KeyDetector keyDetector, UIProxy proxy, + Resources res) { + if (proxy == null || handler == null || keyDetector == null) + throw new NullPointerException(); + mPointerId = id; + mProxy = proxy; + mHandler = handler; + mKeyDetector = keyDetector; + mKeyboardSwitcher = KeyboardSwitcher.getInstance(); + mKeyState = new KeyState(keyDetector); + mHasDistinctMultitouch = proxy.hasDistinctMultitouch(); + mDelayBeforeKeyRepeatStart = res.getInteger(R.integer.config_delay_before_key_repeat_start); + mLongPressKeyTimeout = res.getInteger(R.integer.config_long_press_key_timeout); + mMultiTapKeyTimeout = res.getInteger(R.integer.config_multi_tap_key_timeout); + resetMultiTap(); + } + + public void setOnKeyboardActionListener(OnKeyboardActionListener listener) { + mListener = listener; + } + + public void setKeyboard(Key[] keys, float keyHysteresisDistance) { + if (keys == null || keyHysteresisDistance < 0) + throw new IllegalArgumentException(); + mKeys = keys; + mKeyHysteresisDistanceSquared = (int)(keyHysteresisDistance * keyHysteresisDistance); + // Mark that keyboard layout has been changed. + mKeyboardLayoutHasBeenChanged = true; + } + + public boolean isInSlidingKeyInput() { + return mIsInSlidingKeyInput; + } + + private boolean isValidKeyIndex(int keyIndex) { + return keyIndex >= 0 && keyIndex < mKeys.length; + } + + public Key getKey(int keyIndex) { + return isValidKeyIndex(keyIndex) ? mKeys[keyIndex] : null; + } + + private boolean isModifierInternal(int keyIndex) { + Key key = getKey(keyIndex); + if (key == null) + return false; + int primaryCode = key.codes[0]; + return primaryCode == Keyboard.KEYCODE_SHIFT + || primaryCode == Keyboard.KEYCODE_MODE_CHANGE; + } + + public boolean isModifier() { + return isModifierInternal(mKeyState.getKeyIndex()); + } + + public boolean isOnModifierKey(int x, int y) { + return isModifierInternal(mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null)); + } + + public boolean isSpaceKey(int keyIndex) { + Key key = getKey(keyIndex); + return key != null && key.codes[0] == KP2AKeyboard.KEYCODE_SPACE; + } + + public void updateKey(int keyIndex) { + if (mKeyAlreadyProcessed) + return; + int oldKeyIndex = mPreviousKey; + mPreviousKey = keyIndex; + if (keyIndex != oldKeyIndex) { + if (isValidKeyIndex(oldKeyIndex)) { + // if new key index is not a key, old key was just released inside of the key. + final boolean inside = (keyIndex == NOT_A_KEY); + mKeys[oldKeyIndex].onReleased(inside); + mProxy.invalidateKey(mKeys[oldKeyIndex]); + } + if (isValidKeyIndex(keyIndex)) { + mKeys[keyIndex].onPressed(); + mProxy.invalidateKey(mKeys[keyIndex]); + } + } + } + + public void setAlreadyProcessed() { + mKeyAlreadyProcessed = true; + } + + public void onTouchEvent(int action, int x, int y, long eventTime) { + switch (action) { + case MotionEvent.ACTION_MOVE: + onMoveEvent(x, y, eventTime); + break; + case MotionEvent.ACTION_DOWN: + case MotionEvent.ACTION_POINTER_DOWN: + onDownEvent(x, y, eventTime); + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_POINTER_UP: + onUpEvent(x, y, eventTime); + break; + case MotionEvent.ACTION_CANCEL: + onCancelEvent(x, y, eventTime); + break; + } + } + + public void onDownEvent(int x, int y, long eventTime) { + if (DEBUG) + debugLog("onDownEvent:", x, y); + int keyIndex = mKeyState.onDownKey(x, y, eventTime); + mKeyboardLayoutHasBeenChanged = false; + mKeyAlreadyProcessed = false; + mIsRepeatableKey = false; + mIsInSlidingKeyInput = false; + checkMultiTap(eventTime, keyIndex); + if (mListener != null) { + if (isValidKeyIndex(keyIndex)) { + mListener.onPress(mKeys[keyIndex].codes[0]); + // This onPress call may have changed keyboard layout. Those cases are detected at + // {@link #setKeyboard}. In those cases, we should update keyIndex according to the + // new keyboard layout. + if (mKeyboardLayoutHasBeenChanged) { + mKeyboardLayoutHasBeenChanged = false; + keyIndex = mKeyState.onDownKey(x, y, eventTime); + } + } + } + if (isValidKeyIndex(keyIndex)) { + if (mKeys[keyIndex].repeatable) { + repeatKey(keyIndex); + mHandler.startKeyRepeatTimer(mDelayBeforeKeyRepeatStart, keyIndex, this); + mIsRepeatableKey = true; + } + startLongPressTimer(keyIndex); + } + showKeyPreviewAndUpdateKey(keyIndex); + } + + public void onMoveEvent(int x, int y, long eventTime) { + if (DEBUG_MOVE) + debugLog("onMoveEvent:", x, y); + if (mKeyAlreadyProcessed) + return; + final KeyState keyState = mKeyState; + int keyIndex = keyState.onMoveKey(x, y); + final Key oldKey = getKey(keyState.getKeyIndex()); + if (isValidKeyIndex(keyIndex)) { + if (oldKey == null) { + // The pointer has been slid in to the new key, but the finger was not on any keys. + // In this case, we must call onPress() to notify that the new key is being pressed. + if (mListener != null) { + mListener.onPress(getKey(keyIndex).codes[0]); + // This onPress call may have changed keyboard layout. Those cases are detected + // at {@link #setKeyboard}. In those cases, we should update keyIndex according + // to the new keyboard layout. + if (mKeyboardLayoutHasBeenChanged) { + mKeyboardLayoutHasBeenChanged = false; + keyIndex = keyState.onMoveKey(x, y); + } + } + keyState.onMoveToNewKey(keyIndex, x, y); + startLongPressTimer(keyIndex); + } else if (!isMinorMoveBounce(x, y, keyIndex)) { + // The pointer has been slid in to the new key from the previous key, we must call + // onRelease() first to notify that the previous key has been released, then call + // onPress() to notify that the new key is being pressed. + mIsInSlidingKeyInput = true; + if (mListener != null) + mListener.onRelease(oldKey.codes[0]); + resetMultiTap(); + if (mListener != null) { + mListener.onPress(getKey(keyIndex).codes[0]); + // This onPress call may have changed keyboard layout. Those cases are detected + // at {@link #setKeyboard}. In those cases, we should update keyIndex according + // to the new keyboard layout. + if (mKeyboardLayoutHasBeenChanged) { + mKeyboardLayoutHasBeenChanged = false; + keyIndex = keyState.onMoveKey(x, y); + } + } + keyState.onMoveToNewKey(keyIndex, x, y); + startLongPressTimer(keyIndex); + } + } else { + if (oldKey != null && !isMinorMoveBounce(x, y, keyIndex)) { + // The pointer has been slid out from the previous key, we must call onRelease() to + // notify that the previous key has been released. + mIsInSlidingKeyInput = true; + if (mListener != null) + mListener.onRelease(oldKey.codes[0]); + resetMultiTap(); + keyState.onMoveToNewKey(keyIndex, x ,y); + mHandler.cancelLongPressTimer(); + } + } + showKeyPreviewAndUpdateKey(keyState.getKeyIndex()); + } + + public void onUpEvent(int x, int y, long eventTime) { + if (DEBUG) + debugLog("onUpEvent :", x, y); + mHandler.cancelKeyTimers(); + mHandler.cancelPopupPreview(); + showKeyPreviewAndUpdateKey(NOT_A_KEY); + mIsInSlidingKeyInput = false; + if (mKeyAlreadyProcessed) + return; + int keyIndex = mKeyState.onUpKey(x, y); + if (isMinorMoveBounce(x, y, keyIndex)) { + // Use previous fixed key index and coordinates. + keyIndex = mKeyState.getKeyIndex(); + x = mKeyState.getKeyX(); + y = mKeyState.getKeyY(); + } + if (!mIsRepeatableKey) { + detectAndSendKey(keyIndex, x, y, eventTime); + } + + if (isValidKeyIndex(keyIndex)) + mProxy.invalidateKey(mKeys[keyIndex]); + } + + public void onCancelEvent(int x, int y, long eventTime) { + if (DEBUG) + debugLog("onCancelEvt:", x, y); + mHandler.cancelKeyTimers(); + mHandler.cancelPopupPreview(); + showKeyPreviewAndUpdateKey(NOT_A_KEY); + mIsInSlidingKeyInput = false; + int keyIndex = mKeyState.getKeyIndex(); + if (isValidKeyIndex(keyIndex)) + mProxy.invalidateKey(mKeys[keyIndex]); + } + + public void repeatKey(int keyIndex) { + Key key = getKey(keyIndex); + if (key != null) { + // While key is repeating, because there is no need to handle multi-tap key, we can + // pass -1 as eventTime argument. + detectAndSendKey(keyIndex, key.x, key.y, -1); + } + } + + public int getLastX() { + return mKeyState.getLastX(); + } + + public int getLastY() { + return mKeyState.getLastY(); + } + + public long getDownTime() { + return mKeyState.getDownTime(); + } + + // These package scope methods are only for debugging purpose. + /* package */ int getStartX() { + return mKeyState.getStartX(); + } + + /* package */ int getStartY() { + return mKeyState.getStartY(); + } + + private boolean isMinorMoveBounce(int x, int y, int newKey) { + if (mKeys == null || mKeyHysteresisDistanceSquared < 0) + throw new IllegalStateException("keyboard and/or hysteresis not set"); + int curKey = mKeyState.getKeyIndex(); + if (newKey == curKey) { + return true; + } else if (isValidKeyIndex(curKey)) { + return getSquareDistanceToKeyEdge(x, y, mKeys[curKey]) < mKeyHysteresisDistanceSquared; + } else { + return false; + } + } + + private static int getSquareDistanceToKeyEdge(int x, int y, Key key) { + final int left = key.x; + final int right = key.x + key.width; + final int top = key.y; + final int bottom = key.y + key.height; + final int edgeX = x < left ? left : (x > right ? right : x); + final int edgeY = y < top ? top : (y > bottom ? bottom : y); + final int dx = x - edgeX; + final int dy = y - edgeY; + return dx * dx + dy * dy; + } + + private void showKeyPreviewAndUpdateKey(int keyIndex) { + updateKey(keyIndex); + // The modifier key, such as shift key, should not be shown as preview when multi-touch is + // supported. On the other hand, if multi-touch is not supported, the modifier key should + // be shown as preview. + if (mHasDistinctMultitouch && isModifier()) { + mProxy.showPreview(NOT_A_KEY, this); + } else { + mProxy.showPreview(keyIndex, this); + } + } + + private void startLongPressTimer(int keyIndex) { + if (mKeyboardSwitcher.isInMomentaryAutoModeSwitchState()) { + // We use longer timeout for sliding finger input started from the symbols mode key. + mHandler.startLongPressTimer(mLongPressKeyTimeout * 3, keyIndex, this); + } else { + mHandler.startLongPressTimer(mLongPressKeyTimeout, keyIndex, this); + } + } + + private void detectAndSendKey(int index, int x, int y, long eventTime) { + final OnKeyboardActionListener listener = mListener; + final Key key = getKey(index); + + if (key == null) { + if (listener != null) + listener.onCancel(); + } else { + if (key.text != null) { + if (listener != null) { + listener.onText(key.text); + listener.onRelease(0); // dummy key code + } + } else { + int code = key.codes[0]; + int[] codes = mKeyDetector.newCodeArray(); + mKeyDetector.getKeyIndexAndNearbyCodes(x, y, codes); + // Multi-tap + if (mInMultiTap) { + if (mTapCount != -1) { + mListener.onKey(Keyboard.KEYCODE_DELETE, KEY_DELETE, x, y); + } else { + mTapCount = 0; + } + code = key.codes[mTapCount]; + } + /* + * Swap the first and second values in the codes array if the primary code is not + * the first value but the second value in the array. This happens when key + * debouncing is in effect. + */ + if (codes.length >= 2 && codes[0] != code && codes[1] == code) { + codes[1] = codes[0]; + codes[0] = code; + } + if (listener != null) { + listener.onKey(code, codes, x, y); + listener.onRelease(code); + } + } + mLastSentIndex = index; + mLastTapTime = eventTime; + } + } + + /** + * Handle multi-tap keys by producing the key label for the current multi-tap state. + */ + public CharSequence getPreviewText(Key key) { + if (mInMultiTap) { + // Multi-tap + mPreviewLabel.setLength(0); + mPreviewLabel.append((char) key.codes[mTapCount < 0 ? 0 : mTapCount]); + return mPreviewLabel; + } else { + return key.label; + } + } + + private void resetMultiTap() { + mLastSentIndex = NOT_A_KEY; + mTapCount = 0; + mLastTapTime = -1; + mInMultiTap = false; + } + + private void checkMultiTap(long eventTime, int keyIndex) { + Key key = getKey(keyIndex); + if (key == null) + return; + + final boolean isMultiTap = + (eventTime < mLastTapTime + mMultiTapKeyTimeout && keyIndex == mLastSentIndex); + if (key.codes.length > 1) { + mInMultiTap = true; + if (isMultiTap) { + mTapCount = (mTapCount + 1) % key.codes.length; + return; + } else { + mTapCount = -1; + return; + } + } + if (!isMultiTap) { + resetMultiTap(); + } + } + + private void debugLog(String title, int x, int y) { + int keyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(x, y, null); + Key key = getKey(keyIndex); + final String code; + if (key == null) { + code = "----"; + } else { + int primaryCode = key.codes[0]; + code = String.format((primaryCode < 0) ? "%4d" : "0x%02x", primaryCode); + } + Log.d(TAG, String.format("%s%s[%d] %3d,%3d %3d(%s) %s", title, + (mKeyAlreadyProcessed ? "-" : " "), mPointerId, x, y, keyIndex, code, + (isModifier() ? "modifier" : ""))); + } +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/ProximityKeyDetector.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/ProximityKeyDetector.java new file mode 100644 index 00000000..5c20c798 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/ProximityKeyDetector.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 keepass2android.softkeyboard; + +import android.inputmethodservice.Keyboard.Key; + +import java.util.Arrays; + +class ProximityKeyDetector extends KeyDetector { + private static final int MAX_NEARBY_KEYS = 12; + + // working area + private int[] mDistances = new int[MAX_NEARBY_KEYS]; + + @Override + protected int getMaxNearbyKeys() { + return MAX_NEARBY_KEYS; + } + + @Override + public int getKeyIndexAndNearbyCodes(int x, int y, int[] allKeys) { + final Key[] keys = getKeys(); + final int touchX = getTouchX(x); + final int touchY = getTouchY(y); + int primaryIndex = LatinKeyboardBaseView.NOT_A_KEY; + int closestKey = LatinKeyboardBaseView.NOT_A_KEY; + int closestKeyDist = mProximityThresholdSquare + 1; + int[] distances = mDistances; + Arrays.fill(distances, Integer.MAX_VALUE); + int [] nearestKeyIndices = mKeyboard.getNearestKeys(touchX, touchY); + final int keyCount = nearestKeyIndices.length; + for (int i = 0; i < keyCount; i++) { + final Key key = keys[nearestKeyIndices[i]]; + int dist = 0; + boolean isInside = key.isInside(touchX, touchY); + if (isInside) { + primaryIndex = nearestKeyIndices[i]; + } + + if (((mProximityCorrectOn + && (dist = key.squaredDistanceFrom(touchX, touchY)) < mProximityThresholdSquare) + || isInside) + && key.codes[0] > 32) { + // Find insertion point + final int nCodes = key.codes.length; + if (dist < closestKeyDist) { + closestKeyDist = dist; + closestKey = nearestKeyIndices[i]; + } + + if (allKeys == null) continue; + + for (int j = 0; j < distances.length; j++) { + if (distances[j] > dist) { + // Make space for nCodes codes + System.arraycopy(distances, j, distances, j + nCodes, + distances.length - j - nCodes); + System.arraycopy(allKeys, j, allKeys, j + nCodes, + allKeys.length - j - nCodes); + System.arraycopy(key.codes, 0, allKeys, j, nCodes); + Arrays.fill(distances, j, j + nCodes, dist); + break; + } + } + } + } + if (primaryIndex == LatinKeyboardBaseView.NOT_A_KEY) { + primaryIndex = closestKey; + } + return primaryIndex; + } +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/SharedPreferencesCompat.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/SharedPreferencesCompat.java new file mode 100644 index 00000000..ee7e65ab --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/SharedPreferencesCompat.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package keepass2android.softkeyboard; + +import android.content.SharedPreferences; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * Reflection utils to call SharedPreferences$Editor.apply when possible, + * falling back to commit when apply isn't available. + */ +public class SharedPreferencesCompat { + private static final Method sApplyMethod = findApplyMethod(); + + private static Method findApplyMethod() { + try { + return SharedPreferences.Editor.class.getMethod("apply"); + } catch (NoSuchMethodException unused) { + // fall through + } + return null; + } + + public static void apply(SharedPreferences.Editor editor) { + if (sApplyMethod != null) { + try { + sApplyMethod.invoke(editor); + return; + } catch (InvocationTargetException unused) { + // fall through + } catch (IllegalAccessException unused) { + // fall through + } + } + editor.commit(); + } +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/Suggest.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/Suggest.java new file mode 100644 index 00000000..8b6883e8 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/Suggest.java @@ -0,0 +1,552 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package keepass2android.softkeyboard; + +import android.content.Context; +import android.text.AutoText; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; + +/** + * This class loads a dictionary and provides a list of suggestions for a given sequence of + * characters. This includes corrections and completions. + * @hide pending API Council Approval + */ +public class Suggest implements Dictionary.WordCallback { + + public static final int APPROX_MAX_WORD_LENGTH = 32; + + public static final int CORRECTION_NONE = 0; + public static final int CORRECTION_BASIC = 1; + public static final int CORRECTION_FULL = 2; + public static final int CORRECTION_FULL_BIGRAM = 3; + + /** + * Words that appear in both bigram and unigram data gets multiplier ranging from + * BIGRAM_MULTIPLIER_MIN to BIGRAM_MULTIPLIER_MAX depending on the frequency score from + * bigram data. + */ + public static final double BIGRAM_MULTIPLIER_MIN = 1.2; + public static final double BIGRAM_MULTIPLIER_MAX = 1.5; + + /** + * Maximum possible bigram frequency. Will depend on how many bits are being used in data + * structure. Maximum bigram freqeuncy will get the BIGRAM_MULTIPLIER_MAX as the multiplier. + */ + public static final int MAXIMUM_BIGRAM_FREQUENCY = 127; + + public static final int DIC_USER_TYPED = 0; + public static final int DIC_MAIN = 1; + public static final int DIC_USER = 2; + public static final int DIC_AUTO = 3; + public static final int DIC_CONTACTS = 4; + // If you add a type of dictionary, increment DIC_TYPE_LAST_ID + public static final int DIC_TYPE_LAST_ID = 4; + + static final int LARGE_DICTIONARY_THRESHOLD = 200 * 1000; + + private BinaryDictionary mMainDict; +/* + private Dictionary mUserDictionary; + + private Dictionary mAutoDictionary; + + private Dictionary mContactsDictionary; + + private Dictionary mUserBigramDictionary; +*/ + private int mPrefMaxSuggestions = 12; + + private static final int PREF_MAX_BIGRAMS = 60; + + private boolean mAutoTextEnabled; + + private int[] mPriorities = new int[mPrefMaxSuggestions]; + private int[] mBigramPriorities = new int[PREF_MAX_BIGRAMS]; + + // Handle predictive correction for only the first 1280 characters for performance reasons + // If we support scripts that need latin characters beyond that, we should probably use some + // kind of a sparse array or language specific list with a mapping lookup table. + // 1280 is the size of the BASE_CHARS array in ExpandableDictionary, which is a basic set of + // latin characters. + private int[] mNextLettersFrequencies = new int[1280]; + private ArrayList mSuggestions = new ArrayList(); + ArrayList mBigramSuggestions = new ArrayList(); + private ArrayList mStringPool = new ArrayList(); + private boolean mHaveCorrection; + private CharSequence mOriginalWord; + private String mLowerOriginalWord; + + // TODO: Remove these member variables by passing more context to addWord() callback method + private boolean mIsFirstCharCapitalized; + private boolean mIsAllUpperCase; + + private int mCorrectionMode = CORRECTION_BASIC; + + public Suggest(Context context, int[] dictionaryResId) { + mMainDict = new BinaryDictionary(context, dictionaryResId, DIC_MAIN); + + + Locale locale = context.getResources().getConfiguration().locale; + Log.d("KP2AK", "locale: " + locale.getISO3Language()); + + if (!hasMainDictionary() + || (!"eng".equals(locale.getISO3Language()))) + { + Log.d("KP2AK", "try get plug"); + BinaryDictionary plug = PluginManager.getDictionary(context, locale.getLanguage()); + if (plug != null) { + Log.d("KP2AK", "ok"); + mMainDict.close(); + mMainDict = plug; + } + } + + + initPool(); + } + + + + private void initPool() { + for (int i = 0; i < mPrefMaxSuggestions; i++) { + StringBuilder sb = new StringBuilder(getApproxMaxWordLength()); + mStringPool.add(sb); + } + } + + public void setAutoTextEnabled(boolean enabled) { + mAutoTextEnabled = enabled; + } + + public int getCorrectionMode() { + return mCorrectionMode; + } + + public void setCorrectionMode(int mode) { + mCorrectionMode = mode; + } + + public boolean hasMainDictionary() { + return mMainDict.getSize() > LARGE_DICTIONARY_THRESHOLD; + } + + public int getApproxMaxWordLength() { + return APPROX_MAX_WORD_LENGTH; + } +/* + *//** + * Sets an optional user dictionary resource to be loaded. The user dictionary is consulted + * before the main dictionary, if set. + *//* + public void setUserDictionary(Dictionary userDictionary) { + 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; + } + + public void setUserBigramDictionary(Dictionary userBigramDictionary) { + mUserBigramDictionary = userBigramDictionary; + } +*/ + /** + * Number of suggestions to generate from the input key sequence. This has + * to be a number between 1 and 100 (inclusive). + * @param maxSuggestions + * @throws IllegalArgumentException if the number is out of range + */ + public void setMaxSuggestions(int maxSuggestions) { + if (maxSuggestions < 1 || maxSuggestions > 100) { + throw new IllegalArgumentException("maxSuggestions must be between 1 and 100"); + } + mPrefMaxSuggestions = maxSuggestions; + mPriorities = new int[mPrefMaxSuggestions]; + mBigramPriorities = new int[PREF_MAX_BIGRAMS]; + collectGarbage(mSuggestions, mPrefMaxSuggestions); + while (mStringPool.size() < mPrefMaxSuggestions) { + StringBuilder sb = new StringBuilder(getApproxMaxWordLength()); + mStringPool.add(sb); + } + } + + private boolean haveSufficientCommonality(String original, CharSequence suggestion) { + 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; + 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++; + } + } + matching = Math.max(matching, lessMatching); + + if (minLength <= 4) { + return matching >= 2; + } else { + 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. + * @param view a view for retrieving the context for AutoText + * @param wordComposer contains what is currently being typed + * @param prevWordForBigram previous word (used only for bigram) + * @return list of suggestions. + */ + public List getSuggestions(View view, WordComposer wordComposer, + boolean includeTypedWordIfValid, CharSequence prevWordForBigram) { + LatinImeLogger.onStartSuggestion(prevWordForBigram); + mHaveCorrection = false; + mIsFirstCharCapitalized = wordComposer.isFirstCharCapitalized(); + mIsAllUpperCase = wordComposer.isAllUpperCase(); + collectGarbage(mSuggestions, mPrefMaxSuggestions); + Arrays.fill(mPriorities, 0); + Arrays.fill(mNextLettersFrequencies, 0); + + // Save a lowercase version of the original word + mOriginalWord = wordComposer.getTypedWord(); + if (mOriginalWord != null) { + final String mOriginalWordString = mOriginalWord.toString(); + mOriginalWord = mOriginalWordString; + mLowerOriginalWord = mOriginalWordString.toLowerCase(); + // Treating USER_TYPED as UNIGRAM suggestion for logging now. + LatinImeLogger.onAddSuggestedWord(mOriginalWordString, Suggest.DIC_USER_TYPED, + Dictionary.DataType.UNIGRAM); + } else { + mLowerOriginalWord = ""; + } + + if (wordComposer.size() == 1 && (mCorrectionMode == CORRECTION_FULL_BIGRAM + || mCorrectionMode == CORRECTION_BASIC)) { + // At first character typed, search only the bigrams + Arrays.fill(mBigramPriorities, 0); + collectGarbage(mBigramSuggestions, PREF_MAX_BIGRAMS); + + if (!TextUtils.isEmpty(prevWordForBigram)) { + CharSequence lowerPrevWord = prevWordForBigram.toString().toLowerCase(); + if (mMainDict.isValidWord(lowerPrevWord)) { + prevWordForBigram = lowerPrevWord; + } + /*if (mUserBigramDictionary != null) { + mUserBigramDictionary.getBigrams(wordComposer, prevWordForBigram, this, + mNextLettersFrequencies); + } + if (mContactsDictionary != null) { + mContactsDictionary.getBigrams(wordComposer, prevWordForBigram, this, + mNextLettersFrequencies); + }*/ + if (mMainDict != null) { + mMainDict.getBigrams(wordComposer, prevWordForBigram, this, + mNextLettersFrequencies); + } + char currentChar = wordComposer.getTypedWord().charAt(0); + // TODO: Must pay attention to locale when changing case. + char currentCharUpper = Character.toUpperCase(currentChar); + int count = 0; + int bigramSuggestionSize = mBigramSuggestions.size(); + for (int i = 0; i < bigramSuggestionSize; i++) { + if (mBigramSuggestions.get(i).charAt(0) == currentChar + || mBigramSuggestions.get(i).charAt(0) == currentCharUpper) { + int poolSize = mStringPool.size(); + StringBuilder sb = poolSize > 0 ? + (StringBuilder) mStringPool.remove(poolSize - 1) + : new StringBuilder(getApproxMaxWordLength()); + sb.setLength(0); + sb.append(mBigramSuggestions.get(i)); + mSuggestions.add(count++, sb); + if (count > mPrefMaxSuggestions) break; + } + } + } + + } else if (wordComposer.size() > 1) { + // At second character typed, search the unigrams (scores being affected by bigrams) + /*if (mUserDictionary != null || mContactsDictionary != null) { + if (mUserDictionary != null) { + mUserDictionary.getWords(wordComposer, this, mNextLettersFrequencies); + } + if (mContactsDictionary != null) { + mContactsDictionary.getWords(wordComposer, this, mNextLettersFrequencies); + } + + if (mSuggestions.size() > 0 && isValidWord(mOriginalWord) + && (mCorrectionMode == CORRECTION_FULL + || mCorrectionMode == CORRECTION_FULL_BIGRAM)) { + mHaveCorrection = true; + } + }*/ + mMainDict.getWords(wordComposer, this, mNextLettersFrequencies); + if ((mCorrectionMode == CORRECTION_FULL || mCorrectionMode == CORRECTION_FULL_BIGRAM) + && mSuggestions.size() > 0) { + mHaveCorrection = true; + } + } + if (mOriginalWord != null) { + mSuggestions.add(0, mOriginalWord.toString()); + } + + // Check if the first suggestion has a minimum number of characters in common + if (wordComposer.size() > 1 && mSuggestions.size() > 1 + && (mCorrectionMode == CORRECTION_FULL + || mCorrectionMode == CORRECTION_FULL_BIGRAM)) { + if (!haveSufficientCommonality(mLowerOriginalWord, mSuggestions.get(1))) { + mHaveCorrection = false; + } + } + if (mAutoTextEnabled) { + int i = 0; + int max = 6; + // Don't autotext the suggestions from the dictionaries + if (mCorrectionMode == CORRECTION_BASIC) max = 1; + while (i < mSuggestions.size() && i < max) { + String suggestedWord = mSuggestions.get(i).toString().toLowerCase(); + CharSequence autoText = + AutoText.get(suggestedWord, 0, suggestedWord.length(), view); + // Is there an AutoText correction? + boolean canAdd = autoText != null; + // Is that correction already the current prediction (or original word)? + canAdd &= !TextUtils.equals(autoText, mSuggestions.get(i)); + // Is that correction already the next predicted word? + if (canAdd && i + 1 < mSuggestions.size() && mCorrectionMode != CORRECTION_BASIC) { + canAdd &= !TextUtils.equals(autoText, mSuggestions.get(i + 1)); + } + if (canAdd) { + mHaveCorrection = true; + mSuggestions.add(i + 1, autoText); + i++; + } + i++; + } + } + removeDupes(); + return mSuggestions; + } + + public int[] getNextLettersFrequencies() { + return mNextLettersFrequencies; + } + + 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; + } + + private boolean compareCaseInsensitive(final String mLowerOriginalWord, + final char[] word, final int offset, final int length) { + final int originalLength = mLowerOriginalWord.length(); + if (originalLength == length && Character.isUpperCase(word[offset])) { + for (int i = 0; i < originalLength; i++) { + if (mLowerOriginalWord.charAt(i) != Character.toLowerCase(word[offset+i])) { + return false; + } + } + return true; + } + return false; + } + + public boolean addWord(final char[] word, final int offset, final int length, int freq, + final int dicTypeId, final Dictionary.DataType dataType) { + Dictionary.DataType dataTypeForLog = dataType; + ArrayList suggestions; + int[] priorities; + int prefMaxSuggestions; + if(dataType == Dictionary.DataType.BIGRAM) { + suggestions = mBigramSuggestions; + priorities = mBigramPriorities; + prefMaxSuggestions = PREF_MAX_BIGRAMS; + } else { + suggestions = mSuggestions; + priorities = mPriorities; + prefMaxSuggestions = mPrefMaxSuggestions; + } + + int pos = 0; + + // Check if it's the same word, only caps are different + if (compareCaseInsensitive(mLowerOriginalWord, word, offset, length)) { + pos = 0; + } else { + if (dataType == Dictionary.DataType.UNIGRAM) { + // Check if the word was already added before (by bigram data) + int bigramSuggestion = searchBigramSuggestion(word,offset,length); + if(bigramSuggestion >= 0) { + dataTypeForLog = Dictionary.DataType.BIGRAM; + // turn freq from bigram into multiplier specified above + double multiplier = (((double) mBigramPriorities[bigramSuggestion]) + / MAXIMUM_BIGRAM_FREQUENCY) + * (BIGRAM_MULTIPLIER_MAX - BIGRAM_MULTIPLIER_MIN) + + BIGRAM_MULTIPLIER_MIN; + /* Log.d(TAG,"bigram num: " + bigramSuggestion + + " wordB: " + mBigramSuggestions.get(bigramSuggestion).toString() + + " currentPriority: " + freq + " bigramPriority: " + + mBigramPriorities[bigramSuggestion] + + " multiplier: " + multiplier); */ + freq = (int)Math.round((freq * multiplier)); + } + } + + // Check the last one's priority and bail + if (priorities[prefMaxSuggestions - 1] >= freq) return true; + while (pos < prefMaxSuggestions) { + if (priorities[pos] < freq + || (priorities[pos] == freq && length < suggestions.get(pos).length())) { + break; + } + pos++; + } + } + if (pos >= prefMaxSuggestions) { + return true; + } + + System.arraycopy(priorities, pos, priorities, pos + 1, + prefMaxSuggestions - pos - 1); + priorities[pos] = freq; + int poolSize = mStringPool.size(); + StringBuilder sb = poolSize > 0 ? (StringBuilder) mStringPool.remove(poolSize - 1) + : new StringBuilder(getApproxMaxWordLength()); + sb.setLength(0); + // TODO: Must pay attention to locale when changing case. + if (mIsAllUpperCase) { + sb.append(new String(word, offset, length).toUpperCase()); + } else if (mIsFirstCharCapitalized) { + sb.append(Character.toUpperCase(word[offset])); + if (length > 1) { + sb.append(word, offset + 1, length - 1); + } + } else { + sb.append(word, offset, length); + } + suggestions.add(pos, sb); + if (suggestions.size() > prefMaxSuggestions) { + CharSequence garbage = suggestions.remove(prefMaxSuggestions); + if (garbage instanceof StringBuilder) { + mStringPool.add(garbage); + } + } else { + LatinImeLogger.onAddSuggestedWord(sb.toString(), dicTypeId, dataTypeForLog); + } + return true; + } + + private int searchBigramSuggestion(final char[] word, final int offset, final int length) { + // TODO This is almost O(n^2). Might need fix. + // search whether the word appeared in bigram data + int bigramSuggestSize = mBigramSuggestions.size(); + for(int i = 0; i < bigramSuggestSize; i++) { + if(mBigramSuggestions.get(i).length() == length) { + boolean chk = true; + for(int j = 0; j < length; j++) { + if(mBigramSuggestions.get(i).charAt(j) != word[offset+j]) { + chk = false; + break; + } + } + if(chk) return i; + } + } + + return -1; + } + + public boolean isValidWord(final CharSequence word) { + if (word == null || word.length() == 0) { + return false; + } + return mMainDict.isValidWord(word) + /*|| (mUserDictionary != null && mUserDictionary.isValidWord(word)) + || (mAutoDictionary != null && mAutoDictionary.isValidWord(word)) + || (mContactsDictionary != null && mContactsDictionary.isValidWord(word))*/; + } + + private void collectGarbage(ArrayList suggestions, int prefMaxSuggestions) { + int poolSize = mStringPool.size(); + int garbageSize = suggestions.size(); + while (poolSize < prefMaxSuggestions && garbageSize > 0) { + CharSequence garbage = suggestions.get(garbageSize - 1); + if (garbage != null && garbage instanceof StringBuilder) { + mStringPool.add(garbage); + poolSize++; + } + garbageSize--; + } + if (poolSize == prefMaxSuggestions + 1) { + Log.w("Suggest", "String pool got too big: " + poolSize); + } + suggestions.clear(); + } + + public void close() { + if (mMainDict != null) { + mMainDict.close(); + } + } +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/SwipeTracker.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/SwipeTracker.java new file mode 100644 index 00000000..c5a522e1 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/SwipeTracker.java @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 keepass2android.softkeyboard; + +import android.view.MotionEvent; + +class SwipeTracker { + private static final int NUM_PAST = 4; + private static final int LONGEST_PAST_TIME = 200; + + final EventRingBuffer mBuffer = new EventRingBuffer(NUM_PAST); + + private float mYVelocity; + private float mXVelocity; + + public void addMovement(MotionEvent ev) { + if (ev.getAction() == MotionEvent.ACTION_DOWN) { + mBuffer.clear(); + return; + } + long time = ev.getEventTime(); + final int count = ev.getHistorySize(); + for (int i = 0; i < count; i++) { + addPoint(ev.getHistoricalX(i), ev.getHistoricalY(i), ev.getHistoricalEventTime(i)); + } + addPoint(ev.getX(), ev.getY(), time); + } + + private void addPoint(float x, float y, long time) { + final EventRingBuffer buffer = mBuffer; + while (buffer.size() > 0) { + long lastT = buffer.getTime(0); + if (lastT >= time - LONGEST_PAST_TIME) + break; + buffer.dropOldest(); + } + buffer.add(x, y, time); + } + + public void computeCurrentVelocity(int units) { + computeCurrentVelocity(units, Float.MAX_VALUE); + } + + public void computeCurrentVelocity(int units, float maxVelocity) { + final EventRingBuffer buffer = mBuffer; + final float oldestX = buffer.getX(0); + final float oldestY = buffer.getY(0); + final long oldestTime = buffer.getTime(0); + + float accumX = 0; + float accumY = 0; + final int count = buffer.size(); + for (int pos = 1; pos < count; pos++) { + final int dur = (int)(buffer.getTime(pos) - oldestTime); + if (dur == 0) continue; + float dist = buffer.getX(pos) - oldestX; + float vel = (dist / dur) * units; // pixels/frame. + if (accumX == 0) accumX = vel; + else accumX = (accumX + vel) * .5f; + + dist = buffer.getY(pos) - oldestY; + vel = (dist / dur) * units; // pixels/frame. + if (accumY == 0) accumY = vel; + else accumY = (accumY + vel) * .5f; + } + mXVelocity = accumX < 0.0f ? Math.max(accumX, -maxVelocity) + : Math.min(accumX, maxVelocity); + mYVelocity = accumY < 0.0f ? Math.max(accumY, -maxVelocity) + : Math.min(accumY, maxVelocity); + } + + public float getXVelocity() { + return mXVelocity; + } + + public float getYVelocity() { + return mYVelocity; + } + + static class EventRingBuffer { + private final int bufSize; + private final float xBuf[]; + private final float yBuf[]; + private final long timeBuf[]; + private int top; // points new event + private int end; // points oldest event + private int count; // the number of valid data + + public EventRingBuffer(int max) { + this.bufSize = max; + xBuf = new float[max]; + yBuf = new float[max]; + timeBuf = new long[max]; + clear(); + } + + public void clear() { + top = end = count = 0; + } + + public int size() { + return count; + } + + // Position 0 points oldest event + private int index(int pos) { + return (end + pos) % bufSize; + } + + private int advance(int index) { + return (index + 1) % bufSize; + } + + public void add(float x, float y, long time) { + xBuf[top] = x; + yBuf[top] = y; + timeBuf[top] = time; + top = advance(top); + if (count < bufSize) { + count++; + } else { + end = advance(end); + } + } + + public float getX(int pos) { + return xBuf[index(pos)]; + } + + public float getY(int pos) { + return yBuf[index(pos)]; + } + + public long getTime(int pos) { + return timeBuf[index(pos)]; + } + + public void dropOldest() { + count--; + end = advance(end); + } + } +} \ No newline at end of file diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/TextEntryState.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/TextEntryState.java new file mode 100644 index 00000000..4950425f --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/TextEntryState.java @@ -0,0 +1,278 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package keepass2android.softkeyboard; + +import android.content.Context; +import android.inputmethodservice.Keyboard.Key; +import android.text.format.DateFormat; +import android.util.Log; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Calendar; + +public class TextEntryState { + + private static final boolean DBG = false; + + private static final String TAG = "TextEntryState"; + + private static boolean LOGGING = false; + + private static int sBackspaceCount = 0; + + private static int sAutoSuggestCount = 0; + + private static int sAutoSuggestUndoneCount = 0; + + private static int sManualSuggestCount = 0; + + private static int sWordNotInDictionaryCount = 0; + + private static int sSessionCount = 0; + + private static int sTypedChars; + + private static int sActualChars; + + public enum State { + UNKNOWN, + START, + IN_WORD, + ACCEPTED_DEFAULT, + PICKED_SUGGESTION, + PUNCTUATION_AFTER_WORD, + PUNCTUATION_AFTER_ACCEPTED, + SPACE_AFTER_ACCEPTED, + SPACE_AFTER_PICKED, + UNDO_COMMIT, + CORRECTING, + PICKED_CORRECTION; + } + + private static State sState = State.UNKNOWN; + + private static FileOutputStream sKeyLocationFile; + private static FileOutputStream sUserActionFile; + + public static void newSession(Context context) { + sSessionCount++; + sAutoSuggestCount = 0; + sBackspaceCount = 0; + sAutoSuggestUndoneCount = 0; + sManualSuggestCount = 0; + sWordNotInDictionaryCount = 0; + sTypedChars = 0; + sActualChars = 0; + sState = State.START; + + if (LOGGING) { + try { + sKeyLocationFile = context.openFileOutput("key.txt", Context.MODE_APPEND); + sUserActionFile = context.openFileOutput("action.txt", Context.MODE_APPEND); + } catch (IOException ioe) { + Log.e("TextEntryState", "Couldn't open file for output: " + ioe); + } + } + } + + public static void endSession() { + if (sKeyLocationFile == null) { + return; + } + try { + sKeyLocationFile.close(); + // Write to log file + // Write timestamp, settings, + String out = DateFormat.format("MM:dd hh:mm:ss", Calendar.getInstance().getTime()) + .toString() + + " BS: " + sBackspaceCount + + " auto: " + sAutoSuggestCount + + " manual: " + sManualSuggestCount + + " typed: " + sWordNotInDictionaryCount + + " undone: " + sAutoSuggestUndoneCount + + " saved: " + ((float) (sActualChars - sTypedChars) / sActualChars) + + "\n"; + sUserActionFile.write(out.getBytes()); + sUserActionFile.close(); + sKeyLocationFile = null; + sUserActionFile = null; + } catch (IOException ioe) { + + } + } + + public static void acceptedDefault(CharSequence typedWord, CharSequence actualWord) { + if (typedWord == null) return; + if (!typedWord.equals(actualWord)) { + sAutoSuggestCount++; + } + sTypedChars += typedWord.length(); + sActualChars += actualWord.length(); + sState = State.ACCEPTED_DEFAULT; + LatinImeLogger.logOnAutoSuggestion(typedWord.toString(), actualWord.toString()); + displayState(); + } + + // State.ACCEPTED_DEFAULT will be changed to other sub-states + // (see "case ACCEPTED_DEFAULT" in typedCharacter() below), + // and should be restored back to State.ACCEPTED_DEFAULT after processing for each sub-state. + public static void backToAcceptedDefault(CharSequence typedWord) { + if (typedWord == null) return; + switch (sState) { + case SPACE_AFTER_ACCEPTED: + case PUNCTUATION_AFTER_ACCEPTED: + case IN_WORD: + sState = State.ACCEPTED_DEFAULT; + break; + } + displayState(); + } + + public static void acceptedTyped(CharSequence typedWord) { + sWordNotInDictionaryCount++; + sState = State.PICKED_SUGGESTION; + displayState(); + } + + public static void acceptedSuggestion(CharSequence typedWord, CharSequence actualWord) { + sManualSuggestCount++; + State oldState = sState; + if (typedWord.equals(actualWord)) { + acceptedTyped(typedWord); + } + if (oldState == State.CORRECTING || oldState == State.PICKED_CORRECTION) { + sState = State.PICKED_CORRECTION; + } else { + sState = State.PICKED_SUGGESTION; + } + displayState(); + } + + public static void selectedForCorrection() { + sState = State.CORRECTING; + displayState(); + } + + public static void typedCharacter(char c, boolean isSeparator) { + boolean isSpace = c == ' '; + switch (sState) { + case IN_WORD: + if (isSpace || isSeparator) { + sState = State.START; + } else { + // State hasn't changed. + } + break; + case ACCEPTED_DEFAULT: + case SPACE_AFTER_PICKED: + if (isSpace) { + sState = State.SPACE_AFTER_ACCEPTED; + } else if (isSeparator) { + sState = State.PUNCTUATION_AFTER_ACCEPTED; + } else { + sState = State.IN_WORD; + } + break; + case PICKED_SUGGESTION: + case PICKED_CORRECTION: + if (isSpace) { + sState = State.SPACE_AFTER_PICKED; + } else if (isSeparator) { + // Swap + sState = State.PUNCTUATION_AFTER_ACCEPTED; + } else { + sState = State.IN_WORD; + } + break; + case START: + case UNKNOWN: + case SPACE_AFTER_ACCEPTED: + case PUNCTUATION_AFTER_ACCEPTED: + case PUNCTUATION_AFTER_WORD: + if (!isSpace && !isSeparator) { + sState = State.IN_WORD; + } else { + sState = State.START; + } + break; + case UNDO_COMMIT: + if (isSpace || isSeparator) { + sState = State.ACCEPTED_DEFAULT; + } else { + sState = State.IN_WORD; + } + break; + case CORRECTING: + sState = State.START; + break; + } + displayState(); + } + + public static void backspace() { + if (sState == State.ACCEPTED_DEFAULT) { + sState = State.UNDO_COMMIT; + sAutoSuggestUndoneCount++; + LatinImeLogger.logOnAutoSuggestionCanceled(); + } else if (sState == State.UNDO_COMMIT) { + sState = State.IN_WORD; + } + sBackspaceCount++; + displayState(); + } + + public static void reset() { + sState = State.START; + displayState(); + } + + public static State getState() { + if (DBG) { + Log.d(TAG, "Returning state = " + sState); + } + return sState; + } + + public static boolean isCorrecting() { + return sState == State.CORRECTING || sState == State.PICKED_CORRECTION; + } + + public static void keyPressedAt(Key key, int x, int y) { + if (LOGGING && sKeyLocationFile != null && key.codes[0] >= 32) { + String out = + "KEY: " + (char) key.codes[0] + + " X: " + x + + " Y: " + y + + " MX: " + (key.x + key.width / 2) + + " MY: " + (key.y + key.height / 2) + + "\n"; + try { + sKeyLocationFile.write(out.getBytes()); + } catch (IOException ioe) { + // TODO: May run out of space + } + } + } + + private static void displayState() { + if (DBG) { + Log.d(TAG, "State = " + sState); + } + } +} + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/UserBigramDictionary.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/UserBigramDictionary.java new file mode 100644 index 00000000..820c2a8d --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/UserBigramDictionary.java @@ -0,0 +1,401 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 keepass2android.softkeyboard; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; + +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.database.sqlite.SQLiteQueryBuilder; +import android.os.AsyncTask; +import android.provider.BaseColumns; +import android.util.Log; + +/** + * Stores all the pairs user types in databases. Prune the database if the size + * gets too big. Unlike AutoDictionary, it even stores the pairs that are already + * in the dictionary. + */ +public class UserBigramDictionary extends ExpandableDictionary { + private static final String TAG = "UserBigramDictionary"; + + /** Any pair being typed or picked */ + private static final int FREQUENCY_FOR_TYPED = 2; + + /** Maximum frequency for all pairs */ + private static final int FREQUENCY_MAX = 127; + + /** + * If this pair is typed 6 times, it would be suggested. + * Should be smaller than ContactsDictionary.FREQUENCY_FOR_CONTACTS_BIGRAM + */ + protected static final int SUGGEST_THRESHOLD = 6 * FREQUENCY_FOR_TYPED; + + /** Maximum number of pairs. Pruning will start when databases goes above this number. */ + private static int sMaxUserBigrams = 10000; + + /** + * When it hits maximum bigram pair, it will delete until you are left with + * only (sMaxUserBigrams - sDeleteUserBigrams) pairs. + * Do not keep this number small to avoid deleting too often. + */ + private static int sDeleteUserBigrams = 1000; + + /** + * Database version should increase if the database structure changes + */ + private static final int DATABASE_VERSION = 1; + + private static final String DATABASE_NAME = "userbigram_dict.db"; + + /** Name of the words table in the database */ + private static final String MAIN_TABLE_NAME = "main"; + // TODO: Consume less space by using a unique id for locale instead of the whole + // 2-5 character string. (Same TODO from AutoDictionary) + private static final String MAIN_COLUMN_ID = BaseColumns._ID; + private static final String MAIN_COLUMN_WORD1 = "word1"; + private static final String MAIN_COLUMN_WORD2 = "word2"; + private static final String MAIN_COLUMN_LOCALE = "locale"; + + /** Name of the frequency table in the database */ + private static final String FREQ_TABLE_NAME = "frequency"; + private static final String FREQ_COLUMN_ID = BaseColumns._ID; + private static final String FREQ_COLUMN_PAIR_ID = "pair_id"; + private static final String FREQ_COLUMN_FREQUENCY = "freq"; + + private final KP2AKeyboard mIme; + + /** Locale for which this auto dictionary is storing words */ + private String mLocale; + + private HashSet mPendingWrites = new HashSet(); + private final Object mPendingWritesLock = new Object(); + private static volatile boolean sUpdatingDB = false; + + private final static HashMap sDictProjectionMap; + + static { + sDictProjectionMap = new HashMap(); + sDictProjectionMap.put(MAIN_COLUMN_ID, MAIN_COLUMN_ID); + sDictProjectionMap.put(MAIN_COLUMN_WORD1, MAIN_COLUMN_WORD1); + sDictProjectionMap.put(MAIN_COLUMN_WORD2, MAIN_COLUMN_WORD2); + sDictProjectionMap.put(MAIN_COLUMN_LOCALE, MAIN_COLUMN_LOCALE); + + sDictProjectionMap.put(FREQ_COLUMN_ID, FREQ_COLUMN_ID); + sDictProjectionMap.put(FREQ_COLUMN_PAIR_ID, FREQ_COLUMN_PAIR_ID); + sDictProjectionMap.put(FREQ_COLUMN_FREQUENCY, FREQ_COLUMN_FREQUENCY); + } + + private static DatabaseHelper sOpenHelper = null; + + private static class Bigram { + String word1; + String word2; + int frequency; + + Bigram(String word1, String word2, int frequency) { + this.word1 = word1; + this.word2 = word2; + this.frequency = frequency; + } + + @Override + public boolean equals(Object bigram) { + Bigram bigram2 = (Bigram) bigram; + return (word1.equals(bigram2.word1) && word2.equals(bigram2.word2)); + } + + @Override + public int hashCode() { + return (word1 + " " + word2).hashCode(); + } + } + + public void setDatabaseMax(int maxUserBigram) { + sMaxUserBigrams = maxUserBigram; + } + + public void setDatabaseDelete(int deleteUserBigram) { + sDeleteUserBigrams = deleteUserBigram; + } + + public UserBigramDictionary(Context context, KP2AKeyboard ime, String locale, int dicTypeId) { + super(context, dicTypeId); + mIme = ime; + mLocale = locale; + if (sOpenHelper == null) { + sOpenHelper = new DatabaseHelper(getContext()); + } + if (mLocale != null && mLocale.length() > 1) { + loadDictionary(); + } + } + + @Override + public void close() { + flushPendingWrites(); + // Don't close the database as locale changes will require it to be reopened anyway + // Also, the database is written to somewhat frequently, so it needs to be kept alive + // throughout the life of the process. + // mOpenHelper.close(); + super.close(); + } + + /** + * Pair will be added to the userbigram database. + */ + public int addBigrams(String word1, String word2) { + // remove caps + if (mIme != null && mIme.getCurrentWord().isAutoCapitalized()) { + word2 = Character.toLowerCase(word2.charAt(0)) + word2.substring(1); + } + + int freq = super.addBigram(word1, word2, FREQUENCY_FOR_TYPED); + if (freq > FREQUENCY_MAX) freq = FREQUENCY_MAX; + synchronized (mPendingWritesLock) { + if (freq == FREQUENCY_FOR_TYPED || mPendingWrites.isEmpty()) { + mPendingWrites.add(new Bigram(word1, word2, freq)); + } else { + Bigram bi = new Bigram(word1, word2, freq); + mPendingWrites.remove(bi); + mPendingWrites.add(bi); + } + } + + return freq; + } + + /** + * Schedules a background thread to write any pending words to the database. + */ + public void flushPendingWrites() { + synchronized (mPendingWritesLock) { + // Nothing pending? Return + if (mPendingWrites.isEmpty()) return; + // Create a background thread to write the pending entries + new UpdateDbTask(getContext(), sOpenHelper, mPendingWrites, mLocale).execute(); + // Create a new map for writing new entries into while the old one is written to db + mPendingWrites = new HashSet(); + } + } + + /** Used for testing purpose **/ + void waitUntilUpdateDBDone() { + synchronized (mPendingWritesLock) { + while (sUpdatingDB) { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + } + } + return; + } + } + + @Override + public void loadDictionaryAsync() { + // Load the words that correspond to the current input locale + Cursor cursor = query(MAIN_COLUMN_LOCALE + "=?", new String[] { mLocale }); + try { + if (cursor.moveToFirst()) { + int word1Index = cursor.getColumnIndex(MAIN_COLUMN_WORD1); + int word2Index = cursor.getColumnIndex(MAIN_COLUMN_WORD2); + int frequencyIndex = cursor.getColumnIndex(FREQ_COLUMN_FREQUENCY); + while (!cursor.isAfterLast()) { + String word1 = cursor.getString(word1Index); + String word2 = cursor.getString(word2Index); + int frequency = cursor.getInt(frequencyIndex); + // Safeguard against adding really long words. Stack may overflow due + // to recursive lookup + if (word1.length() < MAX_WORD_LENGTH && word2.length() < MAX_WORD_LENGTH) { + super.setBigram(word1, word2, frequency); + } + cursor.moveToNext(); + } + } + } finally { + cursor.close(); + } + } + + /** + * Query the database + */ + private Cursor query(String selection, String[] selectionArgs) { + SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); + + // main INNER JOIN frequency ON (main._id=freq.pair_id) + qb.setTables(MAIN_TABLE_NAME + " INNER JOIN " + FREQ_TABLE_NAME + " ON (" + + MAIN_TABLE_NAME + "." + MAIN_COLUMN_ID + "=" + FREQ_TABLE_NAME + "." + + FREQ_COLUMN_PAIR_ID +")"); + + qb.setProjectionMap(sDictProjectionMap); + + // Get the database and run the query + SQLiteDatabase db = sOpenHelper.getReadableDatabase(); + Cursor c = qb.query(db, + new String[] { MAIN_COLUMN_WORD1, MAIN_COLUMN_WORD2, FREQ_COLUMN_FREQUENCY }, + selection, selectionArgs, null, null, null); + return c; + } + + /** + * This class helps open, create, and upgrade the database file. + */ + private static class DatabaseHelper extends SQLiteOpenHelper { + + DatabaseHelper(Context context) { + super(context, DATABASE_NAME, null, DATABASE_VERSION); + } + + @Override + public void onCreate(SQLiteDatabase db) { + db.execSQL("PRAGMA foreign_keys = ON;"); + db.execSQL("CREATE TABLE " + MAIN_TABLE_NAME + " (" + + MAIN_COLUMN_ID + " INTEGER PRIMARY KEY," + + MAIN_COLUMN_WORD1 + " TEXT," + + MAIN_COLUMN_WORD2 + " TEXT," + + MAIN_COLUMN_LOCALE + " TEXT" + + ");"); + db.execSQL("CREATE TABLE " + FREQ_TABLE_NAME + " (" + + FREQ_COLUMN_ID + " INTEGER PRIMARY KEY," + + FREQ_COLUMN_PAIR_ID + " INTEGER," + + FREQ_COLUMN_FREQUENCY + " INTEGER," + + "FOREIGN KEY(" + FREQ_COLUMN_PAIR_ID + ") REFERENCES " + MAIN_TABLE_NAME + + "(" + MAIN_COLUMN_ID + ")" + " ON DELETE CASCADE" + + ");"); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + + newVersion + ", which will destroy all old data"); + db.execSQL("DROP TABLE IF EXISTS " + MAIN_TABLE_NAME); + db.execSQL("DROP TABLE IF EXISTS " + FREQ_TABLE_NAME); + onCreate(db); + } + } + + /** + * Async task to write pending words to the database so that it stays in sync with + * the in-memory trie. + */ + private static class UpdateDbTask extends AsyncTask { + private final HashSet mMap; + private final DatabaseHelper mDbHelper; + private final String mLocale; + + public UpdateDbTask(Context context, DatabaseHelper openHelper, + HashSet pendingWrites, String locale) { + mMap = pendingWrites; + mLocale = locale; + mDbHelper = openHelper; + } + + /** Prune any old data if the database is getting too big. */ + private void checkPruneData(SQLiteDatabase db) { + db.execSQL("PRAGMA foreign_keys = ON;"); + Cursor c = db.query(FREQ_TABLE_NAME, new String[] { FREQ_COLUMN_PAIR_ID }, + null, null, null, null, null); + try { + int totalRowCount = c.getCount(); + // prune out old data if we have too much data + if (totalRowCount > sMaxUserBigrams) { + int numDeleteRows = (totalRowCount - sMaxUserBigrams) + sDeleteUserBigrams; + int pairIdColumnId = c.getColumnIndex(FREQ_COLUMN_PAIR_ID); + c.moveToFirst(); + int count = 0; + while (count < numDeleteRows && !c.isAfterLast()) { + String pairId = c.getString(pairIdColumnId); + // Deleting from MAIN table will delete the frequencies + // due to FOREIGN KEY .. ON DELETE CASCADE + db.delete(MAIN_TABLE_NAME, MAIN_COLUMN_ID + "=?", + new String[] { pairId }); + c.moveToNext(); + count++; + } + } + } finally { + c.close(); + } + } + + @Override + protected void onPreExecute() { + sUpdatingDB = true; + } + + @Override + protected Void doInBackground(Void... v) { + SQLiteDatabase db = mDbHelper.getWritableDatabase(); + db.execSQL("PRAGMA foreign_keys = ON;"); + // Write all the entries to the db + Iterator iterator = mMap.iterator(); + while (iterator.hasNext()) { + Bigram bi = iterator.next(); + + // find pair id + Cursor c = db.query(MAIN_TABLE_NAME, new String[] { MAIN_COLUMN_ID }, + MAIN_COLUMN_WORD1 + "=? AND " + MAIN_COLUMN_WORD2 + "=? AND " + + MAIN_COLUMN_LOCALE + "=?", + new String[] { bi.word1, bi.word2, mLocale }, null, null, null); + + int pairId; + if (c.moveToFirst()) { + // existing pair + pairId = c.getInt(c.getColumnIndex(MAIN_COLUMN_ID)); + db.delete(FREQ_TABLE_NAME, FREQ_COLUMN_PAIR_ID + "=?", + new String[] { Integer.toString(pairId) }); + } else { + // new pair + Long pairIdLong = db.insert(MAIN_TABLE_NAME, null, + getContentValues(bi.word1, bi.word2, mLocale)); + pairId = pairIdLong.intValue(); + } + c.close(); + + // insert new frequency + db.insert(FREQ_TABLE_NAME, null, getFrequencyContentValues(pairId, bi.frequency)); + } + checkPruneData(db); + sUpdatingDB = false; + + return null; + } + + private ContentValues getContentValues(String word1, String word2, String locale) { + ContentValues values = new ContentValues(3); + values.put(MAIN_COLUMN_WORD1, word1); + values.put(MAIN_COLUMN_WORD2, word2); + values.put(MAIN_COLUMN_LOCALE, locale); + return values; + } + + private ContentValues getFrequencyContentValues(int pairId, int frequency) { + ContentValues values = new ContentValues(2); + values.put(FREQ_COLUMN_PAIR_ID, pairId); + values.put(FREQ_COLUMN_FREQUENCY, frequency); + return values; + } + } + +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/UserDictionary.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/UserDictionary.java new file mode 100644 index 00000000..5366d6f0 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/UserDictionary.java @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package keepass2android.softkeyboard; + +import android.content.ContentResolver; +import android.content.ContentValues; +import android.content.Context; +import android.database.ContentObserver; +import android.database.Cursor; +import android.provider.UserDictionary.Words; + +public class UserDictionary extends ExpandableDictionary { + + private static final String[] PROJECTION = { + Words._ID, + Words.WORD, + Words.FREQUENCY + }; + + private static final int INDEX_WORD = 1; + private static final int INDEX_FREQUENCY = 2; + + private ContentObserver mObserver; + private String mLocale; + + public UserDictionary(Context context, String locale) { + super(context, Suggest.DIC_USER); + mLocale = locale; + // Perform a managed query. The Activity will handle closing and requerying the cursor + // when needed. + ContentResolver cres = context.getContentResolver(); + + cres.registerContentObserver(Words.CONTENT_URI, true, mObserver = new ContentObserver(null) { + @Override + public void onChange(boolean self) { + setRequiresReload(true); + } + }); + + loadDictionary(); + } + + @Override + public synchronized void close() { + if (mObserver != null) { + getContext().getContentResolver().unregisterContentObserver(mObserver); + mObserver = null; + } + super.close(); + } + + @Override + public void loadDictionaryAsync() { + //Cursor cursor = getContext().getContentResolver() + // .query(Words.CONTENT_URI, PROJECTION, "(locale IS NULL) or (locale=?)", + // new String[] { mLocale }, null); + //addWords(cursor); + } + + /** + * Adds a word to the dictionary and makes it persistent. + * @param word the word to add. If the word is capitalized, then the dictionary will + * recognize it as a capitalized word when searched. + * @param frequency the frequency of occurrence of the word. A frequency of 255 is considered + * the highest. + * @TODO use a higher or float range for frequency + */ + @Override + public synchronized void addWord(String word, int frequency) { + // Force load the dictionary here synchronously + if (getRequiresReload()) loadDictionaryAsync(); + // Safeguard against adding long words. Can cause stack overflow. + if (word.length() >= getMaxWordLength()) return; + + super.addWord(word, frequency); + + // Update the user dictionary provider + final ContentValues values = new ContentValues(5); + values.put(Words.WORD, word); + values.put(Words.FREQUENCY, frequency); + values.put(Words.LOCALE, mLocale); + values.put(Words.APP_ID, 0); + + final ContentResolver contentResolver = getContext().getContentResolver(); + new Thread("addWord") { + public void run() { + contentResolver.insert(Words.CONTENT_URI, values); + } + }.start(); + + // In case the above does a synchronous callback of the change observer + setRequiresReload(false); + } + + @Override + public synchronized void getWords(final WordComposer codes, final WordCallback callback, + int[] nextLettersFrequencies) { + super.getWords(codes, callback, nextLettersFrequencies); + } + + @Override + public synchronized boolean isValidWord(CharSequence word) { + return super.isValidWord(word); + } + + private void addWords(Cursor cursor) { + 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() < maxWordLength) { + super.addWord(word, frequency); + } + cursor.moveToNext(); + } + } + cursor.close(); + } +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/WordComposer.java b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/WordComposer.java new file mode 100644 index 00000000..47cd4ece --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/WordComposer.java @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package keepass2android.softkeyboard; + +import java.util.ArrayList; + +/** + * A place to store the currently composing word with information such as adjacent key codes as well + */ +public class WordComposer { + /** + * The list of unicode values for each keystroke (including surrounding keys) + */ + private final ArrayList mCodes; + + /** + * The word chosen from the candidate list, until it is committed. + */ + private String mPreferredWord; + + private final StringBuilder mTypedWord; + + private int mCapsCount; + + private boolean mAutoCapitalized; + + /** + * Whether the user chose to capitalize the first char of the word. + */ + private boolean mIsFirstCharCapitalized; + + public WordComposer() { + mCodes = new ArrayList(12); + mTypedWord = new StringBuilder(20); + } + + WordComposer(WordComposer copy) { + mCodes = new ArrayList(copy.mCodes); + mPreferredWord = copy.mPreferredWord; + mTypedWord = new StringBuilder(copy.mTypedWord); + mCapsCount = copy.mCapsCount; + mAutoCapitalized = copy.mAutoCapitalized; + mIsFirstCharCapitalized = copy.mIsFirstCharCapitalized; + } + + /** + * Clear out the keys registered so far. + */ + public void reset() { + mCodes.clear(); + mIsFirstCharCapitalized = false; + mPreferredWord = null; + mTypedWord.setLength(0); + mCapsCount = 0; + } + + /** + * Number of keystrokes in the composing word. + * @return the number of keystrokes + */ + public int size() { + return mCodes.size(); + } + + /** + * Returns the codes at a particular position in the word. + * @param index the position in the word + * @return the unicode for the pressed and surrounding keys + */ + public int[] getCodesAt(int index) { + return mCodes.get(index); + } + + /** + * Add a new keystroke, with codes[0] containing the pressed key's unicode and the rest of + * the array containing unicode for adjacent keys, sorted by reducing probability/proximity. + * @param codes the array of unicode values + */ + public void add(int primaryCode, int[] codes) { + mTypedWord.append((char) primaryCode); + correctPrimaryJuxtapos(primaryCode, codes); + mCodes.add(codes); + if (Character.isUpperCase((char) primaryCode)) mCapsCount++; + } + + /** + * Swaps the first and second values in the codes array if the primary code is not the first + * value in the array but the second. This happens when the preferred key is not the key that + * the user released the finger on. + * @param primaryCode the preferred character + * @param codes array of codes based on distance from touch point + */ + private void correctPrimaryJuxtapos(int primaryCode, int[] codes) { + if (codes.length < 2) return; + if (codes[0] > 0 && codes[1] > 0 && codes[0] != primaryCode && codes[1] == primaryCode) { + codes[1] = codes[0]; + codes[0] = primaryCode; + } + } + + /** + * Delete the last keystroke as a result of hitting backspace. + */ + public void deleteLast() { + final int codesSize = mCodes.size(); + if (codesSize > 0) { + mCodes.remove(codesSize - 1); + final int lastPos = mTypedWord.length() - 1; + char last = mTypedWord.charAt(lastPos); + mTypedWord.deleteCharAt(lastPos); + if (Character.isUpperCase(last)) mCapsCount--; + } + } + + /** + * Returns the word as it was typed, without any correction applied. + * @return the word that was typed so far + */ + public CharSequence getTypedWord() { + int wordSize = mCodes.size(); + if (wordSize == 0) { + return null; + } + return mTypedWord; + } + + public void setFirstCharCapitalized(boolean capitalized) { + mIsFirstCharCapitalized = capitalized; + } + + /** + * Whether or not the user typed a capital letter as the first letter in the word + * @return capitalization preference + */ + public boolean isFirstCharCapitalized() { + return mIsFirstCharCapitalized; + } + + /** + * Whether or not all of the user typed chars are upper case + * @return true if all user typed chars are upper case, false otherwise + */ + public boolean isAllUpperCase() { + return (mCapsCount > 0) && (mCapsCount == size()); + } + + /** + * Stores the user's selected word, before it is actually committed to the text field. + * @param preferred + */ + public void setPreferredWord(String preferred) { + mPreferredWord = preferred; + } + + /** + * Return the word chosen by the user, or the typed word if no other word was chosen. + * @return the preferred word + */ + 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; + } + + /** + * Saves the reason why the word is capitalized - whether it was automatic or + * due to the user hitting shift in the middle of a sentence. + * @param auto whether it was an automatic capitalization due to start of sentence + */ + public void setAutoCapitalized(boolean auto) { + mAutoCapitalized = auto; + } + + /** + * Returns whether the word was automatically capitalized. + * @return whether the word was automatically capitalized + */ + public boolean isAutoCapitalized() { + return mAutoCapitalized; + } +} diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/jniLibs/armeabi-v7a/libjni_latinime.so b/src/java/KP2ASoftkeyboard_AS/app/src/main/jniLibs/armeabi-v7a/libjni_latinime.so new file mode 100644 index 00000000..fce10f89 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/jniLibs/armeabi-v7a/libjni_latinime.so differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/jniLibs/armeabi/libjni_latinime.so b/src/java/KP2ASoftkeyboard_AS/app/src/main/jniLibs/armeabi/libjni_latinime.so new file mode 100644 index 00000000..3f97a516 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/jniLibs/armeabi/libjni_latinime.so differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/jniLibs/mips/libjni_latinime.so b/src/java/KP2ASoftkeyboard_AS/app/src/main/jniLibs/mips/libjni_latinime.so new file mode 100644 index 00000000..87fddde6 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/jniLibs/mips/libjni_latinime.so differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/jniLibs/x86/libjni_latinime.so b/src/java/KP2ASoftkeyboard_AS/app/src/main/jniLibs/x86/libjni_latinime.so new file mode 100644 index 00000000..7dc1bbe4 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/jniLibs/x86/libjni_latinime.so differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/anim/key_preview_fadein.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/anim/key_preview_fadein.xml new file mode 100644 index 00000000..9fad7b9a --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/anim/key_preview_fadein.xml @@ -0,0 +1,29 @@ + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/anim/key_preview_fadeout.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/anim/key_preview_fadeout.xml new file mode 100644 index 00000000..7de5123c --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/anim/key_preview_fadeout.xml @@ -0,0 +1,29 @@ + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/anim/mini_keyboard_fadein.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/anim/mini_keyboard_fadein.xml new file mode 100644 index 00000000..9fad7b9a --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/anim/mini_keyboard_fadein.xml @@ -0,0 +1,29 @@ + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/anim/mini_keyboard_fadeout.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/anim/mini_keyboard_fadeout.xml new file mode 100644 index 00000000..7de5123c --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/anim/mini_keyboard_fadeout.xml @@ -0,0 +1,29 @@ + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_dark_normal.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_dark_normal.9.png new file mode 100644 index 00000000..01fc8ca7 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_dark_normal.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_dark_normal_off.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_dark_normal_off.9.png new file mode 100644 index 00000000..af4017e2 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_dark_normal_off.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_dark_normal_on.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_dark_normal_on.9.png new file mode 100644 index 00000000..4c35aca9 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_dark_normal_on.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_dark_pressed.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_dark_pressed.9.png new file mode 100644 index 00000000..174f3452 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_dark_pressed.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off.9.png new file mode 100644 index 00000000..1fcbd9a8 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_dark_pressed_off.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on.9.png new file mode 100644 index 00000000..072753f3 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_dark_pressed_on.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_fulltrans_normal.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_fulltrans_normal.9.png new file mode 100644 index 00000000..b6c234c0 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_fulltrans_normal.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_fulltrans_pressed.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_fulltrans_pressed.9.png new file mode 100644 index 00000000..73a8cd1c Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_fulltrans_pressed.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_light_normal.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_light_normal.9.png new file mode 100644 index 00000000..1ad74605 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_light_normal.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_light_popup_normal.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_light_popup_normal.9.png new file mode 100644 index 00000000..e3a77d61 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_light_popup_normal.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_light_popup_selected.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_light_popup_selected.9.png new file mode 100644 index 00000000..431c4496 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_light_popup_selected.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_light_pressed.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_light_pressed.9.png new file mode 100644 index 00000000..ccd59d5f Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_light_pressed.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_normal.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_normal.9.png new file mode 100644 index 00000000..42c7c146 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_normal.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_normal_off.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_normal_off.9.png new file mode 100644 index 00000000..01e2506b Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_normal_off.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_normal_off_stone.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_normal_off_stone.9.png new file mode 100644 index 00000000..fad0ec45 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_normal_off_stone.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_normal_on.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_normal_on.9.png new file mode 100644 index 00000000..83c6eb3f Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_normal_on.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_normal_on_stone.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_normal_on_stone.9.png new file mode 100644 index 00000000..215f8157 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_normal_on_stone.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_normal_stone.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_normal_stone.9.png new file mode 100644 index 00000000..88acdd74 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_normal_stone.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_pressed.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_pressed.9.png new file mode 100644 index 00000000..e047eaff Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_pressed.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_pressed_off.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_pressed_off.9.png new file mode 100644 index 00000000..218a2d29 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_pressed_off.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_pressed_on.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_pressed_on.9.png new file mode 100644 index 00000000..afe49512 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/btn_keyboard_key_pressed_on.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/cancel.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/cancel.png new file mode 100644 index 00000000..506cf99d Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/cancel.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/candidate_feedback_background.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/candidate_feedback_background.9.png new file mode 100644 index 00000000..203c4e64 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/candidate_feedback_background.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/caution.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/caution.png new file mode 100644 index 00000000..5cb6c54b Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/caution.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/dialog_bubble_step02.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/dialog_bubble_step02.9.png new file mode 100644 index 00000000..b338364c Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/dialog_bubble_step02.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/dialog_bubble_step07.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/dialog_bubble_step07.9.png new file mode 100644 index 00000000..94b91543 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/dialog_bubble_step07.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/highlight_pressed.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/highlight_pressed.png new file mode 100644 index 00000000..ae04901a Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/highlight_pressed.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/hint_popup.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/hint_popup.9.png new file mode 100644 index 00000000..b5ec003e Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/hint_popup.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/ic_dialog_keyboard.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/ic_dialog_keyboard.png new file mode 100644 index 00000000..c7729566 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/ic_dialog_keyboard.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/ic_mic_dialog.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/ic_mic_dialog.png new file mode 100644 index 00000000..349dc4b3 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/ic_mic_dialog.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/ic_subtype_keyboard.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/ic_subtype_keyboard.png new file mode 100644 index 00000000..7015e266 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/ic_subtype_keyboard.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/ic_subtype_mic.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/ic_subtype_mic.png new file mode 100644 index 00000000..cb86a559 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/ic_subtype_mic.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/ic_suggest_strip_microphone.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/ic_suggest_strip_microphone.png new file mode 100644 index 00000000..c00b4aaa Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/ic_suggest_strip_microphone.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/ic_suggest_strip_microphone_swipe.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/ic_suggest_strip_microphone_swipe.png new file mode 100644 index 00000000..256dc3d6 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/ic_suggest_strip_microphone_swipe.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_background.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_background.9.png new file mode 100644 index 00000000..edffac5b Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_background.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_dark_background.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_dark_background.9.png new file mode 100644 index 00000000..f315cbdd Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_dark_background.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_hint_0.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_hint_0.9.png new file mode 100644 index 00000000..271264e9 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_hint_0.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_hint_1.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_hint_1.9.png new file mode 100644 index 00000000..eaf37426 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_hint_1.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_hint_2.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_hint_2.9.png new file mode 100644 index 00000000..8a165711 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_hint_2.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_hint_3.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_hint_3.9.png new file mode 100644 index 00000000..34b50110 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_hint_3.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_hint_4.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_hint_4.9.png new file mode 100644 index 00000000..d4cc250d Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_hint_4.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_hint_5.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_hint_5.9.png new file mode 100644 index 00000000..6a054b42 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_hint_5.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_hint_6.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_hint_6.9.png new file mode 100644 index 00000000..66e91400 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_hint_6.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_hint_7.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_hint_7.9.png new file mode 100644 index 00000000..5eae24f4 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_hint_7.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_hint_8.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_hint_8.9.png new file mode 100644 index 00000000..ea7f512f Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_hint_8.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_hint_9.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_hint_9.9.png new file mode 100644 index 00000000..0bf85de9 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_hint_9.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_key_feedback_background.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_key_feedback_background.9.png new file mode 100644 index 00000000..762a2570 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_key_feedback_background.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_key_feedback_more_background.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_key_feedback_more_background.9.png new file mode 100644 index 00000000..141d2d6b Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_key_feedback_more_background.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_popup_panel_background.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_popup_panel_background.9.png new file mode 100644 index 00000000..d6b2c793 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_popup_panel_background.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_suggest_strip.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_suggest_strip.9.png new file mode 100644 index 00000000..0ccdb6ab Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_suggest_strip.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_suggest_strip_divider.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_suggest_strip_divider.png new file mode 100644 index 00000000..7ca3e613 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/keyboard_suggest_strip_divider.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/list_selector_background_pressed.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/list_selector_background_pressed.9.png new file mode 100644 index 00000000..ba79cf7f Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/list_selector_background_pressed.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/mic_slash.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/mic_slash.png new file mode 100644 index 00000000..dc8da625 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/mic_slash.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/ok_cancel.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/ok_cancel.png new file mode 100644 index 00000000..f11e57a3 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/ok_cancel.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/speak_now_level0.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/speak_now_level0.png new file mode 100644 index 00000000..342849cf Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/speak_now_level0.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/speak_now_level1.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/speak_now_level1.png new file mode 100644 index 00000000..8947a430 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/speak_now_level1.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/speak_now_level2.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/speak_now_level2.png new file mode 100644 index 00000000..44fc58c4 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/speak_now_level2.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/speak_now_level3.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/speak_now_level3.png new file mode 100644 index 00000000..cfa5c1b8 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/speak_now_level3.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/speak_now_level4.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/speak_now_level4.png new file mode 100644 index 00000000..a050d883 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/speak_now_level4.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/speak_now_level5.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/speak_now_level5.png new file mode 100644 index 00000000..8cd5ae7a Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/speak_now_level5.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/speak_now_level6.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/speak_now_level6.png new file mode 100644 index 00000000..9f4481eb Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/speak_now_level6.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_123_mic.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_123_mic.png new file mode 100644 index 00000000..3e4eff69 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_123_mic.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_delete.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_delete.png new file mode 100644 index 00000000..1d24cc85 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_delete.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_done.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_done.png new file mode 100644 index 00000000..b77803d2 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_done.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_kp2a.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_kp2a.png new file mode 100644 index 00000000..66608769 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_kp2a.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_mic.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_mic.png new file mode 100644 index 00000000..512f4608 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_mic.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_num0.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_num0.png new file mode 100644 index 00000000..678a790d Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_num0.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_num1.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_num1.png new file mode 100644 index 00000000..4e68e35b Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_num1.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_num2.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_num2.png new file mode 100644 index 00000000..546663fd Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_num2.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_num3.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_num3.png new file mode 100644 index 00000000..57f9a8d8 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_num3.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_num4.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_num4.png new file mode 100644 index 00000000..de504388 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_num4.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_num5.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_num5.png new file mode 100644 index 00000000..1d2e1ef8 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_num5.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_num6.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_num6.png new file mode 100644 index 00000000..39788b72 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_num6.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_num7.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_num7.png new file mode 100644 index 00000000..fff6f27b Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_num7.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_num8.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_num8.png new file mode 100644 index 00000000..8cc1a955 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_num8.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_num9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_num9.png new file mode 100644 index 00000000..02174250 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_num9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_numalt.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_numalt.png new file mode 100644 index 00000000..200714f6 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_numalt.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_numpound.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_numpound.png new file mode 100644 index 00000000..0a46122b Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_numpound.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_numstar.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_numstar.png new file mode 100644 index 00000000..ca22bd53 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_numstar.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_return.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_return.png new file mode 100644 index 00000000..426e1599 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_return.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_search.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_search.png new file mode 100644 index 00000000..1b6f884f Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_search.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_settings.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_settings.png new file mode 100644 index 00000000..08ba18f2 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_settings.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_shift.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_shift.png new file mode 100644 index 00000000..5a22dd30 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_shift.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_shift_locked.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_shift_locked.png new file mode 100644 index 00000000..56644912 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_shift_locked.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_space.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_space.png new file mode 100644 index 00000000..cd0ebe2f Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_space.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_tab.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_tab.png new file mode 100644 index 00000000..3466e127 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_bkeyboard_tab.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard.png new file mode 100644 index 00000000..b57ae665 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_123_mic.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_123_mic.png new file mode 100644 index 00000000..62669803 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_123_mic.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_delete.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_delete.png new file mode 100644 index 00000000..459ebcff Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_delete.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_done.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_done.png new file mode 100644 index 00000000..471c5021 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_done.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_123_mic.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_123_mic.png new file mode 100644 index 00000000..eef78968 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_123_mic.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_delete.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_delete.png new file mode 100644 index 00000000..8322e8e1 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_delete.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_done.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_done.png new file mode 100644 index 00000000..7015e266 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_done.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_kp2a.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_kp2a.png new file mode 100644 index 00000000..d4616218 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_kp2a.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_language_arrows_left.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_language_arrows_left.png new file mode 100644 index 00000000..889477cf Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_language_arrows_left.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_language_arrows_right.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_language_arrows_right.png new file mode 100644 index 00000000..b0f6d7fe Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_language_arrows_right.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_mic.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_mic.png new file mode 100644 index 00000000..f82c33ae Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_mic.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_numalt.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_numalt.png new file mode 100644 index 00000000..819236c8 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_numalt.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_return.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_return.png new file mode 100644 index 00000000..f038d3ab Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_return.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_search.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_search.png new file mode 100644 index 00000000..337f9e4f Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_search.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_settings.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_settings.png new file mode 100644 index 00000000..8a02be07 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_settings.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_shift.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_shift.png new file mode 100644 index 00000000..abf15f8f Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_shift.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_shift_locked.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_shift_locked.png new file mode 100644 index 00000000..1fd822ea Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_shift_locked.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_space.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_space.png new file mode 100644 index 00000000..70debca9 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_space.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_tab.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_tab.png new file mode 100644 index 00000000..d2efb161 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_feedback_tab.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_kp2a.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_kp2a.png new file mode 100644 index 00000000..f3cfbd4e Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_kp2a.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_language_arrows_left.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_language_arrows_left.png new file mode 100644 index 00000000..dcc4bd59 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_language_arrows_left.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_language_arrows_right.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_language_arrows_right.png new file mode 100644 index 00000000..ecf61a98 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_language_arrows_right.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_mic.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_mic.png new file mode 100644 index 00000000..c8dca62a Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_mic.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_num0.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_num0.png new file mode 100644 index 00000000..10ac70b9 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_num0.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_num1.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_num1.png new file mode 100644 index 00000000..0fc03efa Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_num1.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_num2.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_num2.png new file mode 100644 index 00000000..283560b3 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_num2.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_num3.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_num3.png new file mode 100644 index 00000000..9a3b3294 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_num3.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_num4.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_num4.png new file mode 100644 index 00000000..f13ff1ae Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_num4.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_num5.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_num5.png new file mode 100644 index 00000000..c251329f Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_num5.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_num6.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_num6.png new file mode 100644 index 00000000..4acba4c9 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_num6.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_num7.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_num7.png new file mode 100644 index 00000000..14931c18 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_num7.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_num8.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_num8.png new file mode 100644 index 00000000..d4973fdc Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_num8.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_num9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_num9.png new file mode 100644 index 00000000..49cec66f Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_num9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_numalt.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_numalt.png new file mode 100644 index 00000000..3cc5311c Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_numalt.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_numpound.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_numpound.png new file mode 100644 index 00000000..d0913392 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_numpound.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_numstar.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_numstar.png new file mode 100644 index 00000000..e838e169 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_numstar.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_return.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_return.png new file mode 100644 index 00000000..9d97e1ef Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_return.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_search.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_search.png new file mode 100644 index 00000000..1aa22d7e Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_search.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_settings.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_settings.png new file mode 100644 index 00000000..35d1ed6e Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_settings.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_shift.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_shift.png new file mode 100644 index 00000000..bf217d14 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_shift.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_shift_locked.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_shift_locked.png new file mode 100644 index 00000000..d11b3971 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_shift_locked.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_space.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_space.png new file mode 100644 index 00000000..fcd20de7 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_space.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_space_led.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_space_led.9.png new file mode 100644 index 00000000..2c6f4a92 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_space_led.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_tab.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_tab.png new file mode 100644 index 00000000..51d17d98 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/sym_keyboard_tab.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/voice_ime_background.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/voice_ime_background.9.png new file mode 100644 index 00000000..42868522 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/voice_ime_background.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/voice_swipe_hint.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/voice_swipe_hint.png new file mode 100644 index 00000000..130f83a9 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/voice_swipe_hint.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/working.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/working.png new file mode 100644 index 00000000..5ea70230 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-hdpi/working.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-land/btn_keyboard_key.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-land/btn_keyboard_key.xml new file mode 100644 index 00000000..45578e58 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-land/btn_keyboard_key.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_dark_normal.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_dark_normal.9.png new file mode 100644 index 00000000..4e337fa0 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_dark_normal.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_dark_normal_off.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_dark_normal_off.9.png new file mode 100644 index 00000000..fe18497d Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_dark_normal_off.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_dark_normal_on.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_dark_normal_on.9.png new file mode 100644 index 00000000..00aab3d5 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_dark_normal_on.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_dark_pressed.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_dark_pressed.9.png new file mode 100644 index 00000000..ac0bfd3c Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_dark_pressed.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off.9.png new file mode 100644 index 00000000..ea2f3578 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_dark_pressed_off.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on.9.png new file mode 100644 index 00000000..6195ac0d Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_dark_pressed_on.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_fulltrans_normal.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_fulltrans_normal.9.png new file mode 100644 index 00000000..20f3d508 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_fulltrans_normal.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_fulltrans_pressed.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_fulltrans_pressed.9.png new file mode 100644 index 00000000..1ed3065c Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_fulltrans_pressed.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_light_normal.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_light_normal.9.png new file mode 100644 index 00000000..50cd06ae Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_light_normal.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_light_popup_normal.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_light_popup_normal.9.png new file mode 100644 index 00000000..02d0fcf9 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_light_popup_normal.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_light_popup_selected.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_light_popup_selected.9.png new file mode 100644 index 00000000..125ff133 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_light_popup_selected.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_light_pressed.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_light_pressed.9.png new file mode 100644 index 00000000..7ce52f0f Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_light_pressed.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_normal.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_normal.9.png new file mode 100644 index 00000000..7ba18dd2 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_normal.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_normal_off.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_normal_off.9.png new file mode 100644 index 00000000..bda9b839 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_normal_off.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_normal_off_stone.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_normal_off_stone.9.png new file mode 100644 index 00000000..fad0ec45 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_normal_off_stone.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_normal_on.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_normal_on.9.png new file mode 100644 index 00000000..0c16ed50 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_normal_on.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_normal_on_stone.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_normal_on_stone.9.png new file mode 100644 index 00000000..215f8157 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_normal_on_stone.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_normal_stone.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_normal_stone.9.png new file mode 100644 index 00000000..88acdd74 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_normal_stone.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_pressed.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_pressed.9.png new file mode 100644 index 00000000..39b9314a Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_pressed.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_pressed_off.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_pressed_off.9.png new file mode 100644 index 00000000..bdcf06e1 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_pressed_off.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_pressed_on.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_pressed_on.9.png new file mode 100644 index 00000000..79621a9e Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/btn_keyboard_key_pressed_on.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/cancel.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/cancel.png new file mode 100644 index 00000000..713a3787 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/cancel.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/candidate_feedback_background.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/candidate_feedback_background.9.png new file mode 100644 index 00000000..2a80f096 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/candidate_feedback_background.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/caution.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/caution.png new file mode 100644 index 00000000..eaef5342 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/caution.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/dialog_bubble_step02.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/dialog_bubble_step02.9.png new file mode 100644 index 00000000..d77f85fe Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/dialog_bubble_step02.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/dialog_bubble_step07.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/dialog_bubble_step07.9.png new file mode 100644 index 00000000..80f4a0ea Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/dialog_bubble_step07.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/highlight_pressed.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/highlight_pressed.png new file mode 100644 index 00000000..d27f1061 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/highlight_pressed.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/hint_popup.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/hint_popup.9.png new file mode 100644 index 00000000..444cc26e Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/hint_popup.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/ic_dialog_keyboard.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/ic_dialog_keyboard.png new file mode 100644 index 00000000..9a5aada8 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/ic_dialog_keyboard.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/ic_mic_dialog.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/ic_mic_dialog.png new file mode 100644 index 00000000..77613ca0 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/ic_mic_dialog.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/ic_subtype_keyboard.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/ic_subtype_keyboard.png new file mode 100644 index 00000000..0d7ebd4e Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/ic_subtype_keyboard.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/ic_subtype_mic.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/ic_subtype_mic.png new file mode 100644 index 00000000..247d5b3a Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/ic_subtype_mic.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/ic_suggest_strip_microphone.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/ic_suggest_strip_microphone.png new file mode 100644 index 00000000..18f314a6 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/ic_suggest_strip_microphone.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/ic_suggest_strip_microphone_swipe.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/ic_suggest_strip_microphone_swipe.png new file mode 100644 index 00000000..ff629b67 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/ic_suggest_strip_microphone_swipe.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_background.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_background.9.png new file mode 100644 index 00000000..2bd4b628 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_background.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_dark_background.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_dark_background.9.png new file mode 100644 index 00000000..4f81704c Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_dark_background.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_hint_0.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_hint_0.9.png new file mode 100644 index 00000000..61ad1b50 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_hint_0.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_hint_1.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_hint_1.9.png new file mode 100644 index 00000000..cd7772e7 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_hint_1.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_hint_2.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_hint_2.9.png new file mode 100644 index 00000000..fa5f8b79 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_hint_2.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_hint_3.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_hint_3.9.png new file mode 100644 index 00000000..0c7336cb Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_hint_3.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_hint_4.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_hint_4.9.png new file mode 100644 index 00000000..73ef06c0 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_hint_4.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_hint_5.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_hint_5.9.png new file mode 100644 index 00000000..aea460e1 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_hint_5.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_hint_6.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_hint_6.9.png new file mode 100644 index 00000000..16a9237e Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_hint_6.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_hint_7.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_hint_7.9.png new file mode 100644 index 00000000..6747a19c Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_hint_7.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_hint_8.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_hint_8.9.png new file mode 100644 index 00000000..28be2fb8 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_hint_8.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_hint_9.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_hint_9.9.png new file mode 100644 index 00000000..731d63b1 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_hint_9.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_key_feedback_background.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_key_feedback_background.9.png new file mode 100644 index 00000000..a84c19c3 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_key_feedback_background.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_key_feedback_more_background.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_key_feedback_more_background.9.png new file mode 100644 index 00000000..82513aad Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_key_feedback_more_background.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_popup_panel_background.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_popup_panel_background.9.png new file mode 100644 index 00000000..0d9ab97f Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_popup_panel_background.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_suggest_strip.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_suggest_strip.9.png new file mode 100644 index 00000000..fa6c0fef Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_suggest_strip.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_suggest_strip_divider.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_suggest_strip_divider.png new file mode 100644 index 00000000..36393636 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/keyboard_suggest_strip_divider.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/list_selector_background_pressed.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/list_selector_background_pressed.9.png new file mode 100644 index 00000000..02b4e9a5 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/list_selector_background_pressed.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/mic_slash.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/mic_slash.png new file mode 100644 index 00000000..d04b5634 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/mic_slash.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/ok_cancel.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/ok_cancel.png new file mode 100644 index 00000000..20d10f98 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/ok_cancel.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/speak_now_level0.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/speak_now_level0.png new file mode 100644 index 00000000..5bd13603 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/speak_now_level0.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/speak_now_level1.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/speak_now_level1.png new file mode 100644 index 00000000..ccb76b87 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/speak_now_level1.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/speak_now_level2.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/speak_now_level2.png new file mode 100644 index 00000000..715f9008 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/speak_now_level2.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/speak_now_level3.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/speak_now_level3.png new file mode 100644 index 00000000..725248a2 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/speak_now_level3.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/speak_now_level4.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/speak_now_level4.png new file mode 100644 index 00000000..ff6c50b4 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/speak_now_level4.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/speak_now_level5.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/speak_now_level5.png new file mode 100644 index 00000000..a5d6b89d Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/speak_now_level5.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/speak_now_level6.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/speak_now_level6.png new file mode 100644 index 00000000..dcdb48d0 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/speak_now_level6.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_123_mic.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_123_mic.png new file mode 100644 index 00000000..0749b5fc Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_123_mic.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_delete.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_delete.png new file mode 100644 index 00000000..1a5ff439 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_delete.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_done.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_done.png new file mode 100644 index 00000000..05ce7c64 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_done.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_kp2a.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_kp2a.png new file mode 100644 index 00000000..300d6b88 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_kp2a.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_mic.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_mic.png new file mode 100644 index 00000000..a6cb1cc0 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_mic.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_num0.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_num0.png new file mode 100644 index 00000000..7188f9ca Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_num0.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_num1.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_num1.png new file mode 100644 index 00000000..2a31bd45 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_num1.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_num2.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_num2.png new file mode 100644 index 00000000..c1e9cc9b Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_num2.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_num3.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_num3.png new file mode 100644 index 00000000..e9987668 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_num3.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_num4.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_num4.png new file mode 100644 index 00000000..7f0f3ccc Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_num4.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_num5.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_num5.png new file mode 100644 index 00000000..5f748b41 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_num5.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_num6.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_num6.png new file mode 100644 index 00000000..78aae74a Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_num6.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_num7.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_num7.png new file mode 100644 index 00000000..5bb874c4 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_num7.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_num8.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_num8.png new file mode 100644 index 00000000..6b58fdc8 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_num8.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_num9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_num9.png new file mode 100644 index 00000000..f348c92a Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_num9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_numalt.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_numalt.png new file mode 100644 index 00000000..4fa410b6 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_numalt.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_numpound.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_numpound.png new file mode 100644 index 00000000..9126eed0 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_numpound.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_numstar.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_numstar.png new file mode 100644 index 00000000..9b9f1b98 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_numstar.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_return.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_return.png new file mode 100644 index 00000000..e76225d0 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_return.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_search.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_search.png new file mode 100644 index 00000000..1f180155 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_search.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_settings.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_settings.png new file mode 100644 index 00000000..08ba18f2 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_settings.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_shift.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_shift.png new file mode 100644 index 00000000..c981188d Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_shift.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_shift_locked.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_shift_locked.png new file mode 100644 index 00000000..b8cebd06 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_shift_locked.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_space.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_space.png new file mode 100644 index 00000000..4da7ee86 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_space.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_tab.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_tab.png new file mode 100644 index 00000000..2cb991cb Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_bkeyboard_tab.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard.png new file mode 100644 index 00000000..33d68ccc Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_123_mic.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_123_mic.png new file mode 100644 index 00000000..35afe082 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_123_mic.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_delete.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_delete.png new file mode 100644 index 00000000..1b0f3f83 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_delete.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_done.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_done.png new file mode 100644 index 00000000..c0d6d139 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_done.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_123_mic.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_123_mic.png new file mode 100644 index 00000000..c556c35c Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_123_mic.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_delete.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_delete.png new file mode 100644 index 00000000..a79f1585 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_delete.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_done.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_done.png new file mode 100644 index 00000000..0d7ebd4e Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_done.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_kp2a.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_kp2a.png new file mode 100644 index 00000000..c3dc5a9c Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_kp2a.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_language_arrows_left.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_language_arrows_left.png new file mode 100644 index 00000000..eecb0269 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_language_arrows_left.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_language_arrows_right.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_language_arrows_right.png new file mode 100644 index 00000000..7e10ae3a Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_language_arrows_right.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_mic.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_mic.png new file mode 100644 index 00000000..3ed0782d Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_mic.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_numalt.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_numalt.png new file mode 100644 index 00000000..bc8f1cfc Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_numalt.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_return.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_return.png new file mode 100644 index 00000000..dd99ff38 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_return.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_search.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_search.png new file mode 100644 index 00000000..6b8e01d9 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_search.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_settings.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_settings.png new file mode 100644 index 00000000..03bad184 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_settings.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_shift.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_shift.png new file mode 100644 index 00000000..d5635755 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_shift.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_shift_locked.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_shift_locked.png new file mode 100644 index 00000000..494524a6 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_shift_locked.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_space.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_space.png new file mode 100644 index 00000000..36eb60c1 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_space.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_tab.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_tab.png new file mode 100644 index 00000000..a10dc8fa Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_feedback_tab.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_kp2a.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_kp2a.png new file mode 100644 index 00000000..db54e0ba Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_kp2a.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_language_arrows_left.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_language_arrows_left.png new file mode 100644 index 00000000..7067a8bf Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_language_arrows_left.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_language_arrows_right.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_language_arrows_right.png new file mode 100644 index 00000000..f7a133d9 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_language_arrows_right.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_mic.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_mic.png new file mode 100644 index 00000000..e926b3fa Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_mic.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_num0.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_num0.png new file mode 100644 index 00000000..e7007c87 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_num0.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_num1.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_num1.png new file mode 100644 index 00000000..aaac11b0 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_num1.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_num2.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_num2.png new file mode 100644 index 00000000..4372eb8f Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_num2.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_num3.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_num3.png new file mode 100644 index 00000000..6f54c850 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_num3.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_num4.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_num4.png new file mode 100644 index 00000000..3e50bb95 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_num4.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_num5.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_num5.png new file mode 100644 index 00000000..c39ef440 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_num5.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_num6.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_num6.png new file mode 100644 index 00000000..ea88ceb9 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_num6.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_num7.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_num7.png new file mode 100644 index 00000000..ce800ba4 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_num7.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_num8.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_num8.png new file mode 100644 index 00000000..1a8ff94b Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_num8.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_num9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_num9.png new file mode 100644 index 00000000..8b344c0a Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_num9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_numalt.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_numalt.png new file mode 100644 index 00000000..32a2cf3c Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_numalt.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_numpound.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_numpound.png new file mode 100644 index 00000000..b2419d9a Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_numpound.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_numstar.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_numstar.png new file mode 100644 index 00000000..cb66f968 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_numstar.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_return.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_return.png new file mode 100644 index 00000000..0c10f004 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_return.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_search.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_search.png new file mode 100644 index 00000000..614f85f5 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_search.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_settings.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_settings.png new file mode 100644 index 00000000..ad7618fa Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_settings.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_shift.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_shift.png new file mode 100644 index 00000000..5109b047 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_shift.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_shift_lock.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_shift_lock.png new file mode 100644 index 00000000..244179c2 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_shift_lock.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_shift_locked.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_shift_locked.png new file mode 100644 index 00000000..244179c2 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_shift_locked.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_space.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_space.png new file mode 100644 index 00000000..cbe4a88d Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_space.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_space_led.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_space_led.9.png new file mode 100644 index 00000000..1c1ca2cc Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_space_led.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_tab.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_tab.png new file mode 100644 index 00000000..eddb9a59 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/sym_keyboard_tab.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/voice_ime_background.9.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/voice_ime_background.9.png new file mode 100644 index 00000000..9b15bc25 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/voice_ime_background.9.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/voice_swipe_hint.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/voice_swipe_hint.png new file mode 100644 index 00000000..bb887325 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/voice_swipe_hint.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/working.png b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/working.png new file mode 100644 index 00000000..4a930c52 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable-mdpi/working.png differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable/btn_keyboard_key.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable/btn_keyboard_key.xml new file mode 100644 index 00000000..45578e58 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable/btn_keyboard_key.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable/btn_keyboard_key2.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable/btn_keyboard_key2.xml new file mode 100644 index 00000000..bd745b76 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable/btn_keyboard_key2.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable/btn_keyboard_key3.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable/btn_keyboard_key3.xml new file mode 100644 index 00000000..dbe82d5f --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable/btn_keyboard_key3.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable/btn_keyboard_key_fulltrans.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable/btn_keyboard_key_fulltrans.xml new file mode 100644 index 00000000..bad2a931 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable/btn_keyboard_key_fulltrans.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable/btn_keyboard_key_gingerbread.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable/btn_keyboard_key_gingerbread.xml new file mode 100644 index 00000000..4a113a8a --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable/btn_keyboard_key_gingerbread.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable/btn_keyboard_key_gingerbread_popup.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable/btn_keyboard_key_gingerbread_popup.xml new file mode 100644 index 00000000..9b6d23be --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable/btn_keyboard_key_gingerbread_popup.xml @@ -0,0 +1,21 @@ + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable/btn_keyboard_key_stone.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable/btn_keyboard_key_stone.xml new file mode 100644 index 00000000..a6040a04 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable/btn_keyboard_key_stone.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable/ic_suggest_scroll_background.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable/ic_suggest_scroll_background.xml new file mode 100644 index 00000000..9d246e40 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable/ic_suggest_scroll_background.xml @@ -0,0 +1,25 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable/keyboard_key_feedback.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable/keyboard_key_feedback.xml new file mode 100644 index 00000000..159ba868 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/drawable/keyboard_key_feedback.xml @@ -0,0 +1,22 @@ + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/bubble_text.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/bubble_text.xml new file mode 100644 index 00000000..c3957b65 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/bubble_text.xml @@ -0,0 +1,30 @@ + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/candidate_preview.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/candidate_preview.xml new file mode 100644 index 00000000..fe2002d4 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/candidate_preview.xml @@ -0,0 +1,29 @@ + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/candidates.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/candidates.xml new file mode 100644 index 00000000..f30b817e --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/candidates.xml @@ -0,0 +1,38 @@ + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/input_basic.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/input_basic.xml new file mode 100644 index 00000000..0176565a --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/input_basic.xml @@ -0,0 +1,31 @@ + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/input_basic_highcontrast.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/input_basic_highcontrast.xml new file mode 100644 index 00000000..b85eb2ba --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/input_basic_highcontrast.xml @@ -0,0 +1,32 @@ + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/input_gingerbread.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/input_gingerbread.xml new file mode 100644 index 00000000..164fc0b7 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/input_gingerbread.xml @@ -0,0 +1,36 @@ + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/input_stone_bold.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/input_stone_bold.xml new file mode 100644 index 00000000..1eac195c --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/input_stone_bold.xml @@ -0,0 +1,37 @@ + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/input_stone_normal.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/input_stone_normal.xml new file mode 100644 index 00000000..6669dfff --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/input_stone_normal.xml @@ -0,0 +1,35 @@ + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/input_stone_popup.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/input_stone_popup.xml new file mode 100644 index 00000000..7b876b66 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/input_stone_popup.xml @@ -0,0 +1,41 @@ + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/key_preview.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/key_preview.xml new file mode 100644 index 00000000..de03506a --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/key_preview.xml @@ -0,0 +1,29 @@ + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/keyboard_popup.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/keyboard_popup.xml new file mode 100644 index 00000000..ee997290 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/keyboard_popup.xml @@ -0,0 +1,41 @@ + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/recognition_status.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/recognition_status.xml new file mode 100644 index 00000000..49af7736 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/recognition_status.xml @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/voice_punctuation_hint.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/voice_punctuation_hint.xml new file mode 100644 index 00000000..629a7f2b --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/voice_punctuation_hint.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/voice_swipe_hint.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/voice_swipe_hint.xml new file mode 100644 index 00000000..4e8859a7 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/layout/voice_swipe_hint.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/raw/main.dict b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/raw/main.dict new file mode 100644 index 00000000..472c23a2 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/raw/main.dict differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/raw/type3.ogg b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/raw/type3.ogg new file mode 100644 index 00000000..20e67080 Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/raw/type3.ogg differ diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ar/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ar/strings.xml new file mode 100644 index 00000000..d841a61f --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ar/strings.xml @@ -0,0 +1,140 @@ + + + + + "لوحة مفاتيح Keepass2Android" + "إعدادات لوحة مفاتيح Keepass2Android" + "خيارات الإرسال" + "اهتزاز عند الضغط على مفتاح" + "صوت عند الضغط على مفتاح" + "انبثاق عند الضغط على المفاتيح" + "تصحيح أخطاء الكتابة" + "تمكين تصحيح خطأ الإدخال" + "أخطاء في الإدخال الأفقي" + "تمكين تصحيح خطأ الإدخال" + "اقتراحات الكلمات" + "تصحيح الكلمة السابقة تلقائيًا" + "اقتراحات الكلمات" + "إعدادات اقتراحات الكلمات" + "تمكين الإكمال التلقائي أثناء الكتابة" + "إكمال تلقائي" + "زيادة حجم الحقل النصي" + "إخفاء اقتراحات الكلمات في طريقة العرض الأفقية" + "استخدام الأحرف الكبيرة تلقائيًا" + "استخدام الأحرف الكبيرة في بداية الجملة" + "ترقيم تلقائي" + + "إصلاحات سريعة" + "تصحيح الأخطاء المكتوبة الشائعة" + "عرض الاقتراحات" + "عرض الكلمات المقترحة أثناء الكتابة" + "إكمال تلقائي" + "مفتاح المسافة والترقيم لإدخال كلمة محددة تلقائيًا" + "عرض مفتاح الإعدادات" + "تلقائي" + "إظهار بشكل دائم" + "إخفاء دومًا" + + + + "اقتراحات ثنائية" + "استخدام الكلمة السابقة لتحسين الاقتراح" + + "لا شيء" + "أساسي" + "متقدم" + + "%s : تم الحفظ" + "اضغط باستمرار على أحد المفاتيح لأسفل لمشاهدة علامات التشكيل" + "اضغط على مفتاح الرجوع ↶ لإغلاق لوحة المفاتيح في أي نقطة" + "الدخول إلى الأرقام والرموز" + "اضغط مع الاستمرار على أقصى يمين الكلمة لإضافتها إلى القاموس" + "المس هذا التلميح للمتابعة »" + "المس هنا لإغلاق هذا التلميح وبدء الكتابة!" + "تفتح لوحة المفاتيح في أي وقت تلمس فيه حقلًا نصيًا" + "المس مع الاستمرار أحد المفاتيح لعرض علامات التشكيل"\n"(ø, ö, ô, ó, وهكذا)" + "التبديل إلى الأرقام والرموز من خلال لمس هذا الزر" + "يمكنك الرجوع إلى الأحرف من خلال لمس هذا المفتاح مرة أخرى" + "المس هذا المفتاح مع الاستمرار لتغيير إعدادات لوحة المفاتيح، مثل الإكمال التلقائي" + "جربه!" + "تنفيذ" + "التالي" + "تم" + "إرسال" + "?123" + "123" + "ب ت ث" + "ALT" + "الإدخال الصوتي" + "الإدخال الصوتي غير معتمد حاليًا للغتك، ولكنه يعمل باللغة الإنجليزية." + "الإدخال الصوتي هو ميزة تجريبية تستخدم التعرف على الكلام المتصل في Google." + "لتشغيل الإدخال الصوتي، انتقل إلى إعدادات لوحة المفاتيح." + "لاستخدام الإدخال الصوتي، اضغط على زر الميكروفون أو مرر إصبعك عبر لوحة المفاتيح على الشاشة." + "تحدث الآن" + "العمل" + + "خطأ. الرجاء المحاولة مرة أخرى." + "تعذر الاتصال" + "خطأ، كلام أكثر مما ينبغي." + "مشكلة بالإعدادات الصوتية" + "خطأ في الخادم" + "لم يتم سماع كلام" + "لم يتمّ العثور على أية تطابقات" + "لم يتم تثبيت البحث الصوتي" + "تلميح:"" مرر عبر لوحة المفاتيح للتحدث" + "تلميح:"" جرب في المرة التالية نطق الترقيم مثل \"نقطة\" أو \"فاصلة\" أو \"علامة استفهام\"." + "إلغاء" + "موافق" + "الإدخال الصوتي" + + "في لوحة المفاتيح الرئيسية" + "على لوحة مفاتيح الرموز" + "إيقاف" + + + "الميكروفون في لوحة المفاتيح الرئيسية" + "الميكروفون على لوحة مفاتيح الرموز" + "تم تعطيل الإدخال الصوتي" + + "إرسال تلقائي بعد الصوت" + "الضغط تلقائيًا على المفتاح enter عند البحث أو الانتقال إلى الحقل التالي." + "افتح لوحة المفاتيح"\n\n"المس أي حقل نصي." + "إغلاق لوحة المفاتيح"\n\n"اضغط على المفتاح \"رجوع\"." + "المس أحد مفاتيح الخيارات مع الاستمرار"\n\n"الدخول إلى الترقيم والحركات." + "إعدادات لوحة المفاتيح"\n\n"المس مع الاستمرار المفتاح ""?123""." + "com." + "net." + "org." + "gov." + "edu." + "تحديد طريقة الإرسال" + "لغات الإدخال" + "مرر إصبعك على مفتاح المسافة لتغيير اللغة" + "← المس مرة أخرى للحفظ" + "القاموس متاح" + "تمكين ملاحظات المستخدم" + "المساعدة في تحسين محرر طريقة الإرسال هذا من خلال إرسال إحصاءات الاستخدام وتقارير الأعطال تلقائيًا إلى Google." + "المس لتصحيح الكلمات" + "المس الكلمات المدخلة لتصحيحها" + "مظهر لوحة المفاتيح" + "لوحة مفاتيح" + "صوت" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ar/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ar/strings_kp2a.xml new file mode 100644 index 00000000..7845cbac --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ar/strings_kp2a.xml @@ -0,0 +1,20 @@ + + + + اختر مُدخل آخر + اختر مُدخل + البحث عن مُدخل يحتوي على \"%1$s\" + المستخدم + كلمة السر + اعدادات ادخال البيانات السرية + التعبئة الاوتوماتيكية مفعلة + ملئ البيانات تلقائيا عند وجود حقل فارغ اذا وجد keePass2 Android ان البيانات متوفرة للوحة المفاتيح. + تذكر نصوص حقول التلميح + اذا عبئ الحقل يدويا عن طريق استخدام قيم keepass2Android، تذكر اي قيمة استخدمت و استخدم نص التلميح لذلك الحقل حتى تعاد تعبئتها تلقائيا. + لوحة المفاتيح بسيطة + إظهار لوحة المفاتيح ذات الصف الواحد إذا وجد إدخال متاح للوحة المفاتيح. في حالة التعطيل، يظهر صندوق حوار عند الضغط على مفتاح Keepass2Android. + اقفال قاعدة البيانات عند الانتهاء + عند الضغط على مفتاح \'ذهاب\' على لوحة المفاتيح البسيطة، اقفل قاعدة بيانات. + بدل لوحة المفاتيح عند الانتهاء + عند الضغط على مفتاح \'ذهاب\' على لوحة المفاتيح البسيطة، ابدل لوحة المفاتيح. + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-bg-rBG/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-bg-rBG/strings_kp2a.xml new file mode 100644 index 00000000..b5d5f436 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-bg-rBG/strings_kp2a.xml @@ -0,0 +1,20 @@ + + + + Изберете друг запис + Изберете стойност + Търсене за въведено с \"%1$s\" + Потребител + Парола + Входни настройки на данни + Автоматично попълване е включено + Автоматично попълване при въведено празно поле, ако е Keepass2Android запис е на разположение за клавиатурата и има стойност, която съответства на полето на подсказване. + Запомни скрития текст в полето + Ако текстово поле е попълнено чрез ръчно избиране на стойност от Keepass2Android, запомни коя стойност е въведена в текстовото поле. Полето по-късно ще бъде сравнено със скритата стойност. + Проста клавиатура + Покажи простата 1 редова клавиатура ако стойноста е налична. Ако е изключена се показва диалог при натискане на бутон на Keepass2Android + Заключване на базата данни, когато е готово + При натискане на клавиша Done/Send/Go на простата 1-редова клавиатура, автоматично се заключва на базата данни. + Превключване на клавиатурата, когато свършиш + При натискане на клавиша Done/Send/Go на простата 1-редова клавиатура, превключи клавиатурата. + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-bg/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-bg/strings.xml new file mode 100644 index 00000000..45602fa1 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-bg/strings.xml @@ -0,0 +1,140 @@ + + + + + "Клавиатура на Keepass2Android" + "Настройки на клавиатурата на Keepass2Android" + "Опции за въвеждане" + "Да вибрира при натискане на клавиш" + "Звук при натискане на клавиш" + "Изскачащ прозорец при натискане на клавиш" + "Коригиране на грешките при въвеждане" + "Активиране на корекция на грешки при въвеждане" + "Грешки при въвеждане в хоризонтален изглед" + "Активиране на корекция на грешки при въвеждане" + "Предложения на думи" + "Автоматично коригиране на предишната дума" + "Предложения на думи" + "Настройки за предложения на думи" + "Активиране на автодовършване, докато пишете" + "Автодовършване" + "Размерът на текстовото поле да се увеличи" + "Скриване на предложенията на думи в хоризонтален изглед" + "Автоматично поставяне на главни букви" + "Поставя главна буква в началото на изреченията" + "Автоматично поставяне на пунктуация" + + "Бързи корекции" + "Коригира най-честите грешки при въвеждане" + "Показване на предложения" + "Показване на предложения, докато пишете" + "Автоматично завършване" + "Клавишът за интервал и пунктуация поставя автоматично откроена дума" + "Показване на клавиша за настройки" + "Автоматично" + "Да се показва винаги" + "Да се скрива винаги" + + + + "Предложения за биграми" + "Използване на предишната дума за подобряване на предложението" + + "Няма" + "Основен" + "Разширени" + + "%s : Запазено" + "Задръжте клавиша, за да видите ударенията (ø, ö и т.н.)" + "Натиснете клавиша „Назад“ ↶, за да затворите клавиатурата във всяка една точка" + "Достъп до номера и символи" + "Натиснете и задръжте върху най-лявата дума, за да я добавите към речника" + "Докоснете съвета, за да продължите »" + "Докоснете тук, за да затворите този съвет и да започнете да пишете!" + "Клавиатурата се отваря при всяко докосване на текстово поле" + "Докоснете и задръжте клавиша, за да видите ударенията"\n"(ø, ö, ô, ó и т.н.)" + "Докосването на този клавиш води до преминаване към цифри и символи" + "Върнете се към използване на букви чрез повторно докосване на този клавиш" + "Докоснете и задръжте клавиша за промяна на настройките на клавиатурата, напр. автодовършване" + "Пробвайте!" + "Старт" + "Напред" + "Готово" + "Изпращане" + "?123" + "123" + "АБВГ" + "ALT" + "Гласово въвеждане" + "За вашия език понастоящем не се поддържа гласово въвеждане, но можете да го използвате на английски." + "Гласовото въвеждане е експериментална функция, използваща разпознаването на реч в мрежата на Google." + "За да изключите гласовото въвеждане, отворете настройките на клавиатурата." + "За да използвате гласово въвеждане, натиснете бутона на микрофона или плъзнете пръст през екранната клавиатура." + "Говорете сега" + "Обработва се" + + "Грешка. Моля, опитайте отново." + "Не можа да се свърже" + "Грешка, твърде много речева информация." + "Аудиопроблем" + "Грешка в сървъра" + "Не се чува реч" + "Нямаше съответствия" + "Не е инсталирано гласово търсене" + "Съвет:"" Прокарайте палец през клавиатурата, за да говорите" + "Съвет:"" Следващия път опитайте да произнесете знаците за пунктуация, напр. „точка“, „запетая“ или „въпросителен знак“." + "Отказ" + "OK" + "Гласово въвеждане" + + "На основната клавиатура" + "На клавиатурата на символите" + "Изкл." + + + "Микрофон на основната клавиатура" + "Микрофон на клавиатурата на символите" + "Гласовото въвеждане е деактивирано" + + "Автоматично изпращане след глас" + "Да се натиска автоматично „Enter“ при търсене или преминаване към следващото поле." + "Отворете клавиатурата"\n\n"Докоснете текстово поле." + "Затваряне на клавиатурата"\n\n"Натиснете клавиша „Назад“." + "Докоснете и задръжте клавиш за опции"\n\n"Използвайте пунктуация и акценти." + "Настройки на клавиатурата"\n\n"Докоснете и задръжте клавиша ""?123""." + ".com" + ".net" + ".org" + ".gov" + ".edu" + "Избор на метод на въвеждане" + "Входни езици" + "Плъзнете пръст по клавиша за интервал за промяна на езика" + "← Докоснете отново, за да запазите" + "Има достъп до речник" + "Активиране на отзивите от потребителите" + "Помогнете за подобряването на този редактор за въвеждане чрез автоматично изпращане до Google на статистически данни за употребата и сигнали за сривове." + "Докоснете, за да поправите думите" + "Докоснете въведените думи, за да ги поправите" + "Тема на клавиатурата" + "клавиатура" + "гласово" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ca/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ca/strings.xml new file mode 100644 index 00000000..dd52076b --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ca/strings.xml @@ -0,0 +1,140 @@ + + + + + "Teclat Keepass2Android" + "Configuració del teclat d\'Keepass2Android" + "Opcions d\'entrada" + "Vibra en prémer tecles" + "So en prémer una tecla" + "Finestra emergent en prémer un botó" + "Corregeix els errors ortogràfics" + "Activa la correcció d\'errors d\'entrada" + "Errors d\'entrada en horitzontal" + "Activa la correcció d\'errors d\'entrada" + "Suggeriments de paraules" + "Corregeix automàticament la paraula anterior" + "Suggeriments de paraules" + "Configuració de suggeriment de paraules" + "Activa l\'emplenament automàtic mentre s\'escriu" + "Emplenament automàtic" + "Augmenta la mida del camp de text" + "Amaga els suggeriments de paraules en visualització horitzontal" + "Majúscules automàtiques" + "Posa l\'inici d\'una frase en majúscula" + "Puntuació automàtica" + + "Correccions ràpides" + "Corregeix els errors d\'ortografia habituals" + "Mostra els suggeriments" + "Visualitza paraules suggerides mentre s\'escriu" + "Emplenament automàtic" + "La barra espaiadora i la puntuació insereixen automàticament la paraula ressaltada" + "Mostra la tecla de configuració" + "Automàtic" + "Mostra sempre" + "Amaga sempre" + + + + "Suggeriments Bigram" + "Utilitza la paraula anterior per millorar el suggeriment" + + "Cap" + "Bàsic" + "Avançat" + + "%s: desada" + "Manteniu una tecla premuda per veure\'n les variants (ø, ö, etc.)" + "Premeu la tecla Enrere ↶ per tancar el teclat en qualsevol moment" + "Accedeix a números i símbols" + "Manteniu premuda la paraula de l\'extrem esquerre per afegir-la al diccionari" + "Toqueu aquest suggeriment per continuar »" + "Toqueu aquí per tancar aquest suggeriment i començar a escriure." + "S\'obre el teclat cada vegada que toqueu un camp de text" + "Manteniu premuda una tecla per veure\'n les variants"\n"(ø, ö, ô, ó, etc.)" + "Toqueu aquesta tecla per canviar als números i als símbols" + "Torneu a tocar aquesta tecla per tornar a les lletres" + "Manteniu premuda aquesta tecla per canviar la configuració del teclat, com ara l\'emplenament automàtic" + "Proveu-ho!" + "Vés" + "Següent" + "Fet" + "Envia" + "?123" + "123" + "ABC" + "ALT" + "Entrada de veu" + "Actualment, l\'entrada de veu no és compatible amb el vostre idioma, però funciona en anglès." + "L\'entrada de veu és una funció experimental que utilitza el reconeixement de la parla en xarxa de Google." + "Per desactivar l\'entada de veu, aneu a la configuració del teclat." + "Per utilitzar l\'entrada de veu, premeu el botó del micròfon o feu lliscar el dit pel teclat en pantalla." + "Parleu ara" + "S\'està treballant" + + "Error. Torneu-ho a provar." + "No s\'ha pogut connectar" + "Error; s\'ha parlat massa." + "Problema d\'àudio" + "Error del servidor" + "No s\'escolten paraules" + "No hi ha resultats" + "Cerca per veu no instal·lada" + "Consell:"" Feu lliscar el dit pel teclat per parlar" + "Suggeriment:"" La propera vegada, proveu de dir la puntuació, com ara \"punt\", \"coma\" o \"interrogant\"." + "Cancel·la" + "D\'acord" + "Entrada de veu" + + "Al teclat principal" + "Al teclat de símbols" + "Desactivat" + + + "Micròfon al teclat principal" + "Micròfon al teclat de símbols" + "L\'entrada de veu està desactivada" + + "Enviament automàtic després de la veu" + "Prem automàticament Retorn en cercar o en anar al camp següent." + "Obrir el teclat"\n\n"Toqueu qualsevol camp de text." + "Tancar el teclat"\n\n"Premeu la tecla Enrere." + "Manteniu premuda una tecla per veure les opcions"\n\n"Accediu a la puntuació i als accents." + "Configuració del teclat"\n\n"Manteniu premuda la tecla ""?123""." + ".com" + ".net" + ".org" + ".gov" + ".edu" + "Selecciona el mètode d\'entrada" + "Idiomes d\'entrada" + "Feu lliscar el dit a la barra espaiadora per canviar l\'idioma" + "← Torna a tocar per desar" + "Diccionari disponible" + "Activa els comentaris de l\'usuari" + "Ajuda a millorar aquest editor de mètodes d\'entrada enviant automàticament estadístiques d\'ús i informes de bloqueigs a Google." + "Toca per corregir paraules" + "Toca les paraules introduïdes per corregir-les" + "Tema del teclat" + "teclat" + "veu" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ca/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ca/strings_kp2a.xml new file mode 100644 index 00000000..8747d275 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ca/strings_kp2a.xml @@ -0,0 +1,20 @@ + + + + Selecciona una altra entrada + Seleccioneu entrada + Cerca d\'entrada amb \"%1$s\" + Usuari + Contrasenya + Configuració de credencials d\'entrada + Emplenat automàtic activat + Emplenar automàticament en text quan un camp buit s\'introdueix, si una entrada Keepass2Android està disponible per al teclat i hi ha un valor que coincideix amb el text de pista del camp. + Recordar textos de pista de camp + Si un camp de text s\'omple manualment seleccionant el valor Keepass2Android, recordar quin valor va entrar al camp de text. El camp de text més tard és detectat pel seu text de pista. + Teclat senzill + Mostrar el teclat d\'1 línia si una pàgina està disponible per al teclat. Si està desactivat, es mostra un quadre de diàleg quan es prem la tecla Keepass2Android. + Bloquejar la base de dades quan s\'ha acabat + En prémer la tecla Fet/Enviar/Anar en el teclat d\'1 línia, automàticament bloca la base de dades. + Canviar teclat quan s\'ha acabat + En prémer la tecla Fet/Enviar/Anar en el teclat d\'1 línia, canviar el teclat. + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-cs/bools.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-cs/bools.xml new file mode 100644 index 00000000..897f4b3d --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-cs/bools.xml @@ -0,0 +1,22 @@ + + + + true + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-cs/donottranslate-altchars.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-cs/donottranslate-altchars.xml new file mode 100644 index 00000000..d91a0e44 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-cs/donottranslate-altchars.xml @@ -0,0 +1,34 @@ + + + + áàâãäåæ + 3éěèêë + íìîï8 + óòôõöœø9 + ůúùûü7 + š§ß + ňñ + čç + ýÿ6 + ď + ř4 + ť5 + ž + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-cs/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-cs/strings.xml new file mode 100644 index 00000000..615965fc --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-cs/strings.xml @@ -0,0 +1,140 @@ + + + + + "Klávesnice Keepass2Android" + "Nastavení klávesnice Keepass2Android" + "Možnosti zadávání textu a dat" + "Při stisku klávesy vibrovat" + "Zvuk při stisku klávesy" + "Zobrazit znaky při stisku klávesy" + "Opravovat překlepy" + "Povolit opravu chyb vstupu" + "Chyby vstupu v zobrazení na šířku" + "Povolit opravu chyb vstupu" + "Návrhy slov" + "Automaticky opravit předchozí slovo" + "Návrhy slov" + "Nastavení návrhů slov" + "Povolit automatické dokončování při psaní" + "Automatické dokončování" + "Zvětšit textové pole" + "Skrýt návrhy slov v zobrazení na šířku" + "Velká písmena automaticky" + "Zahájit větu velkým písmenem" + "Automatická interpunkce" + + "Rychlé opravy" + "Opravuje nejčastější chyby při psaní" + "Zobrazit návrhy" + "Zobrazovat navržená slova během psaní" + "Automatické dokončování" + "Stisknutím mezerníku nebo interpunkčního znaménka automaticky vložíte zvýrazněné slovo." + "Zobrazit klávesu Nastavení" + "Automaticky" + "Vždy zobrazovat" + "Vždy skrývat" + + + + "Návrh Bigram" + "Použít předchozí slovo ke zlepšení návrhu" + + "Žádný" + "Základní" + "Pokročilé" + + "%s: Uloženo" + "Podržením klávesy zobrazíte diakritiku (á, ž apod.)" + "Stisknutím klávesy Zpět ↶ můžete klávesnici kdykoli zavřít." + "Přístup k číslům a symbolům" + "Stisknutím a podržením slova zcela vlevo toto slovo přidáte do slovníku." + "Chcete-li pokračovat, dotkněte se tohoto tipu »" + "Chcete-li tento tip zavřít a začít psát, dotkněte se zde." + "Klávesnice se otevře vždy, když se dotknete textového pole." + "Přidržením klávesy zobrazíte diakritiku"\n"(ó, ø, ö, ô apod.)" + "Chcete-li přepnout na režim zadávání číslic a symbolů, dotkněte se této klávesy." + "Chcete-li přejít zpět k zadávání písmen, dotkněte se této klávesy znovu." + "Přidržením této klávesy změníte nastavení klávesnice (např. automatické dokončování)." + "Vyzkoušejte si to." + "Přejít" + "Další" + "Hotovo" + "Odeslat" + "?123" + "123" + "ABC" + "Alt" + "Hlasový vstup" + "Pro váš jazyk aktuálně není hlasový vstup podporován, ale funguje v angličtině." + "Hlasový vstup je experimentální funkce, která využívá síťové rozpoznávání řeči společnosti Google." + "Chcete-li vypnout hlasový vstup, přejděte do nastavení klávesnice." + "Chcete-li použít hlasový vstup, stiskněte tlačítko mikrofonu nebo přejeďte prstem přes klávesnici na obrazovce." + "Mluvte" + "Probíhá zpracování" + + "Chyba. Zkuste to prosím znovu." + "Připojení se nezdařilo." + "Chyba, řeč je příliš dlouhá." + "Problém se zvukem" + "Chyba serveru" + "Nebyla detekována žádná řeč." + "Nebyly nalezeny žádné shody" + "Hlasové vyhledávání není nainstalováno" + "Nápověda:"" Chcete-li aktivovat hlasový vstup, přejeďte prstem přes klávesnici." + "Nápověda:"" Příště zkuste vyslovit interpunkci, například „tečka“, „čárka“ nebo „otazník“." + "Zrušit" + "OK" + "Hlasový vstup" + + "Na hlavní klávesnici" + "Na klávesnici se symboly" + "Vypnout" + + + "Mikrofon na hlavní klávesnici" + "Mikrofon na klávesnici se symboly" + "Hlasový vstup je deaktivován" + + "Po hlasovém vstupu automaticky odeslat" + "Při vyhledávání nebo přechodu na další pole automaticky stisknout Enter." + "Otevřete klávesnici"\n\n"Dotkněte se libovolného textového pole." + "Zavřete klávesnici"\n\n"Stiskněte tlačítko Zpět." + "Přidržením klávesy zobrazte možnosti"\n\n"Přístup k interpunkčním znaménkům a diakritice." + "Nastavení klávesnice"\n\n"Dotkněte se klávesy ""?123"" a přidržte ji." + ".com" + ".cz" + ".org" + ".net" + ".eu" + "Výběr metody zadávání dat" + "Vstupní jazyky" + "Jazyk můžete změnit posunutím prstu po mezerníku." + "← Dalším dotykem slovo uložíte" + "K dispozici je slovník" + "Aktivovat zasílání statistik užívání a zpráv o selhání" + "Automatickým zasíláním statistik o užívání editoru zadávání dat a zpráv o jeho selhání do Googlu můžete přispět k vylepšení tohoto nástroje." + "Dotykem aktivovat opravy" + "Opravy napsaných slov dotykem" + "Motiv klávesnice" + "klávesnice" + "hlas" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-cs/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-cs/strings_kp2a.xml new file mode 100644 index 00000000..95b5ec40 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-cs/strings_kp2a.xml @@ -0,0 +1,20 @@ + + + + Vyberte další položku + Vybrat položku + Hledat položky s \"%1$s\" + Uživatel + Heslo + Nastavení vstupních metod pověření + Automatické vyplňování povoleno + Při vstupu do prázdného pole automaticky doplnit text, pokud je pro klávesnici dostupná položka v Keepass2Android a obsahuje hodnotu odpovídající nápovědě pro toto pole. + Pamatovat si nápovědy pole + Je-li pole ručně vyplněno výběrem položky z Keepass2Android, pamatovat si, která položka byla do pole zadána. Pole je později znovu rozpoznáno podle jeho nápovědy. + Jednoduchá klávesnice + Zobrazit jednoduchou jednořádkovou klávesnici, je-li položka k dispozici. Je-li klávesnice zakázána, dialogové okno se zobrazí při stisknutí klávesy Keepass2Android. + Uzamknout databázi po dokončení + Po stisknutí klávesy Hotovo/Odeslat/Dále na jednoduché jednořádkové klávesnici automaticky uzamknout databázi. + Přepnout klávesnice po dokončení + Po stisknutí klávesy Hotovo/Odeslat/Dále na jednoduché jednořádkové klávesnici přepnout klávesnici. + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-da/donottranslate-altchars.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-da/donottranslate-altchars.xml new file mode 100644 index 00000000..b1cc8b62 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-da/donottranslate-altchars.xml @@ -0,0 +1,38 @@ + + + + áàâąã + 3éèêëę€ + íìîï8 + óòôõ9 + úùûū7 + śšşß + ńñň + çćč + ýÿü6 + ðď + ř4 + ťþ5 + źžż + ł + w + ä + öœ + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-da/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-da/strings.xml new file mode 100644 index 00000000..25d4aa1e --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-da/strings.xml @@ -0,0 +1,140 @@ + + + + + "Keepass2Android-tastatur" + "Indstillinger for Keepass2Android-tastatur" + "Indstillinger for input" + "Vibration ved tastetryk" + "Lyd ved tastetryk" + "Popup ved tastetryk" + "Ret stavefejl" + "Aktiver fejlretning af input" + "Inputfejl i landskab" + "Aktiver fejlretning af input" + "Ordforslag" + "Ret automatisk det forrige ord" + "Ordforslag" + "Indstillinger for ordforslag" + "Aktiver automatisk udfyldelse, når du indtaster" + "Automatisk udfyldelse" + "Forøg tekstfeltets størrelse" + "Skjul ordforslag i landskabsvisning" + "Skriv aut. med stort" + "Første bogstav i en sætning skrives med stort" + "Foretag automatisk tegnsætning" + + "Hurtige løsninger" + "Retter almindelige stavefejl" + "Vis forslag" + "Vis ordforslag under indtastning" + "Udfyld automatisk" + "Mellemrumstast og tegnsætning indsætter automatisk fremhævet ord" + "Vis indstillingsnøgle" + "Automatisk" + "Vis altid" + "Skjul altid" + + + + "Bigram-forslag" + "Brug forrige ord for at forbedre forslag" + + "Ingen" + "Grundlæggende" + "Avanceret" + + "%s: Gemt" + "Hold en tast nede for at se accenter (ø, ö osv.)" + "Tryk på knappen Tilbage ↶ for når som helst at lukke for tastaturet" + "Få adgang til tal og symboler" + "Tryk og hold på ordet længst til venstre for at føje det til ordbogen" + "Berør dette tip for at fortsætte »" + "Berør her for at lukke dette tip og begynde at indtaste!" + "Tastaturet åbner når som helst, du berører et tekstfelt" + "Tryk på en tast, og hold den nede for a vise accenter"\n"(ø, ö, ô, ó osv.)" + "Skift til tal og symboler ved at røre denne tast" + "Gå tilbage til bogstaver ved at berøre denne tast igen" + "Tryk på denne tast, og hold den nede for at ændre tastaturindstillingerne, som f.eks. automatisk udfyldelse" + "Prøv det!" + "Gå" + "Næste" + "Udfør" + "Send" + "?123" + "123" + "ABC" + "ALT" + "Stemmeinput" + "Stemmeinput understøttes i øjeblikket ikke for dit sprog, men fungerer på engelsk." + "Stemme-input er en funktion på forsøgsbasis, som bruger Googles netværksstemmegenkendelse." + "Slå stemmeinput fra i indstillingerne for tastaturet." + "For at bruge stemme-input skal du trykke på knappen mikrofon eller lade glide fingeren hen over skærmtastaturet." + "Tal nu" + "Arbejder" + + "Fejl. Prøv igen." + "Kunne ikke oprette forbindelse" + "Fejl. For meget tale." + "Lydproblem" + "Serverfejl" + "Der høres ingen tale" + "Der blev ikke fundet nogen matches" + "Stemmesøgning er ikke installeret" + "Tip:"" Glid hen over tastaturet for at tale" + "Tip:"" Næste gang kan du forsøge at sige tegnsætning, f.eks. \"punktum\", \"komma\" eller \"spørgsmålstegn\"." + "Annuller" + "OK" + "Stemmeinput" + + "På hovedtastatur" + "På symboltastatur" + "Fra" + + + "Mikrofon på hovedtastatur" + "Mikrofon på symboltastatur" + "Stemmeinput er deaktiveret" + + "Send automatisk efter stemme" + "Tryk automatisk på enter, når du søger eller går til det næste felt." + "Åbn tastaturet"\n\n"Tryk på et hvilket som helst tekstfelt." + "Luk tastaturet"\n\n"Tryk på knappen Tilbage." + "Tryk på en tast, og hold den nede for valgmuligheder"\n\n"Få adgang til tegnsætning og accenter." + "Tastaturindstillinger"\n\n"Tryk på tasten ""?123"", og hold den nede." + ".com" + ".net" + ".org" + ".gov" + ".edu" + "Vælg inputmetode" + "Inputsprog" + "Træk fingeren på mellemrumstasten for at skifte sprog" + "← Tryk igen for at gemme" + "Ordbog er tilgængelig" + "Aktiver brugerfeedback" + "Vær med til at forbedre denne inputmetode ved at sende anvendelsesstatistikker og rapporter om nedbrud til Google." + "Tryk for at rette ord" + "Tryk på de indtastede ord for at rette dem" + "Tastaturtema" + "tastatur" + "stemme" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-da/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-da/strings_kp2a.xml new file mode 100644 index 00000000..1382d946 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-da/strings_kp2a.xml @@ -0,0 +1,20 @@ + + + + Vælg en anden post + Vælg post + Søg efter post med \"%1$s\" + Bruger + Adg.kode + Indstillinger for indtastning af login-oplysninger + Autoudfylding aktiveret + Udfyld automatisk tekst, når fokus går til et tomt felt, hvis en Keepass2Android-post er tilgængeig for tastaturet og der er en værdi, som svarer til feltets tiptekst. + Gem tiptekster for felter + Gem den værdi, som blev indtastet i feltet, hvis et tekstfelt bliver udfyldt ved manuelt at vælge Keepass2Android-værdien. Tekstfeltet bliver senere genkendt via dets tiptekst. + Enkeltrækketastatur + Vis det simple enkelt-række-tastatur, hvis en post er tilgængelig for tastaturet. Hvis dette er slået fra, vil en dialogboks blive vist, når der trykkes på Keepass2Android-tasten. + Lås databasen, når du er færdig + Lås automatisk databasen, når tasten Udfør/Send/Gå trykkes på det simple enkeltrækketastatur. + Skift tastatur når du er færdig + Skift tastatur, når du trykker på tasten Udfør/Send/Gå på enkeltrækketastaturet. + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-de/bools.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-de/bools.xml new file mode 100644 index 00000000..897f4b3d --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-de/bools.xml @@ -0,0 +1,22 @@ + + + + true + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-de/donottranslate-altchars.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-de/donottranslate-altchars.xml new file mode 100644 index 00000000..df27bce2 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-de/donottranslate-altchars.xml @@ -0,0 +1,31 @@ + + + + ä + 3èéêë + ìíîï8 + ö9 + ùúûü7 + §ß + ñ + ç + ýÿ + 6 + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-de/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-de/strings.xml new file mode 100644 index 00000000..124e58d8 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-de/strings.xml @@ -0,0 +1,140 @@ + + + + + "Keepass2Android-Tastatur" + "Keepass2Android-Tastatureinstellungen" + "Eingabeoptionen" + "Vibrieren b. Tastendruck" + "Ton bei Tastendruck" + "Pop-up bei Tastendruck" + "Eingabefehler korrigieren" + "Korrektur von Eingabefehlern aktivieren" + "Eingabefehler im Querformat" + "Korrektur von Eingabefehlern aktivieren" + "Wortvorschläge" + "Vorheriges Wort automatisch korrigieren" + "Wortvorschläge" + "Einstellungen für Wortvorschläge" + "Automatische Vervollständigung während der Eingabe aktivieren" + "Autom. vervollständigen" + "Textfeld vergrößern" + "Wortvorschläge in Querformat ausblenden" + "Autom. Groß-/Kleinschr." + "Sätze mit Großbuchstaben beginnen" + "Autom. Zeichensetzung" + + "Quick Fixes" + "Korrigiert gängige Tippfehler" + "Vorschläge anzeigen" + "Vorgeschlagene Wörter während des Tippens anzeigen" + "Autom. vervollständigen" + "Leertaste und Interpunktion fügen autom. ein markiertes Wort ein" + "Einstellungstaste anz." + "Automatisch" + "Immer anzeigen" + "Immer ausblenden" + + + + "Bigramm-Vorschläge" + "Zur Verbesserung des Vorschlags vorheriges Wort verwenden" + + "Kein" + "Standard" + "Erweitert" + + "%s: gespeichert" + "Zur Anzeige von Umlauten (ä, ö usw.) Taste gedrückt halten" + "Zum Schließen der Tastatur ↶ drücken" + "Auf Zahlen und Symbole zugreifen" + "Lange auf das Wort ganz links außen drücken, um es zum Wörterbuch hinzuzufügen" + "Diesen Hinweis berühren, um fortzufahren »" + "Hier berühren, um diesen Hinweis zu schließen und mit dem Tippen zu beginnen!" + "Die Tastatur wird immer dann geöffnet, wenn Sie ein Textfeld berühren." + "Halten Sie eine Taste gedrückt, um Akzente anzuzeigen"\n"(ø, ö, ô, ó usw.)." + "Wechseln Sie zu Ziffern und Symbolen, indem Sie diese Taste berühren." + "Durch erneutes Drücken dieser Taste gelangen Sie zurück zu den Buchstaben." + "Halten Sie diese Taste gedrückt, um die Tastatureinstellungen, wie beispielsweise die automatische Vervollständigung, zu ändern." + "Probieren Sie es aus!" + "Los" + "Weiter" + "Fertig" + "Senden" + "?123" + "123" + "ABC" + "ALT" + "Spracheingabe" + "Spracheingaben werden derzeit nicht für Ihre Sprache unterstützt, funktionieren jedoch in Englisch." + "Die Spracheingabe ist eine Funktion im Versuchsstadium, die die vernetzte Spracherkennung von Google verwendet." + "Wenn Sie die Spracheingabe deaktivieren möchten, rufen Sie die Tastatureinstellungen auf." + "Um die Spracheingabe zu verwenden, drücken Sie die Mikrofontaste oder ziehen Sie Ihren Finger über die Bildschirmtastatur." + "Jetzt sprechen" + "Vorgang läuft" + + "Fehler. Versuchen Sie es erneut.." + "Keine Verbindung" + "Fehler – Text zu lang" + "Audio-Problem" + "Serverfehler" + "Keine Sprache zu hören" + "Keine Treffer gefunden" + "Sprachsuche nicht installiert" + "Hinweis:"" Ziehen Sie zum Sprechen den Finger über die Tastatur." + "Hinweis:"" Versuchen Sie beim nächsten Mal, Satzzeichen wie \"Punkt\", \"Komma\" oder \"Fragezeichen\" per Sprachbefehl einzugeben." + "Abbrechen" + "OK" + "Spracheingabe" + + "Auf Haupttastatur" + "Auf Symboltastatur" + "Aus" + + + "Mikrofon auf Haupttastatur" + "Mikrofon auf Symboltastatur" + "Spracheingabe ist deaktiviert" + + "Nach Sprachaufnahme automatisch senden" + "Drücken Sie auf die Eingabetaste, wenn Sie einen Suchvorgang durchführen oder zum nächsten Feld wechseln." + "Tastatur öffnen"\n\n"Berühren Sie ein beliebiges Textfeld." + "Tastatur schließen"\n\n"Drücken Sie die Zurücktaste." + "Für Optionen eine Taste 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" + "Eingabemethode auswählen" + "Eingabesprachen" + "Finger über die Leertaste bewegen, um die Eingabesprache zu wechseln" + "← Zum Speichern erneut berühren" + "Wörterbuch verfügbar" + "Nutzer-Feedback aktivieren" + "Tragen Sie zur Verbesserung dieses Eingabemethodeneditors bei, indem Sie automatisch Nutzungsstatistiken und Absturzberichte an Google senden." + "Wortkorrektur" + "Zum Korrigieren auf eingegebene Wörter tippen" + "Tastaturdesign" + "Tastatur" + "Sprache" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-de/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-de/strings_kp2a.xml new file mode 100644 index 00000000..2b0f0f58 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-de/strings_kp2a.xml @@ -0,0 +1,20 @@ + + + + Anderen Eintrag wählen + Eintrag wählen + Suche Eintrag mit \"%1$s\" + Benutzer + Passwort + Zugangsdaten-Eingabe-Einstellungen + Auto-Ausfüllen aktiviert + Wenn auf ein leeres Feld gedrückt wird, dieses automatisch ausfüllen falls ein Keepass2Android Eintrag verfügbar ist und ein Wert existiert, der dem Hinweistext im Feld entspricht. + Hinweistexte der Felder merken + Wenn ein Textfeld ausgefüllt wird, indem manuell ein Keepass2Android-Wert ausgewählt wird: Merken, welcher Wert ins Textfeld eingetragen wurde. Das Textfeld wird dann später an seinem Hinweistext wiedererkannt. + Einfache Tastatur + Zeige die einfache einzeilige Tastatur an, wenn ein Eintrag für die Tastatur verfügbar ist. Wenn deaktiviert, wird ein Dialog angezeigt, wenn die Keepass2Android-Taste gedrückt wird. + Datenbank sperren wenn fertig + Wenn die Fertig/Senden/Los-Taste auf der einfachen einzeiligen Tastatur gedrückt wird: Datenbank automatisch sperren. + Tastatur wechseln wenn fertig + Wenn die Fertig/Senden/Los-Taste auf der einfachen einzeiligen Tastatur gedrückt wird: Zu einer anderen Tastatur wechseln. + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-el/donottranslate-altchars.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-el/donottranslate-altchars.xml new file mode 100644 index 00000000..d3beafad --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-el/donottranslate-altchars.xml @@ -0,0 +1,30 @@ + + + + àáâãäåæ + 3èéêë + ìíîï8 + òóôõöœø9 + ùúûü7 + §ß + ñ + ç + ýÿ6 + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-el/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-el/strings.xml new file mode 100644 index 00000000..c406b7be --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-el/strings.xml @@ -0,0 +1,140 @@ + + + + + "Πληκτρολόγιο Keepass2Android" + "Ρυθμίσεις πληκτρολογίου Keepass2Android" + "Επιλογές εισόδου" + "Δόνηση κατά το πάτημα πλήκτρων" + "Ήχος κατά το πάτημα πλήκτρων" + "Εμφάνιση με το πάτημα πλήκτρου" + "Διόρθωση σφαλμάτων πληκτρολόγησης" + "Ενεργοποίηση διόρθωσης σφαλμάτων εισόδου" + "Σφάλματα οριζόντιας εισαγωγής" + "Ενεργοποίηση διόρθωσης σφαλμάτων εισόδου" + "Υποδείξεις λέξεων" + "Αυτόματη διόρθωση της προηγούμενης λέξης" + "Υποδείξεις λέξεων" + "Ρυθμίσεις υποδείξεων λέξεων" + "Ενεργοποίηση αυτόματης συμπλήρωσης κατά την πληκτρολόγηση" + "Αυτόματη συμπλήρωση" + "Αυξήστε το μέγεθος του πεδίου κειμένου" + "Απόκρυψη υποδείξεων λέξεων στην οριζόντια προβολή" + "Αυτόματη χρήση κεφαλαίων" + "Κεφαλαίο το πρώτο γράμμα της πρότασης" + "Αυτόματος τονισμός" + + "Γρήγορες διορθώσεις" + "Διορθώνει συνηθισμένα λάθη πληκτρολόγησης" + "Εμφάνιση υποδείξεων" + "Προβολή προτεινόμενων λέξεων κατά την πληκτρολόγηση" + "Αυτόματη συμπλήρωση" + "Τα πλήκ.διαστήμ.και τονισμού εισάγ.αυτόμ.την επιλ.λέξη" + "Εμφάνιση πλήκτρου ρυθμίσεων" + "Αυτόματο" + "Να εμφανίζεται πάντα" + "Πάντα απόκρυψη" + + + + "Προτάσεις bigram" + "Χρήση προηγούμενης λέξης για τη βελτίωση πρότασης" + + "Καμία" + "Βασική" + "Σύνθετη" + + "%s : Αποθηκεύτηκε" + "Κρατήστε πατημένο ένα πλήκτρο για να δείτε τους τονισμένους χαρακτήρες (ø, ö, κ.τ.λ.)" + "Πατήστε το πλήκτρο Πίσω ↶ για να κλείσετε το πληκτρολόγιο ανά πάσα στιγμή" + "Πρόσβαση σε αριθμούς και σύμβολα" + "Κρατήστε πατημένη τη λέξη στην άκρη αριστερά, για να την προσθέσετε στο λεξικό" + "Αγγίξτε αυτή τη συμβουλή για να συνεχίσετε »" + "Αγγίξτε εδώ για να κλείσετε τη συμβουλή και να ξεκινήσετε την πληκτρολόγηση!" + "Το πληκτρολόγιο ανοίγει κάθε φορά που αγγίζετε ένα πεδίο κειμένου" + "Αγγίξτε και κρατήστε κάποιο πλήκτρο για να προβάλετε τους τονισμένους χαρακτήρες"\n"(ø, ö, ô, ó κ.τ.λ.)" + "Αλλαγή σε αριθμούς και σύμβολα με το πάτημα αυτού του πλήκτρου" + "Επιστρέψτε στα γράμματα αγγίζοντας ξανά αυτό το πλήκτρο" + "Αγγίξτε και κρατήστε πατημένο αυτό το πληκτρολόγιο για να αλλάξετε τις ρυθμίσεις πληκτρολογίου, όπως η αυτόματη συμπλήρωση" + "Δοκιμάστε το!" + "Μετ." + "Επόμενο" + "Τέλος" + "Αποστολή" + "?123" + "123" + "ΑΒΓ" + "ALT" + "Φωνητική είσοδος" + "Η φωνητική είσοδος δεν υποστηρίζεται αυτή τη στιγμή για τη γλώσσα σας, ωστόσο λειτουργεί στα Αγγλικά." + "Οι φωνητικές εντολές είναι μια πειραματική λειτουργία, η οποία χρησιμοποιεί τη δικτυακή αναγνώριση ομιλίας της Google." + "Για να απενεργοποιήσετε τη φωνητική είσοδο, μεταβείτε στις ρυθμίσεις πληκτρολογίου." + "Για να χρησιμοποιήσετε τις φωνητικές εντολές, πιέστε το κουμπί μικροφώνου ή σύρετε το δάχτυλό σας κατά μήκος του πληκτρολογίου της οθόνης." + "Μιλήστε τώρα" + "Σε λειτουργία" + + "Σφάλμα. Δοκιμάστε ξανά." + "Δεν ήταν δυνατή η σύνδεση" + "Σφάλμα, πολλές λέξεις." + "Πρόβλημα ήχου" + "Σφάλμα διακομιστή" + "Δεν ακούγεται ομιλία" + "Δεν βρέθηκε καμία αντιστοίχιση" + "Η Φωνητική αναζήτηση δεν εγκαταστάθηκε" + "Υπόδειξη:"" Σύρετε κατά μήκος του πληκτρολογίου για να μιλήσετε" + "Υπόδειξη:"" Την επόμενη φορά, προσπαθήστε να προφέρετε σημεία στίξης, όπως \"τελεία\", \"κόμμα\" ή \"ερωτηματικό\"." + "Ακύρωση" + "ΟΚ" + "Φωνητική είσοδος" + + "Στο κύριο πληκτρολόγιο" + "Πληκτρολόγιο συμβόλων ενεργοποίησης" + "Απενεργοποίηση" + + + "Μικρόφωνο στο κύριο πληκτρολόγιο" + "Μικρόφωνο στο πληκτρολόγιο συμβόλων" + "Η φωνητική είσοδος είναι απενεργοποιημένη" + + "Αυτόματη υποβολή μετά από ήχο" + "Πατήστε enter αυτόματα κατά την αναζήτηση ή τη μετάβαση στο επόμενο πεδίο." + "Ανοίξτε το πληκτρολόγιο"\n\n"Αγγίξτε οποιοδήποτε πεδίο κειμένου." + "Κλείστε το πληκτρολόγιο"\n\n"Πατήστε το πλήκτρο Πίσω." + "Αγγίξτε και κρατήστε ένα πλήκτρο για ορισμό επιλογών"\n\n"Πρόσβαση στα σημεία στίξης και τονισμού." + "Ρυθμίσεις πληκτρολογίου"\n\n"Αγγίξτε και κρατήστε το πλήκτρο ""?123""." + ".com" + ".net" + ".org" + ".gov" + ".edu" + "Επιλογή μεθόδου εισόδου" + "Γλώσσες εισόδου" + "Σύρετε το δάχτυλο στο πλήκτρο διαστήματος για να αλλάξετε γλώσσα" + "← Αγγίξτε ξανά για αποθήκευση" + "Λεξικό διαθέσιμο" + "Ενεργοποίηση σχολίων χρηστών" + "Βοηθήστε μας να βελτιώσουμε αυτό το πρόγραμμα επεξεργασίας μεθόδου εισόδου στέλνοντας αυτόματα στατιστικά στοιχεία και αναφορές σφαλμάτων στην Google." + "Αγγίξτε για διόρθωση λέξεων" + "Αγγίξτε τις λέξεις που εισάγετε για να τις διορθώσετε" + "Θέμα πληκτρολογίου" + "πληκτρολόγιο" + "φωνητική" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-el/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-el/strings_kp2a.xml new file mode 100644 index 00000000..f428f208 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-el/strings_kp2a.xml @@ -0,0 +1,10 @@ + + + + Επιλέξτε μια άλλη εγγραφή + Επιλέξτε καταχώρηση + Αναζήτηση για καταχώρηση με \"%1$s\" + Χρήστης + Κωδικός Πρόσβασης + Απλό πληκτρολόγιο + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-en-rGB/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-en-rGB/strings.xml new file mode 100644 index 00000000..fdfefe69 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-en-rGB/strings.xml @@ -0,0 +1,140 @@ + + + + + "Keepass2Android keyboard" + "Keepass2Android keyboard settings" + "Input options" + "Vibrate on key-press" + "Sound on key-press" + "Pop-up on key press" + "Correct typing errors" + "Enable input error correction" + "Landscape input errors" + "Enable input error correction" + "Word suggestions" + "Automatically correct the previous word" + "Word suggestions" + "Word suggestion settings" + "Enable auto-completion while typing" + "Auto-completion" + "Increase text field size" + "Hide word suggestions in landscape view" + "Auto-capitalisation" + "Capitalise the start of a sentence" + "Auto-punctuate" + + "Quick fixes" + "Corrects commonly typed mistakes" + "Show suggestions" + "Display suggested words while typing" + "Auto-complete" + "Spacebar and punctuation automatically insert highlighted word" + "Show settings key" + "Automatic" + "Always show" + "Always hide" + + + + "Bigram Suggestions" + "Use previous word to improve suggestion" + + "None" + "Basic" + "Advanced" + + "%s : Saved" + "Hold a key down to see accents (ø, ö, etc.)" + "Press the back key ↶ to close the keyboard at any point" + "Access numbers and symbols" + "press and hold the left-most word to add it to the dictionary" + "Touch this hint to continue »" + "Touch here to close this hint and start typing!" + "The keyboard opens any time you touch a text field" + "Touch & hold a key to view accents"\n"(ø, ö, ô, ó and so on)" + "Switch to numbers and symbols by touching this key" + "Go back to letters by touching this key again" + "Touch & hold this key to change keyboard settings, like auto-complete" + "Try it!" + "Go" + "Next" + "Done" + "Send" + "?123" + "123" + "ABC" + "ALT" + "Voice input" + "Voice input is not currently supported for your language, but does work in English." + "Voice input is an experimental feature using Google\'s networked speech recognition." + "To turn off voice input, go to keyboard settings." + "To use voice input, press the microphone button or slide your finger across the on-screen keyboard." + "Speak now" + "Working" + + "Error: Please try again." + "Couldn\'t connect" + "Error, too much speech." + "Audio problem" + "Server error" + "No speech heard" + "No matches found" + "Voice search not installed" + "Hint:"" Swipe across keyboard to speak" + "Hint:"" Next time, try speaking punctuation marks, like \"full stop\", \"comma\" or \"question mark\"." + "Cancel" + "OK" + "Voice input" + + "On main keyboard" + "On symbols keyboard" + "Off" + + + "Mic on main keyboard" + "Mic on symbols keyboard" + "Voice input is disabled" + + "Auto-submit after voice" + "Automatically press enter when searching or going to the next field." + "Open the keyboard"\n\n"Touch any text field." + "Close the keyboard"\n\n"Press the Back key." + "Touch & hold a key for options"\n\n"Access punctuation and accents." + "Keyboard settings"\n\n"Touch & hold the ""?123"" key." + ".com" + ".net" + ".org" + ".gov" + ".edu" + "Select input method" + "Input languages" + "Slide finger on spacebar to change language" + "← Touch again to save" + "Dictionary available" + "Enable user feedback" + "Help improve this input method editor by sending usage statistics and crash reports automatically to Google." + "Touch to correct words" + "Touch words entered to correct them" + "Keyboard Theme" + "keyboard" + "voice" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-en/bools.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-en/bools.xml new file mode 100644 index 00000000..897f4b3d --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-en/bools.xml @@ -0,0 +1,22 @@ + + + + true + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-en/donottranslate-altchars.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-en/donottranslate-altchars.xml new file mode 100644 index 00000000..083befa1 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-en/donottranslate-altchars.xml @@ -0,0 +1,27 @@ + + + + àáâãäåāæ + 3èéêëē + ìíîïī8 + òóôõöōœø9 + ùúûüū7 + ýÿ6 + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-es-rUS/donottranslate-altchars.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-es-rUS/donottranslate-altchars.xml new file mode 100644 index 00000000..d3beafad --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-es-rUS/donottranslate-altchars.xml @@ -0,0 +1,30 @@ + + + + àáâãäåæ + 3èéêë + ìíîï8 + òóôõöœø9 + ùúûü7 + §ß + ñ + ç + ýÿ6 + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-es-rUS/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-es-rUS/strings.xml new file mode 100644 index 00000000..8a90f255 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-es-rUS/strings.xml @@ -0,0 +1,140 @@ + + + + + "Teclado de Keepass2Android" + "Configuración de teclado de Keepass2Android" + "Opciones de entrada" + "Vibrar al pulsar teclas" + "Sonar al pulsar las teclas" + "Aviso emergente al pulsar tecla" + "Corregir errores de escritura" + "Habilitar corrección de error de entrada" + "Errores de entrada apaisada" + "Habilitar corrección de error de entrada" + "Sugerencias de palabras" + "Corregir automáticamente la palabra anterior" + "Sugerencias de palabras" + "Configuración de sugerencia de palabra" + "Habilitar finalización automática al escribir" + "Finalización automática" + "Aumentar el tamaño del campo de texto" + "Ocultar sugerencias de palabras en vista apaisada" + "Mayúsculas automáticas" + "Poner en mayúscula el inicio de una oración" + "Puntuación automática" + + "Arreglos rápidos" + "Corrige errores de escritura comunes" + "Mostrar sugerencias" + "Mostrar palabras sugeridas mientras escribe" + "Completar automát." + "La barra espaciadora o la puntuación insertan automáticamente la palabra resaltada." + "Mostrar tecla de configuración" + "Automático" + "Mostrar siempre" + "Ocultar siempre" + + + + "Sugerencias de Vigoran" + "Utiliza la palabra anterior para mejorar la sugerencia" + + "Ninguno" + "Básico" + "Avanzado" + + "%s: guardada" + "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" + "Presiona y mantén presionada la palabra de la izquierda para agregarla al diccionario" + "Toca esta sugerencia para continuar »" + "Toca aquí para cerrar esta sugerencia y comenzar a escribir." + "El teclado se abre cada vez que tocas un campo de texto." + "Toca y mantén presionada una tecla para ver los acentos"\n"(ø, ö, ô, ó, y así sucesivamente)." + "Cambia de números a símbolos tocando esta tecla." + "Vuelve a letras tocando esta tecla nuevamente." + "Toca y mantén presionada esta tecla para cambiar la configuración del teclado, como completar automáticamente." + "¡Pruébalo!" + "Ir" + "Siguiente" + "Hecho" + "Enviar" + "?123" + "123" + "ABC" + "ALT" + "Entrada por voz" + "La entrada por voz no está admitida en tu idioma, pero sí funciona en inglés." + "La entrada por voz es una característica experimental que utiliza la red de reconocimiento de voz de Google." + "Para desactivar la entrada por voz, ve a configuración del teclado." + "Para realizar entrada por voz, presiona el botón del micrófono o desliza tus dedos por el teclado en pantalla." + "Habla ahora" + "Procesando" + + "Error. Vuelve a intentarlo." + "No se pudo establecer la conexión." + "Error, demasiado discurso." + "Problema de audio" + "Error del servidor" + "No se oyó la voz" + "No se encontraron coincidencias" + "Búsqueda por voz no instalada" + "Sugerencia:"" Deslizar en el teclado para hablar" + "Sugerencia:"" La próxima vez intenta decir la puntuación como \"punto\", \"coma\" o \"signo de pregunta\"." + "Cancelar" + "Aceptar" + "Entrada por voz" + + "En el teclado principal" + "En el teclado de símbolos" + "Apagado" + + + "Micrófono en el teclado principal" + "Micrófono en el teclado de símbolos" + "La entrada por voz está inhabilitada." + + "Enviar automáticamente después del audio" + "Presionar automáticamente Ingresar al buscar o ir al campo siguiente." + "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" + "Seleccionar método de entrada" + "Idiomas de entrada" + "Deslizarse manualmente por la barra espaciadora para cambiar el idioma" + "← Tocar de nuevo para guardar" + "Diccionario disponible" + "Habilitar los comentarios del usuario" + "Ayuda a mejorar este editor de método de introducción de texto al enviar las estadísticas de uso y los informes de error a Google." + "Tocar para corregir palabras" + "Toca las palabras ingresadas que desees corregir" + "Tema del teclado" + "Teclado" + "Voz" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-es/bools.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-es/bools.xml new file mode 100644 index 00000000..897f4b3d --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-es/bools.xml @@ -0,0 +1,22 @@ + + + + true + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-es/donottranslate-altchars.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-es/donottranslate-altchars.xml new file mode 100644 index 00000000..721062d2 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-es/donottranslate-altchars.xml @@ -0,0 +1,30 @@ + + + + á + + ìíîï8 + ó9 + ùúûü7 + §ß + ñ + ç + ýÿ6 + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-es/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-es/strings.xml new file mode 100644 index 00000000..60e574e1 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-es/strings.xml @@ -0,0 +1,140 @@ + + + + + "Teclado de Keepass2Android" + "Ajustes del teclado de Keepass2Android" + "Opciones introducción texto" + "Vibrar al pulsar tecla" + "Sonido al pulsar tecla" + "Popup al pulsar tecla" + "Corregir errores de escritura" + "Habilitar la introducción de corrección de errores" + "Errores de introducción de datos en vista horizontal" + "Habilitar la introducción de corrección de errores" + "Sugerencias de palabras" + "Corregir automáticamente la palabra anterior" + "Sugerencias de palabras" + "Ajustes de sugerencia de palabras" + "Habilitar Autocompletar al escribir" + "Autocompletar" + "Aumentar el tamaño del campo de texto" + "Ocultar sugerencias de palabras en la vista horizontal" + "Mayúsculas automáticas" + "Escribir en mayúscula el principio de la frase" + "Puntuación automática" + + "Correcciones rápidas" + "Corrige los errores tipográficos que se cometen con más frecuencia." + "Mostrar sugerencias" + "Muestra las palabras sugeridas mientras se escribe." + "Autocompletar" + "La barra espaciadora y los signos de puntuación insertan automáticamente la palabra resaltada." + "Mostrar tecla de ajustes" + "Automáticamente" + "Mostrar siempre" + "Ocultar siempre" + + + + "Sugerencias de bigramas" + "Usar palabra anterior para mejorar sugerencias" + + "Ninguno" + "Básico" + "Avanzado" + + "%s: guardada" + "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" + "Mantén pulsada la palabra situada más a la izquierda para añadirla al diccionario." + "Toca esta sugerencia para continuar »" + "Toca aquí para cerrar la sugerencia y comenzar a escribir." + "El teclado se abre cada vez que tocas un campo de texto""." + "Mantén pulsada una tecla para ver los caracteres acentuados"\n"(ø, ö, ô, ó, etc.)." + "Cambiar a números y a símbolos tocando esta tecla" + "Volver a las letras tocando esta tecla de nuevo" + "Mantén pulsada esta tecla para cambiar la configuración de teclado a, por ejemplo, autocompletar""." + "¡Pruébalo!" + "Ir" + "Sig." + "Listo" + "Enviar" + "?123" + "123" + "ABC" + "ALT" + "Introducción de voz" + "Actualmente la introducción de voz no está disponible en tu idioma, pero se puede utilizar en inglés." + "La introducción de voz es una función en fase experimental que utiliza la tecnología de reconocimiento de voz en red de Google." + "Para desactivar la función de introducción de voz, accede a la configuración del teclado." + "Para utilizar la función de introducción de voz, pulsa el botón de micrófono o desliza el dedo por el teclado en pantalla." + "Habla ahora" + "En curso" + + "Se ha producido un error. Inténtalo de nuevo." + "No se ha podido establecer conexión." + "Se ha producido un error debido a un exceso de introducción de datos de voz." + "Problema de audio" + "Error del servidor" + "Ninguna conversación escuchada" + "No se ha encontrado ninguna coincidencia." + "La búsqueda por voz no está instalada." + "Sugerencia:"" muévete por el teclado para hablar." + "Sugerencia:"" la próxima vez, prueba a indicar signos de puntuación como, por ejemplo, \"punto\", \"coma\" o \"signo de interrogación\"." + "Cancelar" + "Aceptar" + "Introducción de voz" + + "En teclado principal" + "En teclado de símbolos" + "Desactivado" + + + "Micrófono en teclado principal" + "Micrófono en teclado de símbolos" + "La función de introducción de voz no está habilitada." + + "Enviar automáticamente después de la introducción de voz" + "Pulsar Intro automáticamente al buscar o al pasar al siguiente campo" + "Abrir el teclado"\n\n"Toca cualquier campo de texto." + "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." + "Ajustes del teclado"\n\n"Mantén pulsada la tecla ""?123""." + ".com" + ".net" + ".org" + ".gov" + ".edu" + "Seleccionar método de introducción de texto" + "Idiomas" + "Deslizar el dedo por la barra espaciadora para cambiar el idioma" + "← Volver a tocar para guardar" + "Hay un diccionario disponible." + "Habilitar comentarios de usuarios" + "Ayuda a mejorar este editor de método de introducción de texto enviando estadísticas de uso e informes de error a Google." + "Tocar para corregir palabras" + "Tocar palabras introducidas para corregirlas" + "Tema de teclado" + "teclado" + "voz" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-es/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-es/strings_kp2a.xml new file mode 100644 index 00000000..0cfc171d --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-es/strings_kp2a.xml @@ -0,0 +1,20 @@ + + + + Seleccione otra entrada + Seleccione una entrada + Buscar entrada con \"%1$s\" + Usuario + Contraseña + Configuración de credenciales + Auto completado habilitado + Completar automáticamente el campo vacío actual, si hay disponible una entrada de Keepass2Android para el teclado y hay un valor que coincide con el texto de indicio del campo. + Recordar textos de ayuda + Si un campo de texto se llena seleccionando manualmente el valor de Keepass2Android, recordar qué valor ha sido elegido para este campo. El campo de texto se vuelve a detectar en el futuro por el texto de ayuda. + Teclado simple + Mostrar el teclado simple de una fila si hay una entrada disponible para el teclado. Si está deshabilitado, se muestra un diálogo cuando se presiona la tecla Keepass2Android. + Bloquear base de datos al finalizar + Bloquea automáticamente la base de datos al presionar Hecho/Enviar/Adelante en el teclado simple de una fila. + Cambiar de teclado al finalizar + Cambiar de teclado al presionar Hecho/Enviar/Adelante en el teclado simple de una fila. + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-fa/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-fa/strings.xml new file mode 100644 index 00000000..2dca196b --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-fa/strings.xml @@ -0,0 +1,140 @@ + + + + + "صفحه کلید Keepass2Android" + "تنظیمات صفحه کلید Keepass2Android" + "گزینه های ورودی" + "لرزش با فشار کلید" + "صدا با فشار کلید" + "بازشو با فشار کلید" + "تصحیح خطاهای تایپی" + "فعال کردن تصحیح خطای ورودی" + "خطاهای ورود افقی" + "فعال کردن تصحیح خطای ورودی" + "پیشنهادات کلمه" + "تصحیح خودکار کلمه قبلی" + "پیشنهادات کلمه" + "تنظیمات پیشنهاد کلمه" + "فعال کردن تکمیل خودکار در حین تایپ" + "تکمیل خودکار" + "افزایش اندازه قسمت متنی" + "پنهان کردن پیشنهادات کلمه در نمای افقی" + "نوشتن با حروف بزرگ خودکار" + "بزرگ کردن اول هر جمله" + "نشان گذاری خودکار" + + "راه حل های سریع" + "تصحیح خطاهای تایپی رایج" + "نمایش پیشنهادات" + "نمایش واژه های پیشنهادی در حین تایپ" + "تکمیل خودکار" + "کلید خط فاصله و علائم نگارشی به صورت خودکار کلمه برجسته شده را وارد می کنند." + "نمایش کلید تنظیمات" + "خودکار" + "همیشه نمایش" + "همیشه پنهان" + + + + "توضیحات بیگرام" + "برای بهبود پیشنهاد از کلمه قبلی استفاده شود" + + "هیچکدام" + "پایه" + "پیشرفته" + + "%s : ذخیره شد" + "برای مشاهده علائم تکیه (ø، ö و موارد دیگر) کلیدی را پایین نگه دارید" + "برای بستن صفحه کلید در هر نقطه که بخواهید، کلید برگشت ↶ را فشار دهید" + "دسترسی به اعداد و نمادها" + "انتهای سمت چپ واژه را برای افزودن آن به فرهنگ لغت فشار داده و نگه دارید" + "این نکته را برای ادامه لمس کنید »" + "برای بستن این نکته و شروع تایپ، اینجا را لمس کنید!" + "هر زمان که قسمت متنی را لمس می کنید، صفحه کلید باز می شود" + "یک کلید را برای مشاهده تکیه های صدا لمس کرده و نگه دارید (ø، ö، ô، ó و موارد دیگر)"\n + "تغییر شماره ها و نمادها با لمس این کلید" + "با لمس مجدد این کلید، به حروف برگردید" + "این کلید را برای تغییر تنظیمات صفحه کلید مانند تکمیل خودکار لمس کرده و فشار دهید" + "امتحان کنید!" + "برو" + "بعدی" + "انجام شد" + "ارسال" + "?123" + "123" + "ABC" + "ALT" + "ورودی صوتی" + "ورودی صوتی در حال حاضر برای زبان شما پشتیبانی نمی شود اما برای زبان انگلیسی فعال است." + "ورودی صوتی یک ویژگی آزمایشی با استفاده از تشخیص گفتار شبکه Google است." + "برای خاموش کردن ورودی صدا، به تنظیمات صفحه کلید بروید." + "برای استفاده از ورودی صوتی، دکمه میکروفن را فشار دهید یا انگشت خود را روی صفحه کلید روی صفحه حرکت دهید." + "اکنون صحبت کنید" + "در حال کار" + + "خطا: لطفاً دوباره امتحان کنید." + "متصل نشد" + "خطا، گفتار بسیار زیاد است." + "مشکل صوتی" + "خطای سرور" + "گفتاری شنیده نشد" + "مورد منطبقی یافت نشد" + "جستجوی صوتی نصب نشده است" + "نکته: "" برای صحبت روی صفحه کلید ضربه بزنید" + "نکته: دفعه دیگر، از نشانه گذاری های گفتاری مانند \"نقطه\"، \"کاما\" یا \"علامت سؤال\" استفاده کنید." + "لغو" + "تأیید" + "ورودی صوتی" + + "در صفحه کلید اصلی" + "در صفحه کلید نمادها" + "خاموش" + + + "میکروفن در صفحه کلید اصلی" + "میکروفن در صفحه کلید نمادها" + "ورودی صوتی غیر فعال شده است" + + "ارائه خودکار بعد از صدا" + "هنگام جستجو یا رفتن به قسمت بعدی، Enter را به صورت خودکار فشار دهید." + "صفحه کلید را باز کنید"\n\n"هر قسمت متنی را لمس کنید." + "بستن صفحه کلید"\n\n"کلید برگشت را فشار دهید." + "یک کلید را برای گزینه های"\n\n" دسترسی به علائم نگارشی و تکیه های صدا لمس کرده و نگه دارید." + "تنظیمات صفحه کلید"\n\n"کلید ""?123"" را لمس کرده و نگهدارید." + ".com" + ".net" + ".org" + ".gov" + ".edu" + "انتخاب روش ورودی" + "زبان های ورودی" + "برای تغییر زبان انگشت را روی کلید فاصله بلغزانید" + "← جهت ذخیره دوباره لمس کنید" + "دیکشنری موجود است" + "فعال کردن بازخورد کاربر" + "با ارسال خودکار آمارهای کاربرد و گزارش های خرابی به Google، به بهبود این ویرایشگر روش ورودی کمک کنید." + "برای تصحیح کلمات لمس کنید" + "برای تصحیح کلمات وارد شده آنها را لمس کنید" + "طرح زمینه صفحه کلید" + "صفحه کلید" + "صوتی" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-fi/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-fi/strings.xml new file mode 100644 index 00000000..52a8da62 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-fi/strings.xml @@ -0,0 +1,140 @@ + + + + + "Keepass2Android-näppäimistö" + "Keepass2Android-näppäimistön asetukset" + "Syöttövalinnat" + "Käytä värinää näppäimiä painettaessa" + "Toista ääni näppäimiä painettaessa" + "Ponnahdusikkuna painalluksella" + "Korjaa kirjoitusvirheet" + "Ota syöttövirheen korjaus käyttöön" + "Vaakasuunnan syöttövirheet" + "Ota syöttövirheen korjaus käyttöön" + "Sanaehdotukset" + "Korjaa edellinen sana automaattisesti" + "Sanaehdotukset" + "Sanaehdotusasetukset" + "Ota automaattinen täydennys käyttöön kirjoitettaessa" + "Automaattinen täydennys" + "Suurenna tekstikenttää" + "Piilota sanaehdotukset vaakasuuntaisessa näkymässä" + "Automaattiset isot kirjaimet" + "Aloittaa lauseet isolla kirjaimella" + "Automaattiset välimerkit" + + "Pikakorjaukset" + "Korjaa yleiset kirjoitusvirheet" + "Näytä ehdotukset" + "Näytä sanaehdotukset kirjoitettaessa" + "Automaattinen täydennys" + "Välilyönti ja välimerkki lisäävät automaattisesti korostetun sanan" + "Näytä asetukset-näppäin" + "Automaattinen" + "Näytä aina" + "Piilota aina" + + + + "Bigram-ehdotukset" + "Paranna ehdotusta aiemman sanan avulla" + + "Ei mitään" + "Tavallinen" + "Edistynyt" + + "%s : Tallennettu" + "Näet aksenttimerkit (ø, ö jne.) pitämällä näppäintä painettuna." + "Voit sulkea näppäimistön milloin tahansa painamalla Takaisin-painiketta ↶" + "Käytä numeroita ja symboleita" + "Lisää vasemmanpuoleinen sana sanakirjaan pitämällä sitä painettuna" + "Jatka koskettamalla tätä vihjettä »" + "Sulje tämä vihje ja aloita kirjoittaa koskettamalla tätä!" + "Näppäimistö avautuu, kun kosketat tekstikenttää" + "Näytä aksenttimerkit pitämällä näppäintä painettuna"\n"(ø, ö, ô, ó ja niin edelleen" + "Vaihda numeroihin ja symboleihin koskettamalla tätä näppäintä" + "Siirry takaisin kirjaimiin koskettamalla tätä näppäintä uudelleen" + "Muuta näppäimistön asetuksia, kuten automaattista täydentämistä, pitämällä tätä näppäintä painettuna" + "Kokeile!" + "Siirry" + "Seuraava" + "Valmis" + "Lähetä" + "?123" + "123" + "ABC" + "ALT" + "Äänisyöte" + "Äänisyötettä ei vielä tueta kielelläsi, mutta voit käyttää sitä englanniksi." + "Äänisyöte on kokeellinen Googlen puheentunnistusta käyttävä ominaisuus." + "Siirry näppäimistön asetuksiin poistaaksesi äänisyötteen käytöstä." + "Käytä äänisyötettä painamalla mikrofonipainiketta tai liu\'uttamalla sormeasi näytön näppäimistön poikki." + "Puhu nyt" + "Työstetään" + + "Virhe. Yritä uudelleen." + "Ei yhteyttä" + "Virhe, liikaa puhetta." + "Ääniongelma" + "Palvelinvirhe" + "Puhetta ei kuulu" + "Ei vastineita" + "Äänihakua ei asennettu" + "Vihje:"" liu\'uta sormea näppäimistöllä ja puhu" + "Vihje:"" kokeile seuraavalla kerralla puhua välimerkit, kuten \"period\" (piste), \"comma\" (pilkku) tai \"question mark\" (kysymysmerkki)." + "Peruuta" + "OK" + "Äänisyöte" + + "Päänäppäimistössä" + "Symbolinäppäimistössä" + "Pois käytöstä" + + + "Päänäppäimistön mikrofoni" + "Symbolinäppäimistön mikrofoni" + "Äänisyöte ei ole käytössä" + + "Lähetä automaattisesti puheen jälkeen" + "Paina automaattisesti enter-näppäintä tehdessäsi hakuja tai siirtyessäsi seuraavaan kenttään." + "Avaa näppäimistö"\n\n"Kosketa tekstikenttää." + "Sulje näppäimistö"\n\n"Paina Takaisin-näppäintä." + "Näet asetukset pitämällä näppäintä painettuna"\n\n"Käytä välimerkkejä ja aksenttimerkkejä." + "Näppäimistön asetukset"\n\n"Pidä painettuna""?123""-näppäintä." + ".com" + ".net" + ".org" + ".gov" + ".edu" + "Valitse syöttötapa" + "Syöttökielet" + "Vaihda kieltä liu\'uttamalla sormea välilyöntinäppäimellä" + "← Tallenna koskettamalla uudelleen" + "Sanakirja saatavilla" + "Ota käyttäjäpalaute käyttöön" + "Auta parantamaan tätä syöttötavan muokkausohjelmaa lähettämällä automaattisesti käyttötietoja ja kaatumisraportteja Googlelle." + "Korjaa sanoja koskettamalla" + "Korjaa sanoja koskettamalla niitä" + "Näppäimistön teema" + "näppäimistö" + "ääni" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-fi/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-fi/strings_kp2a.xml new file mode 100644 index 00000000..7fe2faf7 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-fi/strings_kp2a.xml @@ -0,0 +1,20 @@ + + + + Valitse toinen merkintä + Valitse merkintä + Etsi merkintä \"%1$s\" + Käyttäjä + Salasana + Tietojen syötön asetukset + Automaattinen täyttö + Täytä kenttä automaattisesti kun se havaitaan tyhjänä. Jos merkintä on saatavana Keepass2Android näppäimistölle ja kentän vihjearvo löytyy. + Muista kenttien vihjeet + Jos tekstikenttä täytetään manuaalisesti valitsemalla Keepass2Androidin tarjoama arvo, muista mikä arvo kenttään syötettiin. Kenttä tunnistetaan uudelleen myöhemmin vihjetekstin perusteella. + 1-rivinen näppäimistö + Näytä 1-rivinen näppäimistö jos merkintä on saatavilla. Jos asetus ei ole käytössä, näytetään valintaruutu Keepass2Android näppäimistön kuvaketta painettaessa. + Lukitse tietokanta kun on valmis + Lukitse tietokanta automaattisesti kun painetaan yksinkertaisen 1-rivisen näppäimistön Valmis/Lähetä/Mene näppäintä. + Näppäimistön vaihto + Vaihda näppäimistö kun painetaan yksinkertaisen 1-rivisen näppäimistön Valmis/Lähetä/Siirry näppäintä. + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-fr-rCA/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-fr-rCA/strings.xml new file mode 100644 index 00000000..03d696c7 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-fr-rCA/strings.xml @@ -0,0 +1,19 @@ + + + + "Clavier Keepass2Android" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-fr/bools.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-fr/bools.xml new file mode 100644 index 00000000..897f4b3d --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-fr/bools.xml @@ -0,0 +1,22 @@ + + + + true + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-fr/donottranslate-altchars.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-fr/donottranslate-altchars.xml new file mode 100644 index 00000000..874d89da --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-fr/donottranslate-altchars.xml @@ -0,0 +1,33 @@ + + + + 1àáâãäåæ + 3èéêë + ìíîï8 + òóôõöœø9 + ùúûü7 + §ß + ñ + ç + ýÿ6 + + + 2 + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-fr/donottranslate.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-fr/donottranslate.xml new file mode 100644 index 00000000..b79df7b3 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-fr/donottranslate.xml @@ -0,0 +1,25 @@ + + + + + .\u0009\u0020,;:!?\'\n()[]*&@{}/<>_+=|\u0022 + + ., + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-fr/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-fr/strings.xml new file mode 100644 index 00000000..8d1fb13d --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-fr/strings.xml @@ -0,0 +1,140 @@ + + + + + "Clavier Keepass2Android" + "Paramètres du clavier Keepass2Android" + "Options de saisie" + "Vibrer à chaque touche" + "Son à chaque touche" + "Agrandir les caractères" + "Corriger les fautes de frappe" + "Activer la correction des erreurs de saisie" + "Erreurs de saisie en mode paysage" + "Activer la correction des erreurs de saisie" + "Saisie prédictive" + "Corriger automatiquement le mot précédent" + "Saisie prédictive" + "Paramètres de la saisie prédictive" + "Activer la saisie semi-automatique" + "Saisie semi-automatique" + "Agrandir le champ de texte" + "Masquer la saisie prédictive en mode paysage" + "Majuscules auto" + "Mettre en majuscule la première lettre de chaque phrase" + "Ponctuation automatique" + + "Corrections rapides" + "Corrige les fautes de frappe courantes" + "Afficher les suggestions" + "Afficher les suggestions de terme lors de la saisie" + "Saisie semi-automatique" + "Insérer autom. terme surligné (pression sur barre espace/ponctuation)" + "Afficher touche param." + "Automatique" + "Toujours afficher" + "Toujours masquer" + + + + "Suggestions de type bigramme" + "Améliorer la suggestion en fonction du mot précédent" + + "Aucun" + "Simple" + "Avancé" + + "%s : enregistré" + "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" + "Appuyer et maintenir le doigt sur le mot le plus à gauche pour l\'ajouter au dictionnaire" + "Touchez ce conseil pour continuer »" + "Touchez ici pour fermer ce conseil et commencer à saisir votre texte." + "Le clavier s\'affiche à chaque fois que vous touchez une zone de texte." + "Maintenez une touche enfoncée pour afficher les accents"\n"(ø, ö, ô, ó, etc.)""." + "Appuyez sur cette touche pour basculer vers les chiffres et les symboles." + "Appuyez de nouveau sur cette touche pour retourner aux lettres." + "Maintenez cette touche enfoncée afin de modifier les paramètres du clavier, tels que la saisie semi-automatique." + "Essayez !" + "OK" + "Suivant" + "OK" + "Envoyer" + "?123" + "123" + "ABC" + "ALT" + "Saisie vocale" + "La saisie vocale n\'est pas encore prise en charge pour votre langue, mais elle fonctionne en anglais." + "La saisie vocale est une fonctionnalité expérimentale qui fait appel à la reconnaissance vocale en réseau de Google." + "Pour désactiver la saisie vocale, accédez aux paramètres du clavier." + "Pour utiliser la saisie vocale, appuyez sur la touche du microphone ou faites glisser votre doigt sur le clavier à l\'écran." + "Parlez maintenant" + "Traitement en cours" + + "Erreur. Veuillez réessayer." + "Connexion impossible" + "Erreur, discours trop long." + "Problème audio" + "Erreur serveur" + "Aucune requête vocale détectée" + "Aucune correspondance n\'a été trouvée." + "Recherche vocale non installée" + "Astuce :"" Faites glisser votre doigt sur le clavier pour parler." + "Astuce :"" La prochaine fois, essayez de prononcer la ponctuation, en énonçant des termes tels que \"point\", \"virgule\" ou \"point d\'interrogation\"." + "Annuler" + "OK" + "Saisie vocale" + + "Sur le clavier principal" + "Sur le clavier des symboles" + "Désactivée" + + + "Micro sur le clavier principal" + "Micro sur le clavier des symboles" + "Saisie vocale désactivée" + + "Envoi automatique après la saisie vocale" + "Appuyez automatiquement sur Entrée pour effectuer une recherche ou accéder au champ suivant." + "Ouvrir le clavier"\n\n"Appuyez sur un champ de texte." + "Fermer le clavier"\n\n"Appuyez sur la touche Retour." + "Appuyez 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" + "Sélectionner un mode de saisie." + "Langues de saisie" + "Faites glisser votre doigt sur la barre d\'espacement pour changer la langue." + "← Appuyer de nouveau pour enregistrer" + "Dictionnaire disponible" + "Autoriser les commentaires des utilisateurs" + "Contribuer à l\'amélioration de cet éditeur du mode de saisie grâce à l\'envoi automatique de statistiques d\'utilisation et de rapports d\'incident à Google." + "Appuyer pour corriger" + "Appuyer sur les mots saisis pour les corriger" + "Thème du clavier" + "clavier" + "voix" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-fr/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-fr/strings_kp2a.xml new file mode 100644 index 00000000..868b991a --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-fr/strings_kp2a.xml @@ -0,0 +1,20 @@ + + + + Choisir une autre entrée + Choisir une entrée + Rechercher une entrée avec \"%1$s\" + Utilisateur + Mot de passe + Paramètres d\'entrée des identifiants + Remplissage automatique activé + Renseigner automatiquement le texte lorsqu\'un champ vide est saisi, si une entrée Keepass2Android est disponible pour le clavier et qu\'il y a un champ qui correspond au texte d\'indication du champ. + Rappeler le texte du champ d\'information + Si un champ est rempli en sélectionnant manuellement le champ de Keepass2Android, n\'oubliez pas le champ qui a été entré dans le champ. Le champ est à nouveau détecté plus tard grâce à son texte d\'indication. + Clavier simple + Afficher le clavier simple 1-ligne si une entrée est disponible pour le clavier. Si désactivé, une boîte de dialogue apparaît lorsque vous appuyez sur la touche Keepass2Android. + Verrouiller la base de données lorsque terminé + Lorsque vous appuyez sur la touche Terminé/Envoyé/Go sur le clavier simple 1-ligne, verrouille automatiquement la base de données. + Changer de clavier lorsque terminé + Lorsque vous appuyez sur la touche Terminé/Envoyé/Go sur le clavier simple 1-ligne, changer le clavier. + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-hr/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-hr/strings.xml new file mode 100644 index 00000000..38702666 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-hr/strings.xml @@ -0,0 +1,140 @@ + + + + + "Keepass2Android tipkovnica" + "Postavke tipkovnice za Keepass2Android" + "Opcije ulaza" + "Vibracija pri pritisku na tipku" + "Zvuk pri pritisku tipke" + "Povećanja na pritisak tipke" + "Ispravi pogreške u pisanju" + "Omogućavanje ispravka pogreške pri unosu" + "Pogreške pri pejzažnom unosu" + "Omogućavanje ispravka pogreške pri unosu" + "Prijedlozi riječi" + "Automatsko ispravljanje prethodne riječi" + "Prijedlozi riječi" + "Postavke prijedloga riječi" + "Omogućavanje automatskog dovršavanja pri upisivanju" + "Automatsko dovršavanje" + "Povećaj tekstualno polje" + "Sakrij prijedloge riječi u pejzažnom prikazu" + "Automatsko pisanje velikih slova" + "Stavi veliko slovo na početku rečenice" + "Automatsko stavljanje interpunkcije" + + "Brzi popravci" + "Ispravlja uobičajene pogreške u pisanju" + "Pokaži prijedloge" + "Prikazivanje predloženih riječi prilikom upisivanja" + "Automatsko dovršavanje" + "Razmaknica i interpunkcija automatski umeću istaknutu riječ" + "Prikaži tipku postavki" + "Automatski" + "Uvijek prikaži" + "Uvijek sakrij" + + + + "Bigram prijedlozi" + "Upotrijebi prethodnu riječ radi poboljšanja prijedloga" + + "Nijedan" + "Osnovni" + "Napredno" + + "%s : Spremljeno" + "Pritisnite i držite tipku da biste vidjeli naglaske (ø, ö itd.)" + "Pritisnite tipku \"Natrag\" ↶ za zatvaranje tipkovnice" + "Pristup brojevima i simbolima" + "Pritisnite i držite krajnju lijevu riječ da biste je dodali u rječnik." + "Dodirnite ovaj savjet za nastavak »" + "Dodirnite ovdje da biste zatvorili savjet i počeli upisivati!" + "Tipkovnica se otvara svaki put kada dodirnete tekstualno polje" + "Dodirnite i držite tipku da biste vidjeli naglaske"\n"(ø, ö, ô, ó i tako dalje)" + "Prijeđite na brojeve i simbole dodirom na ovu tipku" + "Dodirnite ponovo ovu tipku za povratak na slova" + "Dodirnite i držite ovu tipku da biste promijenili postavke tipkovnice, poput automatskog dovršavanja" + "Isprobajte!" + "Idi" + "Dalje" + "Gotovo" + "Pošalji" + "?123" + "123" + "ABC" + "ALT" + "Glasovni ulaz" + "Vaš jezik trenutno nije podržan za glasovni unos, ali radi za engleski." + "Glasovni unos je pokusna značajka koja koristi Googleovo umreženo prepoznavanje govora." + "Za isključivanje glasovnog unosa idite na postavke tipkovnice." + "Da biste koristili glasovni unos pritisnite gumb mikrofona ili kliznite prstom preko tipkovnice na zaslonu." + "Govorite sad" + "Obrada" + + "Pogreška. Pokušajte ponovo." + "Spajanje nije bilo moguće" + "Pogreška, predugi govor." + "Problem sa zvukom" + "Pogreška na poslužitelju" + "Nije se čuo govor" + "Nisu pronađeni rezultati" + "Glasovno pretraživanje nije instalirano" + "Savjet:"" Prijeđite preko tipkovnice pa govorite" + "Savjet:"" Sljedeći put pokušajte izgovoriti znakove interpunkcije poput \"točka, \"zarez\" ili \"upitnik\"." + "Odustani" + "U redu" + "Glasovni ulaz" + + "Na glavnoj tipkovnici" + "Na tipkovnici sa simbolima" + "Isključeno" + + + "Mikrofon na glavnoj tipkovnici" + "Mikrofon na tipkovnici sa simbolima" + "Glasovni unos je onemogućen" + + "Automatski pošalji nakon glasovnog unosa" + "Automatski se pritišće \"Enter\" kad pretražujete ili idete na sljedeće polje." + "Otvaranje tipkovnice"\n\n"Dodirnite bilo koje tekstualno polje" + "Zatvaranje tipkovnice"\n\n"Pritisnite tipku \"Natrag\"." + "Dodirnite i držite tipku da biste vidjeli opcije"\n\n"Pristup interpunkciji i naglascima." + "Postavke tipkovnice"\n\n"Dodirnite i držite tipku ""?123""." + ".com" + ".net" + ".org" + ".gov" + ".edu" + "Odabir ulazne metode" + "Jezici unosa" + "Kliznite prstom po razmaknici za promjenu jezika" + "← Dodirnite opet za spremanje" + "Rječnik je dostupan" + "Omogući korisničke povratne informacije" + "Pomozite u poboljšanju ovog urednika ulazne metode automatskim slanjem statistike upotrebe i padova Googleu." + "Dodirnite za ispravak riječi" + "Dodirnite unesene riječi radi ispravka" + "Tema tipkovnice" + "tipkovnica" + "glas" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-hu/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-hu/strings.xml new file mode 100644 index 00000000..98dbc113 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-hu/strings.xml @@ -0,0 +1,140 @@ + + + + + "Keepass2Android-billentyűzet" + "Keepass2Android billentyűzetbeállítások" + "Beviteli beállítások" + "Rezgés billentyű megnyomása esetén" + "Hangjelzés billentyű megnyomása esetén" + "Legyen nagyobb billentyű lenyomásakor" + "Gépelési hibák kijavítása" + "Beviteli hibák javításának engedélyezése" + "Fekvő beviteli hibák" + "Beviteli hibák javításának engedélyezése" + "Szójavaslatok" + "Az előző szó automatikus kijavítása" + "Szójavaslatok" + "Szójavaslati beállítások" + "Automatikus kiegészítés engedélyezése gépelés közben" + "Automatikus kiegészítés" + "A szövegmező méretének növelése" + "Szójavaslatok elrejtése fekvő nézetben" + "Automatikusan nagy kezdőbetű" + "Nagybetűvel kezdi a mondatot" + "Automatikus központozás" + + "Gyorsjavítások" + "Kijavítja a gyakori gépelési hibákat" + "Javaslatok megjelenítése" + "A javasolt szavak megjelenítése gépelés közben" + "Automatikus kiegészítés" + "A szóköz és az írásjelek használata automatikusan beszúrja a kiemelt szót" + "Beállítások billentyű megjelenítése" + "Automatikus" + "Mindig látszik" + "Mindig rejtve" + + + + "Bigram javaslatok" + "Előző szó használata a javaslatok javításához" + + "Nincs" + "Alap" + "Speciális" + + "%s : mentve" + "Az ékezetes betűk megtekintéséhez tartsa lenyomva valamelyik billentyűt (ø, ö stb.)" + "A vissza gomb ↶ megnyomásával bármikor elrejtheti a billentyűzetet" + "Számok és szimbólumok elérése" + "A szótárhoz történő hozzáadásához nyomja meg hosszan a bal oldali legszélső szót" + "A folytatáshoz érintse meg ezt a tippet »" + "Érintse meg itt a tipp bezárásához és a gépelés megkezdéséhez." + "Szövegmező megérintésekor a billentyűzet mindig megjelenik" + "Érintse meg és tartsa lenyomva valamelyik billentyűt az ékezetes betűk megtekintéséhez"\n"(ø, ö, ô, ó stb.)" + "Számokra és szimbólumokra ennek a billentyűnek a megérintésével válthat" + "A billentyű újbóli megérintésével visszatérhet a betűkhöz" + "Érintse meg és tartsa lenyomva ezt a billentyűt a billentyűzet-beállítások (pl. az automatikus kiegészítés) módosításához" + "Próbálja ki!" + "Ugrás" + "Tovább" + "Kész" + "Küldés" + "?123" + "123" + "ABC" + "ALT" + "Hangbevitel" + "A hangbevitel szolgáltatás jelenleg nem támogatja az Ön nyelvét, ám angolul működik." + "A hangbevitel a Google hálózati beszédfelismerését alkalmazó kísérleti funkció." + "A hangbevitelt a billentyűzet beállításai között lehet kikapcsolni." + "A hangbevitel használatához nyomja meg a mikrofon gombját vagy húzza végig az ujját a képernyő-billentyűzeten." + "Most beszéljen" + "Feldolgozás" + + "Hiba történt. Kérjük, próbálja újra." + "Nem sikerült kapcsolódni" + "Hiba történt; túl sokat beszélt." + "Hangprobléma" + "Szerverhiba" + "Nem hallatszott beszéd" + "Nem található egyezés" + "A hangalapú keresés nincs telepítve" + "Tipp:"" húzza végig az ujját a billentyűzeten a beszédhez" + "Tipp:"" következő alkalommal próbálja ki az írásjelek kimondását is, pl. \"period\", \"comma\" vagy \"question mark\"." + "Mégse" + "OK" + "Hangbevitel" + + "Főbillentyűzeten" + "Szimbólumbillentyűzeten" + "Ki" + + + "Mikrofon a főbillentyűzeten" + "Mikrofon a szimbólumbillentyűzeten" + "A hangbevitel ki van kapcsolva" + + "Automatikus küldés a beszéd után" + "Az Enter automatikus megnyomása keresés vagy a következő mezőre ugrás során." + "A billentyűzet megjelenítése"\n\n"Érintse meg valamelyik szövegmezőt." + "A billentyűzet bezárása"\n\n"Nyomja meg a Vissza billentyűt." + "A lehetőségek megjelenítéséhez érintse meg és tartsa lenyomva valamelyik billentyűt"\n\n"Az írásjelek és az ékezetes betűk elérése." + "Billentyűzetbeállítások"\n\n"Érintse meg és tartsa lenyomva a ""?123"" billentyűt." + ".com" + ".net" + ".org" + ".gov" + ".edu" + "Beviteli mód kiválasztása" + "Beviteli nyelvek" + "A nyelv módosításához húzza végig az ujját a szóköz billentyűn" + "← Érintse meg újra a mentéshez" + "Van elérhető szótár" + "Felhasználói visszajelzés engedélyezése" + "Segíthet ennek a beviteli módszernek a javításában, ha engedélyezi a használati statisztikák és a hibajelentések elküldését a Google-nak." + "Javítás a szavak megérintésével" + "A beírt szavakat megérintve kijavíthatja őket" + "Billentyűzettéma" + "billentyűzet" + "hang" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-hu/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-hu/strings_kp2a.xml new file mode 100644 index 00000000..a7b171b3 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-hu/strings_kp2a.xml @@ -0,0 +1,20 @@ + + + + Válasszon egy másik bejegyzést + Válasszon bejegyzést + Bejegyzés keresése: \"%1$s\" + Felhasználó + Jelszó + Hitelesítő adatok bevitele + Automatikus kitöltés engedélyezve + Egy üres mezőbe lépve annak automatikus kitöltése, ha a billentyűzet számára van elérhető Keepass2Android bejegyzés és az tartalmaz a mezőhöz megadott útmutatásnak megfelelő értéket. + A mezők útmutatásának tárolása + Ha egy mezőt egy Keepass2Android érték manuális kiválasztásával tölt ki, rendelődjön hozzá a Keepass2Android értékhez a mezőhöz megadott útmutatás, hogy legközelebb ennek alapján a mezőt automatikusan ki lehessen tölteni. + Egyszerű billentyűzet + Az egyszerű egysoros billentyűzet használata, ha a billentyűzet számára van elérhető Keepass2Android bejegyzés. Ha le van tiltva, egy párbeszédpanel jelenik meg a Keepass2Android billentyű megnyomásakor. + Adatbázis lezárása, ha kész + Az egysoros billentyűzet Kész/Küldés/Ugrás gombjának megnyomásakor az adatbázis automatikus zárolása. + Billentyűzetváltás, ha kész + Az egysoros billentyűzet Kész/Küldés/Ugrás gombjának megnyomásakor automatikus billentyűzet-váltás. + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-in/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-in/strings.xml new file mode 100644 index 00000000..7d07a068 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-in/strings.xml @@ -0,0 +1,140 @@ + + + + + "Keyboard Keepass2Android" + "Setelan Keepass2Android Android" + "Opsi masukan" + "Getar jika tombol ditekan" + "Berbunyi jika tombol ditekan" + "Muncul saat tombol ditekan" + "Perbaiki kesalahan ketik" + "Aktifkan perbaikan galat masukan" + "Galat masukan lanskap" + "Aktifkan perbaikan galat masukan" + "Saran kata" + "Perbaiki kata sebelumnya secara otomatis" + "Saran kata" + "Setelan saran kata" + "Aktifkan pengisian otomatis saat mengetik" + "Pengisian otomatis" + "Tambah ukuran bidang teks" + "Sembunyikan saran kata dalam tampilan melintang" + "Kapitalisasi otomatis" + "Kapitalisasi awal kalimat" + "Beri tanda baca otomatis" + + "Perbaikan cepat" + "Memperbaiki kesalahan ketik umum" + "Perlihatkan saran" + "Tampilkan kata yang disarankan ketika mengetik" + "Pengisian otomatis" + "Bilah spasi dan tanda baca secara otomatis memasukkan kata yang disorot" + "Lihat tombol setelan" + "Otomatis" + "Selalu tampilkan" + "Selalu sembunyikan" + + + + "Saran Bigram" + "Gunakan kata sebelumnya untuk meningkatkan sara" + + "Tak Satu Pun" + "Dasar" + "Lanjutan" + + "%s : Telah disimpan" + "Tahan tombol untuk melihat aksen (ø, ö, dll.)" + "Tekan tombol kembali ↶ untuk menutup keyboard kapan saja" + "Akses angka dan simbol" + "Tekan terus kata yang paling kiri untuk menambahkannya ke kamus" + "Sentuh petunjuk ini untuk melanjutkan »" + "Sentuh di sini untuk menutup petunjuk dan mulailah mengetik!" + "Keyboard terbuka setiap kali Anda menyentuh bidang teks" + "Sentuh & tahan tombol untuk melihat aksen"\n"(ø, ö, ô, ó, dan seterusnya)" + "Beralih ke angka dan simbol dengan menekan tombol ini" + "Kembali ke huruf dengan menekan tombol ini lagi" + "Sentuh & tahan tombol ini untuk mengubah setelan keyboard, seperti lengkapi otomatis" + "Cobalah!" + "Buka" + "Berikutnya" + "Selesai" + "Kirimkan" + "?123" + "123" + "ABC" + "ALT" + "Masukan suara" + "Masukan suara saat ini tidak didukung untuk bahasa Anda, tetapi bekerja dalam Bahasa Inggris." + "Masukan suara adalah fitur eksperimental yang menggunakan pengenal suara berjaringan Google." + "Untuk mematikan masukan suara, buka setelan keyboard." + "Untuk menggunakan masukan suara, tekan tombol mikrofon atau geser jari Anda di sepanjang keyboard pada layar." + "Ucapkan sekarang" + "Bekerja" + + "Galat: Coba lagi." + "Tidak dapat menyambung" + "Galat, terlalu banyak ucapan." + "Masalah audio" + "Galat server" + "Tidak terdengar ucapan" + "Tak ditemukan yang cocok" + "Penelusuran suara tidak terpasang" + "Petunjuk:"" Gesek keyboard untuk berbicara" + "Petunjuk:"" Selanjutnya, coba ucapkan tanda baca seperti \"titik\", \"koma\", atau \"tanda tanya\"." + "Batal" + "OK" + "Masukan suara" + + "Di keyboard utama" + "Di keyboard simbol" + "Mati" + + + "Mik di keyboard utama" + "Mik di keyboard simbol" + "Masukan suara dinonaktifkan" + + "Kirim otomatis setelah suara" + "Tekan enter secara otomatis saat menelusuri atau menuju ke bidang berikutnya." + "Buka keyboard"\n\n"Sentuh bidang teks mana pun." + "Tutup keyboard"\n\n"Tekan tombol Kembali." + "Sentuh & tahan tombol tertentu untuk opsi"\n\n"Akses tanda baca dan aksen." + "Setelan keyboard"\n\n"Sentuh & tahan tombol ""?123""." + ".com" + ".net" + ".org" + ".gov" + ".edu" + "Pilih metode masukan" + "Bahasa masukan" + "Geser jari pada bilah spasi untuk mengubah bahasa" + "← Sentuh sekali lagi untuk menyimpan" + "Kamus yang tersedia" + "Aktifkan umpan balik pengguna" + "Bantu tingkatkan metode editor masukan dengan mengirim statistik penggunaan dan laporan kerusakan ke Google secara otomatis." + "Sentuh untuk memperbaiki kata" + "Sentuh kata yang dimasukkan untuk memperbaikinya" + "Tema Keyboard" + "keyboard" + "suara" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-in/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-in/strings_kp2a.xml new file mode 100644 index 00000000..345f4413 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-in/strings_kp2a.xml @@ -0,0 +1,7 @@ + + + + Pilih entri lain + Pilih entri + Mencari entri dengan \"%1$s\" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-it/bools.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-it/bools.xml new file mode 100644 index 00000000..897f4b3d --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-it/bools.xml @@ -0,0 +1,22 @@ + + + + true + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-it/donottranslate-altchars.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-it/donottranslate-altchars.xml new file mode 100644 index 00000000..23960171 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-it/donottranslate-altchars.xml @@ -0,0 +1,30 @@ + + + + àá + 3èé + ìíîï8 + òó9 + ùúûü7 + § + ñ + ç + ýÿ6 + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-it/donottranslate.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-it/donottranslate.xml new file mode 100644 index 00000000..3e3f3ef2 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-it/donottranslate.xml @@ -0,0 +1,23 @@ + + + + + .\u0009\u0020,;:!?\'\n()[]*&@{}/<>_+=|\u0022 + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-it/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-it/strings.xml new file mode 100644 index 00000000..bc906530 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-it/strings.xml @@ -0,0 +1,140 @@ + + + + + "Tastiera Keepass2Android" + "Impostazioni tastiera Keepass2Android" + "Opzioni inserimento" + "Vibrazione tasti" + "Suono tasti" + "Popup sui tasti" + "Correggi errori di digitazione" + "Attiva la correzione degli errori di inserimento" + "Errori di inserimento in visualizzazione orizzontale" + "Attiva la correzione degli errori di inserimento" + "Suggerimenti parola" + "Correggi automaticamente la parola precedente" + "Suggerimenti parola" + "Impostazioni suggerimento parole" + "Attiva il completamento automatico durante la digitazione" + "Completamento automatico" + "Aumenta dimensioni campo di testo" + "Nascondi i suggerimenti delle parole in visualizzazione orizzontale" + "Maiuscole automatiche" + "Rendi maiuscole le iniziali delle frasi" + "Punteggiatura automat." + + "Correzioni veloci" + "Corregge gli errori di digitazione più comuni" + "Mostra suggerimenti" + "Visualizza le parole suggerite durante la digitazione" + "Completamento autom." + "Barra spaziatrice e punteggiatura inseriscono la parola evidenziata" + "Mostra tasto impostaz." + "Automatico" + "Mostra sempre" + "Nascondi sempre" + + + + "Suggerimenti sui bigrammi" + "Utilizza parola precedente per migliorare il suggerimento" + + "Nessuna" + "Base" + "Avanzate" + + "%s : parola salvata" + "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" + "Tieni premuto sulla parola all\'estrema sinistra per aggiungerla al dizionario" + "Tocca questo suggerimento per continuare »" + "Tocca qui per chiudere questo suggerimento e iniziare a digitare." + "La tastiera si apre ogni volta che tocchi un campo di testo" + "Tocca e tieni premuto un pulsante per visualizzare le lettere con segni diacritici"\n"(ø, ö, ô, ó e così via)" + "Passa a numeri e simboli toccando questo pulsante" + "Torna alle lettere toccando di nuovo questo pulsante" + "Tocca e tieni premuto questo pulsante per modificare le impostazioni della tastiera, come il completamento automatico" + "Prova!" + "Vai" + "Avanti" + "Fine" + "Invia" + "?123" + "123" + "ABC" + "ALT" + "Comandi vocali" + "I comandi vocali non sono attualmente supportati per la tua lingua ma funzionano in inglese." + "I comandi vocali sono una funzione sperimentale che utilizza il riconoscimento vocale in rete di Google." + "Per disattivare i comandi vocali, vai alle impostazioni della tastiera." + "Per utilizzare i comandi vocali, premi il pulsante del microfono o fai scorrere il dito sulla tastiera sullo schermo." + "Parla ora" + "Elaborazione in corso" + + "Errore. Riprova più tardi." + "Impossibile connettersi." + "Errore: conversazione troppo lunga." + "Problema audio" + "Errore del server" + "Nessuna frase vocale rilevata" + "Nessuna corrispondenza trovata" + "Ricerca vocale non installata" + "Suggerimento."" Fai scorrere il dito sulla tastiera per parlare" + "Suggerimento."" La prossima volta, prova a pronunciare termini relativi alla punteggiatura come \"punto\", \"virgola\" o \"punto di domanda\"." + "Annulla" + "OK" + "Comandi vocali" + + "Su tastiera principale" + "Su tastiera simboli" + "Non attivi" + + + "Microfono su tastiera principale" + "Microfono su tastiera simboli" + "Comandi vocali disabilitati" + + "Invia automaticamente dopo comando vocale" + "Premi automaticamente \"Invio\" durante una ricerca o un passaggio al campo successivo." + "Apertura tastiera"\n\n"Tocca qualsiasi campo di testo." + "Chiusura tastiera"\n\n"Premi il tasto Indietro." + "Tocca e tieni premuto un pulsante per le opzioni"\n\n"Accesso a punteggiatura e accenti." + "Impostazioni tastiera"\n\n"Tocca e tieni premuto il pulsante ""?123""." + ".com" + ".net" + ".org" + ".gov" + ".edu" + "Seleziona metodo di inserimento" + "Lingue comandi" + "Scorri il dito sulla barra spaziatrice per cambiare la lingua" + "← Tocca di nuovo per salvare" + "Dizionario disponibile" + "Attiva commenti degli utenti" + "Aiuta a migliorare l\'editor del metodo di inserimento inviando automaticamente a Google statistiche sull\'utilizzo e segnalazioni sugli arresti anomali." + "Tocca per correggere" + "Tocca le parole inserite per correggerle" + "Tema della tastiera" + "tastiera" + "vocale" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-it/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-it/strings_kp2a.xml new file mode 100644 index 00000000..079889d7 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-it/strings_kp2a.xml @@ -0,0 +1,20 @@ + + + + Seleziona un\'altra voce + Seleziona una voce + Cerca la voce \"%1$s\" + Utente + Password + Impostazioni delle credenziali di ingresso + Auto-Compilazione abilitata + Inserisci automaticamente il testo, quando si entra in un campo vuoto, se è selezionata una voce di Keepass2Android per la tastiera ed esiste un valore che corrisponde al testo di suggerimento del campo. + Ricorda i testi di suggerimento del campo + Se un campo di testo viene compilato selezionando manualmente il valore di Keepass2Android, ricorda quale valore è stato immesso nel campo. In seguito il campo di testo verrà rilevato tramite il suo testo di suggerimento. + Tastiera semplice + Mostra la tastiera a una riga se è disponibile una voce per la tastiera. Se disabilitato, verrà mostrata una finestra di dialogo alla pressione del tasto Keepass2Android. + Blocca il database quando terminato + Premendo il tasto Fatto/Invia/Vai sulla tastiera a una riga, blocca automaticamente il database. + Cambia tastiera quando terminato + Premendo il tasto Fatto/Invia/Vai sulla tastiera a una riga, cambia la tastiera. + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-iw/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-iw/strings.xml new file mode 100644 index 00000000..376fc806 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-iw/strings.xml @@ -0,0 +1,140 @@ + + + + + "מקלדת Keepass2Android" + "הגדרות מקלדת של Keepass2Android" + "אפשרויות קלט" + "רטט עם לחיצה על מקשים" + "צלילים עם לחיצה על מקשים" + "חלון קופץ עם לחיצה על מקשים" + "תקן שגיאות הקלדה" + "הפוך תיקון שגיאות קלט לפעיל" + "שגיאות קלט בפריסה לרוחב" + "הפוך תיקון שגיאות קלט לפעיל" + "הצעות למילים" + "תקן באופן אוטומטי את המילה הקודמת" + "הצעות למילים" + "הגדרות של הצעות מילים" + "הפוך השלמה אוטומטית לפעילה בעת הקלדה" + "השלמה אוטומטית" + "הגדל את הגודל של שדה הטקסט" + "הסתר הצעות למילים בתצוגה לרוחב" + "הפיכה אוטומטית של אותיות לרישיות" + "הוסף אות רישית בתחילת משפט" + "פיסוק אוטומטי" + + "תיקונים מהירים" + "מתקן שגיאות הקלדה נפוצות" + "הצג הצעות" + "הצג הצעות למילים בעת הקלדה" + "השלמה אוטומטית" + "הקשה על מקש הרווח וסימני הפיסוק תוסיף באופן אוטומטי את המילה המסומנת" + "הצג מקש הגדרות" + "אוטומטי" + "הצג תמיד" + "הסתר תמיד" + + + + "הצעות של צמדי אותיות (Bigram)" + "השתמש במילה הקודמת כדי לשפר את ההצעה" + + "ללא" + "בסיסי" + "מתקדם" + + "%s : נשמרה" + "החזק מקש לחוץ כדי לראות אקצנטים (ø, ö וכדומה)" + "לחץ על המקש \'הקודם\' ↶ כדי לסגור את המקלדת בכל עת" + "גישה למספרים וסמלים" + "לחץ על המילה השמאלית הקיצונית והחזק אותה לחוצה כדי להוסיף למילון" + "גע ברמז זה כדי להמשיך »" + "גע כאן כדי לסגור רמז זה ולהתחיל בהקלדה!" + "המקלדת נפתחת בכל פעם שאתה נוגע בשדה טקסט" + "גע במקש והחזק אותו לחוץ כדי להציג אקצנטים"\n"(ø, ö, ô, ó וכדומה)" + "עבור למספרים וסמלים על ידי נגיעה במקש זה" + "חזור לאותיות על ידי מגע במקש זה שוב" + "גע במקש זה והחזק אותו לחוץ כדי לשנות את הגדרות המקלדת, כגון השלמה אוטומטית" + "נסה אותו!" + "בצע" + "הבא" + "בוצע" + "שלח" + "?123" + "123" + "ABC" + "ALT" + "קלט קולי" + "קלט קולי אינו נתמך בשלב זה בשפתך, אך הוא פועל באנגלית." + "קלט קולי הוא תכונה ניסיונית של זיהוי הדיבור ברשת של Google." + "כדי לכבות את הקלט הקולי, עבור להגדרות מקלדת." + "כדי להשתמש בקלט הקולי, לחץ על לחצן המיקרופון או החלק את האצבע על המקלדת שבמסך." + "דבר כעת" + "פועל" + + "שגיאה. נסה שוב." + "אין אפשרות להתחבר" + "שגיאה, דיבור רב מדי." + "בעיה באודיו" + "שגיאת שרת" + "לא נשמע דיבור" + "לא נמצאו התאמות" + "חיפוש קולי לא מותקן" + "רמז:"" העבר על המקלדת כדי לדבר" + "רמז:"" בפעם הבאה, נסה לומר את סימני הפיסוק כגון \"נקודה\", \"פסיק\" או \"סימן שאלה\"." + "ביטול" + "אישור" + "קלט קולי" + + "במקלדת הראשית" + "מקלדת סמלים מופעלת" + "כבוי" + + + "מיקרופון במקלדת הראשית" + "מיקרופון במקלדת סמלים" + "הקלט הקולי מושבת" + + "שליחה אוטומטית לאחר הקלטת קול" + "הקש על Enter באופן אוטומטי בעת חיפוש או מעבר לשדה הבא." + "פתח את המקלדת"\n\n"גע בשדה טקסט כלשהו." + "סגור את המקלדת"\n\n"לחץ על הלחצן \'הקודם\'." + "גע במקש והחזק אותו לחוץ לקבלת אפשרויות"\n\n"קבל גישה לסימני פיסוק ואקצנטים." + "הגדרות מקלדת"\n\n"גע במקש ""?123"" והחזק אותו לחוץ." + "‎.com" + "‎.net" + "‎.org" + "‎.gov" + "‎.edu" + "בחר שיטת קלט" + "שפות קלט" + "החלק את האצבע על מקש הרווח כדי לשנות שפה" + "← גע שוב כדי לשמור" + "מילון זמין" + "הפוך משוב ממשתמשים לפעיל" + "עזור לשפר שיטת קלט זו על ידי שליחה אוטומטית של סטטיסטיקת שימוש ודוחות קריסת מחשב ל-Google." + "גע כדי לתקן מילים" + "גע במילים שהוזנו כדי לתקן אותן" + "עיצוב מקלדת" + "מקלדת" + "קולי" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-iw/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-iw/strings_kp2a.xml new file mode 100644 index 00000000..1db547b9 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-iw/strings_kp2a.xml @@ -0,0 +1,15 @@ + + + + בחר ערך אחר + בחר ערך + חפש ערך עם \'%1$s\' + משתמש + סיסמה + הגדרות קלט האימות + השלמה-אוטומאטית מאופשרת + זכור את שדה טקסט הרמזים + מקלדת פשוטה + נעל מסד הנתונים בסיום + החלף מקלדת בסיום + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ja/donottranslate-altchars.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ja/donottranslate-altchars.xml new file mode 100644 index 00000000..d3beafad --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ja/donottranslate-altchars.xml @@ -0,0 +1,30 @@ + + + + àáâãäåæ + 3èéêë + ìíîï8 + òóôõöœø9 + ùúûü7 + §ß + ñ + ç + ýÿ6 + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ja/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ja/strings.xml new file mode 100644 index 00000000..de7da58d --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ja/strings.xml @@ -0,0 +1,140 @@ + + + + + "Keepass2Androidキーボード" + "Keepass2Androidキーボードの設定" + "入力オプション" + "キー操作バイブ" + "キー操作音" + "キー押下時ポップアップ" + "入力ミス補正" + "入力間違いを自動修正する" + "横表示での入力修正" + "入力間違いを自動修正する" + "入力候補表示" + "前の単語を自動修正する" + "入力候補表示" + "入力候補の設定" + "オートコンプリートを使用する" + "オートコンプリート" + "入力作業スペースを広げる" + "横表示では入力候補を表示しない" + "自動大文字変換" + "英字入力で文頭文字を大文字にする" + "句読点を自動入力" + + "クイックフィックス" + "よくある誤字・脱字を修正します" + "入力候補を表示" + "入力時に入力候補を表示する" + "オートコンプリート" + "誤入力をスペースまたは句読点キーで修正する" + "設定キーを表示" + "自動" + "常に表示" + "常に非表示" + + + + "バイグラム入力候補表示" + "直前の単語から入力候補を予測します" + + "なし" + "基本" + "高度" + + "%s:保存しました" + "キー長押しでアクセント文字を表示(ø、öなど)" + "戻るキーでキーボードを閉じます" + "数字と記号" + "一番左の単語を長押しすると辞書に追加されます" + "続けるにはここをタッチ" + "タッチしてこのヒントを終了し、入力を開始してください。" + "テキストフィールドを選択するとキーボードが表示されます" + "キーを長押しするとアクセント付き文字"\n"(ø、ö、ô、óなど)が表示されます" + "このキーを押すと、数字/記号入力に切り替わります" + "このキーを押すと、文字入力に再度切り替わります" + "オートコンプリートなどのキーボードの設定を変更するには、このキーを長押しします" + "試してみてください。" + "実行" + "次へ" + "完了" + "送信" + "?123" + "123" + "ABC" + "ALT" + "音声入力" + "音声入力は現在英語には対応していますが、日本語には対応していません。" + "音声入力はGoogleのネットワーク音声認識技術を利用した試験段階の機能です。" + "音声入力をOFFにするには、キーボードの設定を開きます。" + "音声入力するには、マイクボタンを押すか画面キーボードをスワイプしてください。" + "お話しください" + "処理中" + + "エラーです。もう一度お試しください。" + "接続できませんでした" + "音声が長すぎてエラーになりました。" + "オーディオエラー" + "サーバーエラー" + "音声が聞き取れません" + "該当なし" + "Voice Searchはインストールされていません" + "ヒント:"" 音声入力するにはキーボードをスワイプします" + "ヒント:"" 次回は句読点として「period」、「comma」、「question mark」などの音声入力を試してみてください。" + "キャンセル" + "OK" + "音声入力" + + "メインキーボード上" + "記号キーボード上" + "OFF" + + + "メインキーボードのマイク" + "記号キーボードのマイク" + "音声入力は無効です" + + "入力後に自動送信する" + "検索または次のフィールドに進む際、Enterキーが自動的に押されます。" + "キーボードを開く"\n\n"テキストフィールドをタップします。" + "キーボードを閉じる"\n\n"[戻る]キーを押します。" + "キーを長押しして選択する"\n\n"句読点キーとアクセント文字を表示します。" + "キーボードの設定"\n\n"[""?123""]キーを長押しします。" + ".com" + ".net" + ".org" + ".gov" + ".edu" + "入力方法の選択" + "入力言語" + "スペースバーで指をスライドさせて言語を変更する" + "←保存するにはもう一度タップ" + "辞書を利用できます" + "ユーザーフィードバックを有効にする" + "IMEの機能向上のため、使用統計状況やクラッシュレポートをGoogleに自動送信します。" + "タップして語句を修正" + "入力した語句をタップして修正" + "キーボードテーマ" + "キーボード" + "音声" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ja/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ja/strings_kp2a.xml new file mode 100644 index 00000000..7dc5a795 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ja/strings_kp2a.xml @@ -0,0 +1,20 @@ + + + + 別のエントリを選択 + エントリの選択 + エントリを\"%1$s\"で検索します。 + ユーザー + パスワード + 資格情報の入力の設定 + オートフィルを有効にする + Keepass2Android のエントリーでキーボードが使用可能で、フィールドのヒントのテキストに一致する値がある場合、空のフィールドに自動的にテキストが入力されます。 + フィールドのヒントのテキストを保存 + Keepass2Android の値を手動で選択してテキスト フィールドを入力する場合、テキスト フィールドに入力された値を保存します。後でそのヒント テキストを使用してテキスト フィールドを検出します。 + シンプルキーボード + エントリがキーボードで利用できる場合シンプルな1行のキーボードをを表示します。もし無効にした場合、Keepass2Androidキーが押されたときにダイアログが表示されます。 + 完了時にデーターベースをロックする + シンプルな1行のキーボードで完了/送信/実行キーを押したときにデーターベースを自動でロックします。 + 完了時にキーボードを切り替える + シンプルな1行のキーボードで完了/送信/実行キーを押したときにキーボードを切り替えます。 + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ko/donottranslate-altchars.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ko/donottranslate-altchars.xml new file mode 100644 index 00000000..d3beafad --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ko/donottranslate-altchars.xml @@ -0,0 +1,30 @@ + + + + àáâãäåæ + 3èéêë + ìíîï8 + òóôõöœø9 + ùúûü7 + §ß + ñ + ç + ýÿ6 + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ko/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ko/strings.xml new file mode 100644 index 00000000..b60c7d65 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ko/strings.xml @@ -0,0 +1,140 @@ + + + + + "Keepass2Android 키보드" + "Keepass2Android 키보드 설정" + "입력 옵션" + "키를 누를 때 진동 발생" + "키를 누를 때 소리 발생" + "키를 누를 때 팝업" + "입력 오류 수정" + "입력 오류 수정 사용" + "가로 입력 오류" + "입력 오류 수정 사용" + "단어 추천" + "이전 단어를 자동으로 수정" + "단어 추천" + "단어 추천 설정" + "입력할 때 자동 완성 사용" + "자동 완성" + "입력란 크기 늘리기" + "가로 보기에서 추천 단어 숨기기" + "자동 대문자화" + "문장의 첫 글자를 대문자로 표시" + "자동 구두점 입력" + + "빠른 수정" + "자주 발생하는 오타를 수정합니다." + "추천 단어 표시" + "글자를 입력하는 동안 추천 단어를 표시" + "자동 완성" + "스페이스바와 문장부호 키로 강조 표시된 단어를 자동 삽입" + "설정 키 표시" + "자동" + "항상 표시" + "항상 숨기기" + + + + "Bigram 추천" + "이전 단어를 사용하여 추천 기능 개선" + + "없음" + "기본" + "고급" + + "%s: 저장됨" + "키를 길게 누르면 악센트(ø, ö 등)가 표시됩니다." + "키보드를 닫으려면 언제든지 뒤로 키(↶)를 누르세요." + "숫자 및 기호 사용" + "맨 왼쪽에 있는 단어를 길게 누르면 사전에 추가됩니다." + "계속하려면 힌트를 터치하세요. »" + "힌트를 닫고 입력을 시작하려면 여기를 터치하세요." + "언제든지 입력란을 터치하면 키보드가 열립니다." + "키를 길게 터치하면 악센트"\n"(ø, ö, ô, ó 등)가 표시됩니다." + "이 키를 터치하면 숫자 및 기호 키보드로 전환됩니다." + "이 키를 다시 터치하면 문자 키보드로 돌아갑니다." + "자동 완성과 같은 키보드 설정을 변경하려면 이 키를 길게 터치하세요." + "이제 사용해 보세요." + "이동" + "다음" + "완료" + "전송" + "?123" + "123" + "ABC" + "ALT" + "음성 입력" + "음성 입력은 현재 자국어로 지원되지 않으며 영어로 작동됩니다." + "음성 입력은 Google의 네트워크화된 음성 인식을 사용하는 실험적 기능입니다." + "음성 입력을 사용하지 않으려면 키보드 설정으로 이동하세요." + "음성 입력을 사용하려면 마이크 버튼을 누르거나 터치 키보드 위로 손가락을 미끄러지듯 움직이세요." + "지금 말하세요." + "인식 중" + + "오류가 발생했습니다. 다시 시도해 보세요." + "연결할 수 없습니다." + "음성을 너무 많이 입력했습니다." + "오디오 문제" + "서버 오류" + "음성이 인식되지 않았습니다." + "일치하는 항목 없음" + "음성 검색이 설치되지 않았습니다." + "도움말:"" 키보드 위로 손가락을 미끄러지듯 움직이고 나서 말하세요." + "도움말:"" 다음 번에는 \'마침표\', \'쉼표\', \'물음표\'와 같은 구두점을 말해 보세요." + "취소" + "확인" + "음성 입력" + + "기본 키보드" + "기호 키보드" + "사용 안함" + + + "기본 키보드의 마이크" + "기호 키보드의 마이크" + "음성 입력이 사용 중지됨" + + "음성을 입력한 다음 자동 제출" + "검색하거나 다음 입력란으로 이동할 때 자동으로 Enter 키를 누릅니다." + "키보드 열기"\n\n"아무 텍스트 입력란이나 터치하세요." + "키보드 닫기"\n\n"\'뒤로\' 키를 누르세요." + "키를 길게 눌러 옵션 보기"\n\n"문장 부호 및 악센트 기호 입력창이 열립니다." + "키보드 설정"\n\n"?123"" 키를 길게 누르세요." + ".com" + ".net" + ".org" + ".gov" + ".edu" + "입력 방법 선택" + "입력 언어" + "손가락을 스페이스바에서 미끄러지듯 움직여 언어 변경" + "← 저장하려면 다시 터치하세요." + "사전 사용 가능" + "사용자 의견 사용" + "사용 통계 및 충돌 보고서를 Google에 자동으로 전송하여 입력 방법 편집기의 개선에 도움을 줍니다." + "터치하여 단어 수정" + "입력한 단어를 터치하여 수정" + "키보드 테마" + "키보드" + "음성" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ko/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ko/strings_kp2a.xml new file mode 100644 index 00000000..10025055 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ko/strings_kp2a.xml @@ -0,0 +1,20 @@ + + + + 다른 항목 선택 + 항목 선택 + \"%1$ s\" 항목 검색 + 사용자 + 비밀번호 + 자격증명 입력 설정 + 자동채우기 사용 + Keepass2Android 키보드가 가진 항목의 값이 빈 필드의 힌트 텍스트와 일치하는 경우, 빈 필드를 자동으로 채움 + 필드의 힌트 텍스트 기억하기 + Keepass2Androd의 값을 선택하여 수동으로 필드를 채울 경우, 해당 텍스드 필드 기억하기. 해당 텍스트 필드는 나중에 힌트 텍스트에 의해 다시 감지되게 됨. + 간편 키보드 + 만약 사용가능한 항목이 있다면 1열 간편 키보드를 띄움. 만약 이 옵션이 비활성상태라 하더라도 Keepass2Android 키를 눌러 대화상자에 표시됨. + 완료시 데이테베이스 잠금 + 완료/보내기/엔터 키를 누르면 자동으로 데이터베이스 잠금 + 완료 시 키보드 바꾸기 + 1열 간편키보드 상태에서 완료/보내기/이동 키를 누르면 키보드 전환되기. + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-land/dimens.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-land/dimens.xml new file mode 100644 index 00000000..df8333e8 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-land/dimens.xml @@ -0,0 +1,31 @@ + + + + + 42.329987dip + 2.0dip + 43.19998dip + 0.0dip + 38.0dip + 63.0dip + 2.0dip + 73.44dip + -43.19998dip + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-lt/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-lt/strings.xml new file mode 100644 index 00000000..3ab1cc99 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-lt/strings.xml @@ -0,0 +1,140 @@ + + + + + "„Keepass2Android“ klaviatūra" + "„Keepass2Android“ klaviatūros nustatymai" + "Įvesties parinktys" + "Vibruoti, kai paspaudžiami klavišai" + "Klavišo paspaudimo garsas" + "Iššoka paspaudus klavišą" + "Taisyti rašybos klaidas" + "Įgalinti įvesties klaidos taisymą" + "Gulsčia įvestis" + "Įgalinti įvesties klaidos taisymą" + "Žodžių pasiūlymai" + "Automatiškai taisyti ankstesnį žodį" + "Žodžių pasiūlymai" + "Žodžių pasiūlymo nustatymai" + "Įgalinti automatinį užbaigimą, kai įvedinėjamas tekstas" + "Automatinis užbaigimas" + "Padidinti teksto lauko dydį" + "Gulsčiame rodinyje slėpti žodžių pasiūlymus" + "Automatinis didžiųjų raidžių rašymas" + "Sakinio pradžią rašyti didžiąja raide" + "Automatiškai dėti skyrybos ženklus" + + "Greiti pataisymai" + "Taiso dažnai padarytas rašybos klaidas" + "Rodyti pasiūlymus" + "Įvedant tekstą pateikti siūlomus žodžius" + "Automatiškai užbaigti" + "Tarpo klavišas ir skyrybos ženklai automatiškai įterpia paryškintą žodį" + "Rodyti nustatymų raktą" + "Automatinis" + "Visada rodyti" + "Visada slėpti" + + + + "Digramų pasiūlymai" + "Naudoti ankstesnį žodį pasiūlymui patobulinti" + + "Nėra" + "Paprastas" + "Išplėstinis" + + "%s: išsaugota" + "Laikykite klavišą nuspaudę, kad pamatytumėte kirčius (ø, ö ir t. t.)" + "Paspauskite klavišą „Atgal“ ↶, kad uždarytumėte klaviatūrą" + "Pasiekti skaičius ir simbolius" + "Paspauskite ir laikykite nuspaudę kairiausią žodį, kad pridėtumėte jį prie žodyno" + "Palieskite šią užuominą, jei norite tęsti »" + "Paleiskite čia, kad uždarytumėte šią užuominą ir pradėtumėte įvedinėti tekstą!" + "Klaviatūra atsidarys kaskart, kai paliesite teksto lauką" + "Palieskite ir laikykite klavišą, kad pamatytumėte kirčius"\n"(ø, ö, ô, ó, and so on)" + "Perjunkite į skaičius ir simbolius, paliesdami šį klavišą" + "Grįžkite prie raidžių dar kartą paliesdami šį klavišą" + "Palieskite ir laikykite šį klavišą, kad pakeistumėte klaviatūros nustatymus, pvz., automatinį užbaigimą" + "Išbandykite tai!" + "Pradėti" + "Kitas" + "Atlikta" + "Siųsti" + "?123" + "123" + "ABC" + "ALT" + "Balso įvestis" + "Šiuo metu balso įvestis jūsų kompiuteryje nepalaikoma, bet ji veikia anglų k." + "Balso įvestis – tai eksperimentinė funkcija, naudojanti „Google“ tinklo kalbos atpažinimą." + "Jei norite išjungti balso įvestį, eikite į klaviatūros nustatymus." + "Jei norite naudoti balso įvestį, paspauskite mikrofono mygtuką arba pirštu slyskite ekranine klaviatūra." + "Kalbėkite dabar" + "Veikia" + + "Klaida. Bandykite dar kartą." + "Nepavyko prijungti" + "Klaida, per daug kalbos." + "Problema su garsu" + "Serverio klaida" + "Negirdima jokia kalba" + "Atitikmenų nerasta" + "Balso paieška neįdiegta" + "Užuomina:"" perbraukite klaviatūra, kad galėtumėte kalbėti" + "Užuomina:"" kitą kartą pabandykite sakyti skyrybos ženklų pavadinimus, pvz., „taškas“, „kablelis“ arba „klaustukas“." + "Atšaukti" + "Gerai" + "Balso įvestis" + + "Pagrindinėje klaviatūroje" + "Simbolių klaviatūroje" + "Išjungta" + + + "Pagrindinės klaviatūros mikrofonas" + "Mikrofonas simbolių klaviatūroje" + "Balso įvestis išjungta" + + "Automatiškai pateikti po balso" + "Automatiškai spausti „Įvesti“ ieškant ar einant į kitą lauką." + "Atidarykite klaviatūrą"\n\n"Palieskite bet kurį teksto lauką." + "Uždarykite klaviatūrą"\n\n"Paspauskite klavišą „Atgal“." + "Palieskite ir laikykite klavišą, kad pamatytumėte parinktis"\n\n"Pasiekite skyrybos ženklus ir kirčius." + "Klaviatūros nustatymai"\n\n"Palieskite ir laikykite klavišą ""?123""." + ".com" + ".net" + ".org" + ".gov" + ".edu" + "Pasirinkti įvesties metodą" + "Įvesties kalbos" + "Pirštu slyskite tarpo klavišu, kad pakeistumėte kalbą" + "← Kad išsaugotumėte, dar kartą palieskite" + "Žodynas galimas" + "Įgalinti naudotojų atsiliepimus" + "Padėkite patobulinti šią įvesties metodo redagavimo programą automatiškai „Google“ siųsdami naudojimo statistiką ir strigčių ataskaitas." + "Jei norite ištais. žodž., paliesk." + "Jei norite ištaisyti įvestus žodžius, palieskite juos" + "Klaviatūros tema" + "klaviatūra" + "Voice" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-lv/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-lv/strings.xml new file mode 100644 index 00000000..b1ec1e12 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-lv/strings.xml @@ -0,0 +1,140 @@ + + + + + "Keepass2Android tastatūra" + "Keepass2Android tastatūras iestatījumi" + "Ievades opcijas" + "Vibrēt, nospiežot taustiņu" + "Skaņa, nospiežot taustiņu" + "Nospiežot taustiņu, parādīt uznirstošo izvēlni" + "Labot drukas kļūdas" + "Iespējot ievades kļūdu labošanu" + "Ainavas orientācijas ievades kļūdas" + "Iespējot ievades kļūdu labošanu" + "Vārdu ieteikumi" + "Automātiski labot iepriekšējo vārdu" + "Vārdu ieteikumi" + "Vārdu ieteikumu iestatījumi" + "Iespējot automātisko pabeigšanu ievades laikā" + "Automātiska pabeigšana" + "Palielināt teksta lauka lielumu" + "Ainavas skatījumā slēpt vārdu ieteikumus" + "Automātiska lielo burtu lietošana" + "Sākt teikumu ar lielo burtu" + "Automātiska pieturzīmju lietošana" + + "Ātrie labojumi" + "Nodrošina izplatītu drukas kļūdu labošanu." + "Rādīt ieteikumus" + "Ievades laikā attēlot ieteiktos vārdus" + "Automātiska pabeigšana" + "Automātiski ievietot iezīmēto vārdu, izmantojot atstarpes taustiņu un pieturzīmes" + "Rādīt iestatījumu taustiņu" + "Automātiski" + "Vienmēr rādīt" + "Vienmēr slēpt" + + + + "Bigram ieteikumi" + "Ieteikuma uzlabošanai izmantot iepriekšējo vārdu" + + "Nav" + "Pamata" + "Uzlabots" + + "%s: saglabāts" + "Turiet taustiņu nospiestu, lai skatītu uzsvēruma zīmes (ø, ö u.c.)." + "Jebkurā brīdī nospiediet taustiņu Atpakaļ ↶, lai aizvērtu tastatūru." + "Piekļūt cipariem un simboliem" + "Nospiediet kreisajā pusē esošo vārdu un turiet, lai pievienotu to vārdnīcai." + "Pieskarieties šim ieteikumam, lai turpinātu »" + "Pieskarieties šeit, lai aizvērtu šo ieteikumu un sāktu ievadi." + "Tastatūra tiek atvērta ikreiz, kad pieskaraties teksta laukam""." + "Pieskarieties taustiņam un turiet, lai skatītu uzsvara zīmes"\n"(ø, ö, ô, ó utt.)." + "Pieskarieties šim taustiņam, lai izmantotu ciparus un simbolus." + "Vēlreiz pieskarieties šim taustiņam, lai atkal izmantotu burtus." + "Pieskarieties taustiņam un turiet, lai mainītu tastatūras iestatījumus, piemēram, automātisko pabeigšanu." + "Izmēģiniet to!" + "Sākt" + "Tālāk" + "Gatavs" + "Sūtīt" + "?123" + "123" + "ABC" + "ALT" + "Balss ievade" + "Balss ievade jūsu valodā pašlaik netiek atbalstīta, taču tā ir pieejama angļu valodā." + "Balss ievade ir izmēģinājuma funkcija, kuras pamatā ir Google tīkla runas atpazīšanas līdzeklis." + "Lai izslēgtu balss ievadi, atveriet tastatūras iestatījumus." + "Lai izmantotu balss ievadi, nospiediet mikrofona pogu vai slidiniet pirkstus pāri ekrāna tastatūrai." + "Runājiet!" + "Notiek apstrāde" + + "Kļūda. Lūdzu, mēģiniet vēlreiz." + "Nevar izveidot savienojumu." + "Kļūda, pārāk ilga balss ievade." + "Audio problēma" + "Servera kļūda" + "Nekas nav dzirdams." + "Nav atrasta neviena atbilstība." + "Balss meklēšana nav instalēta." + "Ieteikums:"" slidiniet pirkstu pār tastatūru, lai veiktu balss ievadi." + "Ieteikums:"" nākamreiz mēģiniet izrunāt pieturzīmes, piemēram, “punkts”, “komats” vai “jautājuma zīme”." + "Atcelt" + "Labi" + "Balss ievade" + + "Izmantojot galveno tastatūru" + "Izmantojot simbolu tastatūru" + "Izsl." + + + "Galvenās tastatūras mikrofons" + "Simbolu tastatūras mikrofons" + "Balss ievade ir atspējota" + + "Automātiski iesniegt pēc balss ievades" + "Automātiski nospiest ievades taustiņu, meklējot vai pārejot uz nākamo lauku." + "Tastatūras atvēršana"\n\n"Pieskarieties jebkuram teksta laukam." + "Tastatūras aizvēršana"\n\n"Nospiediet taustiņu Atpakaļ." + "Pieskarieties taustiņam un turiet, lai skatītu opcijas."\n\n"Piekļūstiet pieturzīmēm un uzsvara zīmēm." + "Tastatūras iestatījumi"\n\n"Pieskarieties taustiņam ""?123"" un turiet." + ".com" + ".net" + ".org" + ".gov" + ".edu" + "Atlasīt ievades metodi" + "Ievades valodas" + "Slidiniet pirkstu uz atstarpes taustiņa, lai mainītu valodu" + "← Pieskarieties vēlreiz, lai saglabātu" + "Ir pieejama vārdnīca." + "Iespējot lietotāju atsauksmes" + "Palīdziet uzlabot šo ievades metodes redaktoru, automātiski nosūtot lietojuma statistiku un pārskatus par avārijām uzņēmumam Google." + "Pieskarties, lai izlabotu vārdus" + "Pieskarties ievadītajiem vārdiem, lai tos labotu" + "Tastatūras motīvs" + "tastatūra" + "balss" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-nb/donottranslate-altchars.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-nb/donottranslate-altchars.xml new file mode 100644 index 00000000..6257dfc3 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-nb/donottranslate-altchars.xml @@ -0,0 +1,37 @@ + + + + äáàâąã + 3éèêëę€ + íìîï8 + öóòôõ9 + üúùûū7 + śšşß + ńñň + çćč + ýÿ6 + ðď + ř4 + ťþ5 + źžż + ł + w + œ + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-nb/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-nb/strings.xml new file mode 100644 index 00000000..95a41345 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-nb/strings.xml @@ -0,0 +1,140 @@ + + + + + "Keepass2Android tastatur" + "Innstillinger for Keepass2Android tastatur" + "Inndataalternativer" + "Vibrer ved tastetrykk" + "Lyd ved tastetrykk" + "Hurtigvindu ved tastetrykk" + "Rett opp skrivefeil" + "Slå på retting av skrivefeil" + "Rett opp skrivefeil i breddeformat" + "Slå på retting av skrivefeil" + "Autokorrektur" + "Autokorriger forrige ord" + "Ordforslag" + "Innstillinger for ordforslag" + "Skru på autofullføring under skriving" + "Autofullfør" + "Større tekstfelt" + "Skjul ordforslag i breddeformat" + "Stor forbokstav" + "Start automatisk setninger med stor bokstav" + "Automatisk punktum" + + "Autokorrektur" + "Retter vanlige stavefeil" + "Vis forslag" + "Vis foreslåtte ord under skriving" + "Autofullføring" + "Mellomrom og punktum setter automatisk inn valgt ord" + "Vis innstillingsnøkkel" + "Automatisk" + "Vis alltid" + "Skjul alltid" + + + + "Bigram-forslag" + "Bruk forrige ord til å forbedre forslaget" + + "Ingen" + "Grunnleggende" + "Avansert" + + "%s: Lagret" + "Hold en tast nede for å se aksenterte tegn (ø, ö, osv.)" + "Trykk tilbakeknappen, ↶, for å lukke tastaturet" + "Få tilgang til tall og symboler" + "Trykk lenge på ordet lengst til venstre for å legge det til i ordlisten" + "Trykk på dette hintet for å forsette »" + "Trykk her for å lukke dette hintet og begynne å skrive!" + "Tastaturet åpnes når du tar på et tekstfelt" + "Trykk på og hold nede en tast for å se aksenter"\n"(ø, ö, ô, ó, osv.)" + "Bytt til tall og symboler ved å trykke på denne tasten" + "Gå tilbake til bokstaver igjen ved å trykke på denne tasten" + "Trykk på og hold nede denne tasten for å endre tastaturinnstillinger, som autofullføring" + "Prøv det!" + "Gå" + "Neste" + "Utfør" + "Send" + "?123" + "123" + "ABC" + "ALT" + "Stemmedata" + "Stemmedata håndteres foreløpig ikke på ditt språk, men fungerer på engelsk." + "Talekommandoer er en eksperimentell funksjon som bruker Googles nettverksbaserte talegjenkjenning." + "Gå til innstillinger for tastatur for å slå av stemmedata." + "Du bruker talekommandoer ved å trykke på mikrofonknappen eller skyve fingeren over tastaturet på skjermen." + "Snakk nå" + "Arbeider" + + "Feil. Prøv på nytt." + "Kunne ikke koble til" + "Feil – for mye tale" + "Lydproblem" + "Tjenerfeil" + "Ingen tale høres" + "Ingen treff" + "Talesøk ikke installert" + "Hint:"" Sveip over tastaturet for å snakke" + "Hint:"" Neste gang kan du prøve å tale inn tegnsettingen ved for eksempel å si «punktum», «komma» eller «spørsmålstegn»." + "Avbryt" + "OK" + "Talekommando" + + "På hovedtastatur" + "På talltastatur" + "Av" + + + "Mikrofon på hovedtastatur" + "Mikrofon på talltastatur" + "Talekommando er deaktivert" + + "Send inn automatisk etter tale" + "Trykk Enter automatisk ved søk eller flytting til neste felt." + "Åpne tastaturet"\n\n"Trykk på et tekstfelt." + "Lukke tastaturet"\n\n"Trykk på tilbaketasten." + "Trykk og hold nede en tast for flere valg"\n\n"Få tilgang til skilletegn og aksenter." + "Innstillinger for tastatur"\n\n"Trykk på & hold ""?123""-tasten." + ".no" + ".com" + ".net" + ".org" + ".info" + "Velg inndatametode" + "Inndataspråk" + "Dra fingeren på mellomromstasten for å endre språk" + "Trykk på nytt for å lagre" + "Ordbok tilgjengelig" + "Aktiver brukertilbakemelding" + "Ved å sende bruksstatistikk og programstopprapporter til Google automatisk, hjelper du oss med å gjøre redigeringsfunksjonen for denne inndatametoden enda bedre." + "Trykk for å endre ord" + "Trykk på ord du har skrevet inn, for å endre dem" + "Tastaturtema" + "tastatur" + "stemme" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-nb/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-nb/strings_kp2a.xml new file mode 100644 index 00000000..ef6df9b9 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-nb/strings_kp2a.xml @@ -0,0 +1,20 @@ + + + + Velg en annen oppføring + Velg oppføring + Søke etter oppføringen med \"%1$s\" + Bruker + Passord + Innstillinger for innloggingsdetaljer + Autofyll aktivert + Fyll inn tomme felter automatisk dersom det fins en oppføring for tastaturet til Keepass2Android, og det fins en verdi som samsvarer med feltets hinttekst. + Husk feltenes hinttekster + Dersom feltet fylles manuelt ved å velge en verdi fra Keepass2Android, husk verdien som ble skrevet inn i tekstfeltet. Tekstfeltet vil senere bli gjenkjent av dets hinttekst. + Enkelt tastatur + Vis det enkle 1 rad tastaturet hvis det finnes en oppføring for tastaturet. Hvis deaktivert, vises en dialogboks når Keepass2Android tasten trykkes. + Lås databasen når ferdig + Når du trykker tasten for Ferdig/Send/Gå på det enkle enlinjers tastturet, lås databasen automatisk. + Bytt tastatur når ferdig + Når du trykker tasten for Ferdig/Send/Gå på det enkle enlinjers tastturet, bytt tastatur. + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-nl/bools.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-nl/bools.xml new file mode 100644 index 00000000..897f4b3d --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-nl/bools.xml @@ -0,0 +1,22 @@ + + + + true + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-nl/donottranslate-altchars.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-nl/donottranslate-altchars.xml new file mode 100644 index 00000000..d3beafad --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-nl/donottranslate-altchars.xml @@ -0,0 +1,30 @@ + + + + àáâãäåæ + 3èéêë + ìíîï8 + òóôõöœø9 + ùúûü7 + §ß + ñ + ç + ýÿ6 + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-nl/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-nl/strings.xml new file mode 100644 index 00000000..40c6b3bd --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-nl/strings.xml @@ -0,0 +1,140 @@ + + + + + "Keepass2Android-toetsenbord" + "Instellingen voor Keepass2Android-toetsenbord" + "Invoeropties" + "Trillen bij toetsaanslag" + "Geluid bij toetsaanslag" + "Pop-up bij toetsaanslag" + "Typefouten corrigeren" + "Foutcorrectie tijdens invoer inschakelen" + "Invoerfouten in liggende weergave" + "Foutcorrectie tijdens invoer inschakelen" + "Woordsuggesties" + "Het vorige woord automatisch corrigeren" + "Woordsuggesties" + "Instellingen voor woordsuggesties" + "Automatisch voltooien tijdens typen inschakelen" + "Automatisch voltooien" + "Tekstveld vergroten" + "Woordsuggesties verbergen in liggende weergave" + "Auto-hoofdlettergebruik" + "Hoofdletter gebruiken aan het begin van een zin" + "Automatische interpunctie" + + "Snelle oplossingen" + "Hiermee worden veelvoorkomende typefouten gecorrigeerd" + "Suggesties weergeven" + "Voorgestelde woorden weergeven tijdens typen" + "Auto-aanvullen" + "Gemarkeerd woord automatisch invoegen met spatiebalk en interpunctie" + "Instellingscode weergeven" + "Automatisch" + "Altijd weergeven" + "Altijd verbergen" + + + + "Digram-suggesties" + "Vorig woord gebruiken om suggestie te verbeteren" + + "Geen" + "Basis" + "Geavanceerd" + + "%s: opgeslagen" + "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" + "Blijf drukken op het meest linkse woord om het toe te voegen aan het woordenboek" + "Raak deze tip aan om door te gaan »" + "Raak dit punt aan om deze tip te sluiten en te beginnen met typen." + "Het toetsenbord wordt geopend wanneer u een tekstveld aanraakt" + "Blijf een toets aanraken om diakritische tekens weer te geven"\n"(ø, ö, ô, ó, enzovoort)" + "Schakel over naar cijfers en symbolen door deze toets aan te raken" + "Ga terug naar letters door deze toets nogmaals aan te raken" + "Blijf deze toets aanraken om toetsenbordinstellingen te wijzigen, zoals auto-aanvullen" + "Probeer het zelf!" + "Start" + "Volgende" + "Gereed" + "Verzenden" + "?123" + "123" + "ABC" + "Alt" + "Spraakinvoer" + "Spraakinvoer wordt momenteel niet ondersteund in uw taal, maar is wel beschikbaar in het Engels." + "Spraakinvoer is een experimentele functie met de spraakherkenning van het Google-netwerk." + "Als u spraakinvoer wilt uitschakelen, gaat u naar de toetsenbordinstellingen." + "Als u spraakinvoer gebruikt, drukt u op de microfoonknop of schuift u uw vinger over het schermtoetsenbord." + "Nu spreken" + "Wordt uitgevoerd" + + "Fout. Probeer het opnieuw." + "Kan geen verbinding maken" + "Fout, te lange spraakinvoer." + "Audioprobleem" + "Serverfout" + "Geen spraak te horen" + "Geen resultaten gevonden" + "Spraakgestuurd zoeken is niet geïnstalleerd" + "Hint:"" schuif over het toetsenbord om te spreken" + "Hint:"" spreek de volgende keer interpunctie uit, zoals \'period\' (punt), \'comma\' (komma) of \'question mark\' (vraagteken)." + "Annuleren" + "OK" + "Spraakinvoer" + + "Op hoofdtoetsenbord" + "Op toetsenbord voor symbolen" + "Uit" + + + "Microfoon op hoofdtoetsenbord" + "Microfoon op toetsenbord voor symbolen" + "Spraakinvoer is uitgeschakeld" + + "Automatisch verzenden na spraak" + "Drukt automatisch op Enter tijdens het zoeken of wanneer u naar het volgende veld wilt gaan." + "Het toetsenbord openen"\n\n"Raak een tekstveld aan." + "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" + "Invoermethode selecteren" + "Invoertalen" + "Schuif uw vinger over de spatiebalk om de taal te wijzigen" + "← Raak nogmaals aan om op te slaan" + "Woordenboek beschikbaar" + "Gebruikersfeedback inschakelen." + "Help deze invoermethode te verbeteren door automatisch gebruiksstatistieken en crashmeldingen naar Google te verzenden." + "Raak aan om woorden te corrigeren" + "Raak ingevoerde woorden aan om ze te corrigeren" + "Toetsenbordthema" + "toetsenbord" + "spraak" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-nl/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-nl/strings_kp2a.xml new file mode 100644 index 00000000..0cf38faf --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-nl/strings_kp2a.xml @@ -0,0 +1,20 @@ + + + + Kies een andere regel + Kies regel + Zoek voor regel met \"%1$s\" + Gebruiker + Wachtwoord + Referentie invoer instellingen + Automatisch-vullen ingeschakeld + Vult automatisch tekst in een leeg tekstveld in, als een Keepass2Android regel beschikbaar is voor het toetsenbord en als het veld overeenkomt met de opgeslagen veld hint-tekst. + Onthoud veld hint-teksten + Als een tekst veld gevuld is door handmatig een Keepass2Android waarde te kiezen, onthoud welke KP2A waarde was gebruikt voor het tekst veld. Het tekst veld word later herkend d.m.v. de hint-tekst. + Eenvoudig toetsenbord + Toon het eenvoudige toetsenbord als een KP2A regel beschikbaar is voor het toetsenbord. Wanneer uitgeschakeld, een venster word getoond als de Keepass2Android toets is ingedrukt. + Vergrendel de database na voltooiing + Als de Gedaan/Verzenden/Gaan toets op het eenvoudige toetsenbord is ingedrukt, vergrendel automatisch de database. + Wissel toetsenbord na voltooiing + Als de Gedaan/Verzenden/Gaan toets op het eenvoudige toetsenbord is ingedrukt, verwissel het toetsenbord. + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-nn/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-nn/strings_kp2a.xml new file mode 100644 index 00000000..351dfe74 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-nn/strings_kp2a.xml @@ -0,0 +1,3 @@ + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-pl/bools.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-pl/bools.xml new file mode 100644 index 00000000..897f4b3d --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-pl/bools.xml @@ -0,0 +1,22 @@ + + + + true + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-pl/donottranslate-altchars.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-pl/donottranslate-altchars.xml new file mode 100644 index 00000000..da6b5fd5 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-pl/donottranslate-altchars.xml @@ -0,0 +1,32 @@ + + + + ą + ę3 + ìíîï8 + ó9 + ùúûü7 + ś + ń + ć + ýÿ6 + źż + ł + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-pl/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-pl/strings.xml new file mode 100644 index 00000000..7545335d --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-pl/strings.xml @@ -0,0 +1,140 @@ + + + + + "Klawiatura Keepass2Android" + "Ustawienia klawiatury Keepass2Android" + "Opcje wprowadzania" + "Wibracja przy naciśnięciu" + "Dźwięk przy naciśnięciu" + "Powiększ po naciśnięciu" + "Popraw błędy pisowni" + "Włącz poprawianie błędów wprowadzania" + "Błędy wprowadzania w orientacji poziomej" + "Włącz poprawianie błędów wprowadzania" + "Sugestie słów" + "Automatycznie poprawiaj poprzednie słowo" + "Sugestie słów" + "Ustawienia propozycji słów" + "Włącz autouzupełnianie podczas wpisywania" + "Autouzupełnianie" + "Zwiększ rozmiar pola tekstowego" + "Wyłącz sugestie słów w orientacji poziomej" + "Wstawiaj wielkie litery" + "Zamieniaj na wielką pierwszą literę zdania" + "Automatyczna interpunkcja" + + "Szybkie poprawki" + "Poprawia częste błędy wpisywania" + "Pokaż sugestie" + "Wyświetl sugerowane słowa podczas wpisywania" + "Autouzupełnianie" + "Spacja i znaki przestankowe wstawiają podświetlone słowo" + "Pokaż klawisz ustawień" + "Automatycznie" + "Zawsze pokazuj" + "Zawsze ukrywaj" + + + + "Sugestie dla bigramów" + "Używaj poprzedniego wyrazu, aby polepszyć sugestię" + + "Brak" + "Podstawowy" + "Zaawansowany" + + "%s : Zapisano" + "Przytrzymaj klawisz, aby wyświetlić znaki akcentowane (ą, ó itp.)" + "Naciśnij klawisz cofania ↶, aby zamknąć klawiaturę w dowolnym momencie" + "Przejdź do cyfr i symboli" + "Naciśnij i przytrzymaj słowo po lewej stronie w celu dodania go do słownika" + "Dotknij tej podpowiedzi, aby kontynuować »" + "Dotknij tutaj, aby zamknąć tę podpowiedź i zacząć pisać!" + "Klawiatura jest otwierana po każdym dotknięciu pola tekstowego." + "Dotknij i przytrzymaj klawisz, aby wyświetlić znaki akcentowane"\n"(ą, ę, ł, ó itd.)." + "Przełącz na cyfry i symbole, dotykając tego klawisza." + "Wróć do trybu liter, dotykając ponownie tego klawisza." + "Dotknij i przytrzymaj ten klawisz, aby zmienić ustawienia klawiatury, takie jak autouzupełnianie." + "Wypróbuj!" + "OK" + "Dalej" + "OK" + "Wyślij" + "?123" + "123" + "ABC" + "ALT" + "Wprowadzanie głosowe" + "Wprowadzanie głosowe obecnie nie jest obsługiwane w Twoim języku, ale działa w języku angielskim." + "Wprowadzanie głosowe to funkcja eksperymentalna wykorzystująca funkcję firmy Google umożliwiającą rozpoznawanie mowy przy użyciu sieci." + "Aby wyłączyć wprowadzanie głosowe, przejdź do ustawień klawiatury." + "Aby skorzystać z wprowadzania głosowego, naciśnij przycisk mikrofonu lub przesuń palcem po klawiaturze ekranowej." + "Mów teraz" + "W toku" + + "Błąd. Spróbuj ponownie." + "Nie można nawiązać połączenia" + "Błąd, zbyt długa wypowiedź." + "Problem z dźwiękiem" + "Błąd serwera" + "Nie wykryto mowy" + "Brak wyników" + "Wyszukiwanie głosowe nie jest zainstalowane" + "Wskazówka:"" przesuń palcem po klawiaturze, aby mówić." + "Wskazówka:"" następnym razem spróbuj wypowiadać nazwy znaków interpunkcyjnych: „kropka”, „przecinek” lub „pytajnik”." + "Anuluj" + "OK" + "Wprowadzanie głosowe" + + "Na klawiaturze głównej" + "Na klawiaturze z symbolami" + "Wyłączone" + + + "Mikrofon na klawiaturze głównej" + "Mikrofon na klawiaturze z symbolami" + "Wprowadzanie głosowe jest wyłączone" + + "Automatyczne przesyłanie uruchamiane głosem" + "Podczas wyszukiwania lub przechodzenia do następnego pola automatycznie naciśnij klawisz Enter." + "Otwórz klawiaturę"\n\n"Dotknij dowolnego pola tekstowego." + "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" + "Wybierz sposób wprowadzania tekstu" + "Języki wprowadzania" + "Przesuń palcem po spacji, aby zmienić język" + "← Dotknij ponownie, aby zapisać" + "Słownik dostępny" + "Włącz przesyłanie opinii użytkownika" + "Pomóż ulepszyć edytor wprowadzania tekstu, automatycznie wysyłając do Google statystyki użycia i raporty o awariach." + "Popraw dotknięte słowo" + "Dotknięte słowo zostanie poprawione" + "Motyw klawiatury" + "klawiatura" + "głosowe" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-pl/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-pl/strings_kp2a.xml new file mode 100644 index 00000000..e0cd7338 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-pl/strings_kp2a.xml @@ -0,0 +1,20 @@ + + + + Wybierz inną pozycję + Wybierz pozycję + Wyszukaj pozycję z \"%1$s\" + Użytkownik + Hasło + Ustawienia wprowadzania poświadczeń + Automatyczne wprowadzanie włączone + Automatycznie wypełnij tekstem, jeżeli zostanie wprowadzone puste pole, gdy z klawiatury dostępny jest wpis Keepass2Android i istnieje pole, które odpowiada podpowiedzi pola. + Pamiętaj podpowiedź pola + Jeżeli pole zostało wypełnione ręcznie wybierając pole Keepass2Android, pamiętaj które pole zostało wprowadzone do pola. Pole jest później wykrywane ponownie przez jego podpowiedź. + Prosta klawiatura + Wyświetl prostą 1-wierszową klawiaturę jeżeli wpis jest dostępny dla klawiatury. Jeżeli wyłączone, zostanie wyświetlony dialog gdy przycisk Keepass2Android zostanie wciśnięty. + Zablokuj bazę danych po zakończeniu + Po naciśnięciu klawisza Gotowe/Wyślij/Idź na prostej klawiaturze 1-wierszowej, automatycznie zablokuj bazę danych. + Przełącz klawiaturę po zakończeniu + Po naciśnięciu przycisku Gotowe/Wyślij/Idź na prostej klawiaturze 1-wierszowej, przełącz klawiaturę. + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-pt-rBR/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-pt-rBR/strings_kp2a.xml new file mode 100644 index 00000000..56f47c1f --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-pt-rBR/strings_kp2a.xml @@ -0,0 +1,20 @@ + + + + Selecione outra entrada + Selecione uma entrada + Localizar entrada com \"%1$s\" + Usuário + Senha + Configurações de entrada de credencial + Auto-preenchimento habilitado + Preenche automaticamente um campo vazio quando selecionado, se uma entrada de Keepass2Android estiver disponível para o teclado e houver um valor que coincide com o texto de dica do campo. + Lembrar de textos de dica de campo + Se um campo de texto for preenchido manualmente selecionando um valor de Keepass2Android, lembrar qual valor foi inserido no campo de texto. O campo de texto é detectado novamente pelo seu texto de dica. + Teclado simples + Mostrar o teclado simples de 1 linha se uma entrada estiver disponível para o teclado. Se desabilitado, uma caixa de diálogo é mostrada quando é pressionada a tecla Keepass2Android. + Bloquear banco de dados quando concluído + Ao pressionar a tecla Feito/Enviar/Ir no teclado simples de 1 linha, bloquear automaticamente o banco de dados. + Trocar teclado quando concluído + Ao pressionar a tecla Feito/Enviar/Ir no teclado simples de 1 linha, trocar o teclado. + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-pt-rPT/donottranslate-altchars.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-pt-rPT/donottranslate-altchars.xml new file mode 100644 index 00000000..d3beafad --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-pt-rPT/donottranslate-altchars.xml @@ -0,0 +1,30 @@ + + + + àáâãäåæ + 3èéêë + ìíîï8 + òóôõöœø9 + ùúûü7 + §ß + ñ + ç + ýÿ6 + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-pt-rPT/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-pt-rPT/strings.xml new file mode 100644 index 00000000..6fac966a --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-pt-rPT/strings.xml @@ -0,0 +1,140 @@ + + + + + "Teclado do Keepass2Android" + "Definições de teclado do Keepass2Android" + "Opções de introdução" + "Vibrar ao primir as teclas" + "Som ao premir as teclas" + "Mostrar popup ao premir tecla" + "Corrigir erros de escrita" + "Activar a correcção de erros de entrada" + "Erros de entrada na horizontal" + "Activar a correcção de erros de entrada" + "Sugestões de palavras" + "Corrigir automaticamente a palavra anterior" + "Sugestões de palavras" + "Definições de sugestão de palavras" + "Activar a conclusão automática durante a escrita" + "Conclusão automática" + "Aumentar o tamanho do campo de texto" + "Ocultar sugestões de palavras na vista horizontal" + "Letras maiúsculas automáticas" + "Colocar inicial maiúscula no início de uma frase" + "Pontuação automática" + + "Correcções rápidas" + "Corrige os erros de escrita comuns" + "Mostrar sugestões" + "Apresentar sugestões de palavras ao escrever" + "Conclusão automática" + "A barra de espaços e a pontuação inserem automaticamente uma palavra realçada" + "Mostrar tecla das definições" + "Automático" + "Mostrar sempre" + "Ocultar sempre" + + + + "Sugestões Bigram" + "Utilizar a palavra anterior para melhorar a sugestão" + + "Nenhum" + "Básico" + "Avançados" + + "%s: guardada" + "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" + "Prima e mantenha premida a palavra mais à esquerda para a adicionar ao dicionário" + "Toque nesta sugestão para continuar »" + "Toque aqui para fechar esta sugestão e começar a escrever!" + "O teclado abre quando tocar num campo de texto" + "Mantenha premida uma tecla para ver os acentos"\n"(ø, ö, ô, ó, etc.)" + "Mude para números e símbolos tocando nesta tecla" + "Regresse às letras tocando novamente nesta tecla" + "Mantenha premida esta tecla para alterar definições do teclado, tais como a conclusão automática" + "Experimente!" + "Ir" + "Seguinte" + "Feito" + "Enviar" + "?123" + "123" + "ABC" + "ALT" + "Entrada de voz" + "Actualmente, a entrada de voz não é suportada para o seu idioma, mas funciona em inglês." + "A entrada de voz é uma funcionalidade experimental que utiliza o reconhecimento de voz em rede da Google." + "Para desactivar a entrada de voz, aceda às definições do teclado." + "Para utilizar a entrada de voz, prima o botão do microfone ou deslize o dedo no teclado do ecrã." + "Falar agora" + "A executar" + + "Erro. Tente novamente." + "Não foi possível ligar" + "Erro, discurso demasiado longo." + "Problema de áudio" + "Erro no servidor" + "Nenhuma voz ouvida" + "Não foram encontradas correspondências" + "Pesquisa de voz não instalada" + "Sugestão:"" Deslize no teclado para falar" + "Sugestão:"" Da próxima vez, experimente dizer a pontuação como \"ponto final\", \"vírgula\" ou \"ponto de interrogação\"." + "Cancelar" + "OK" + "Entrada de voz" + + "No teclado principal" + "No teclado de símbolos" + "Desactivada" + + + "Microfone no teclado principal" + "Microfone no teclado de símbolos" + "A entrada de voz está desactivada" + + "Enviar automaticamente depois da voz" + "Premir automaticamente ENTER ao pesquisar ou avançar para o campo seguinte." + "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" + "Seleccionar método de entrada" + "Idiomas de entrada" + "Deslize o dedo pela barra de espaço para alterar o idioma" + "← Toque novamente para guardar" + "Dicionário disponível" + "Activar comentários do utilizador" + "Envie automaticamente estatísticas de utilização e relatórios de falhas para a Google e ajude-nos a melhor este editor de método de introdução." + "Tocar para corrigir palavras" + "Tocar nas palavras introduzidas para as corrigir" + "Tema do teclado" + "teclado" + "voz" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-pt-rPT/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-pt-rPT/strings_kp2a.xml new file mode 100644 index 00000000..67f16418 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-pt-rPT/strings_kp2a.xml @@ -0,0 +1,20 @@ + + + + Selecionar outra entrada + Selecionar entrada + Procurar entrada com \"%1$s\" + Utilizador + Palavra-passe + Definições de introdução de cvredenciais + Auto-preenchimento ativado + Preenche automaticamente o texto ao inserir um campo vazio, se uma entrada de Keepass2Android estiver disponível para o teclado e existir um valor que coincida com a dica do campo. + Memorizar dicas de campo + Se um campo de texto for preenchido manualmente selecionando um valor Keepass2Android, lembra-se o valor que foi inserido no campo de texto. Posteriormente, o campo de texto é detetado novamente pelo seu texto de dica. + Teclado simples + Mostrar teclado simples de 1 linha, se existir uma entrada disponível para o teclado. Se desativada, será mostrada uma caixa de diálogo ao premir a tecla Keepass2Android. + Bloquear base de dados ao terminar + Ao premir a tecla Terminado/Enviar/Ir no teclado de 1 linha, bloquear base de dados automaticamente. + Trocar teclado ao terminar + Ao premir a tecla Terminado/Enviar/Ir no teclado de 1 linha, trocar de teclado. + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-pt/donottranslate-altchars.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-pt/donottranslate-altchars.xml new file mode 100644 index 00000000..d3beafad --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-pt/donottranslate-altchars.xml @@ -0,0 +1,30 @@ + + + + àáâãäåæ + 3èéêë + ìíîï8 + òóôõöœø9 + ùúûü7 + §ß + ñ + ç + ýÿ6 + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-pt/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-pt/strings.xml new file mode 100644 index 00000000..00183f66 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-pt/strings.xml @@ -0,0 +1,140 @@ + + + + + "Teclado Keepass2Android" + "Configurações de teclado Keepass2Android" + "Opções de entrada" + "Vibrar ao tocar a tecla" + "Som ao tocar a tecla" + "Exibir pop-up ao digitar" + "Corrigir erros de digitação" + "Ativar a correção de erro de entrada" + "Erros de entrada de paisagem" + "Ativar a correção de erro de entrada" + "Sugestões de palavra" + "Corrigir automaticamente a palavra anterior" + "Sugestões de palavra" + "Configurações de sugestão de palavra" + "Ativar a conclusão automática durante a digitação" + "Conclusão automática" + "Aumentar o tamanho do arquivo de texto" + "Ocultar sugestões de palavra na visualização da paisagem" + "Capitaliz. automática" + "Colocar em maiúscula o início de uma frase" + "Pontuação automática" + + "Reparos rápidos" + "Corrige erros comuns de digitação" + "Mostrar sugestões" + "Exibir sugestões de palavras durante a digitação" + "Conclusão automática" + "Barra de espaço e pontuação inserem a palavra destacada" + "Mostrar tecla de config." + "Automático" + "Mostrar sempre" + "Sempre ocultar" + + + + "Sugestões de bigrama" + "Usar palavra anterior para melhorar a sugestão" + + "Nenhum" + "Básico" + "Avançado" + + "%s : Salvo" + "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" + "Pressione e segure a palavra mais à esquerda para adicioná-la ao dicionário" + "Toque nesta dica para continuar »" + "Toque aqui para fechar esta dica e começar a digitar!" + "O teclado abre toda vez que você tocar em um campo de texto" + "Tocar e segurar uma tecla para visualizar acentos"\n"(ø, ö, ô, ó e assim por diante)" + "Alternar para números e símbolos tocando nessa tecla" + "Voltar às letras tocando novamente nessa tecla" + "Tocar e segurar esta tecla para alterar as configurações do teclado, como a conclusão automática" + "Experimente!" + "Ir" + "Avançar" + "Feito" + "Enviar" + "?123" + "123" + "ABC" + "ALT" + "Entrada de voz" + "A entrada de voz não é suportada no momento para o seu idioma, mas funciona em inglês." + "A entrada de voz é um recurso experimental que usa o reconhecimento de fala de rede do Google." + "Para desativar a entrada de voz, vá para as configurações do teclado." + "Para usar a entrada de voz, pressione o botão com o microfone ou deslize o dedo sobre o teclado na tela." + "Fale agora" + "Trabalhando" + + "Erro. Tente novamente." + "Não foi possível conectar" + "Erro, fala muito longa." + "Problema com o áudio" + "Erro do servidor" + "Nenhuma fala ouvida" + "Não há resultados compatíveis" + "A pesquisa por voz não está instalada" + "Dica:"" Deslize sobre o teclado para falar" + "Dica:"" Da próxima vez, tente falar o nome da pontuação como \"ponto\", \"vírgula\" ou \"ponto de interrogação\"." + "Cancelar" + "OK" + "Entrada de voz" + + "No teclado principal" + "No teclado de símbolos" + "Desativado" + + + "Microfone no teclado principal" + "Microfone no teclado de símbolos" + "Entrada de voz desativada" + + "Enviar automaticamente depois de falar" + "Pressione Enter automaticamente ao pesquisar ou ir para o próximo campo." + "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" + "Selecionar método de entrada" + "Idiomas de entrada" + "Deslize o dedo na barra de espaços para alterar o idioma" + "← Toque novamente para salvar" + "Dicionário disponível" + "Ativar comentário do usuário" + "Ajude a melhorar este editor de método de entrada enviando automaticamente ao Google estatísticas de uso e relatórios de falhas." + "Tocar para corrigir" + "Toque as palavras para corrigi-las" + "Tema do teclado" + "teclado" + "voz" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-rm/donottranslate-altchars.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-rm/donottranslate-altchars.xml new file mode 100644 index 00000000..f17026fa --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-rm/donottranslate-altchars.xml @@ -0,0 +1,30 @@ + + + + àáâãäåæ + 3èéêë + ìíîï8 + òóöôõœø9 + ùúûü7 + §ß + ñ + ç + ýÿ6 + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-rm/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-rm/strings.xml new file mode 100644 index 00000000..0c5d21dc --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-rm/strings.xml @@ -0,0 +1,148 @@ + + + + + "Tastatura Keepass2Android" + "Parameters da la tastatura Keepass2Android" + + + "Vibrar cun smatgar in buttun" + "Tun cun smatgar in buttun" + "Pop-up cun smatgar ina tasta" + "Curreger sbagls d\'endataziun" + "Activar la correctura da sbagls d\'endataziun" + "Sbagls d\'endataziun en il format orizontal" + "Activar la correctura da sbagls d\'endataziun" + "Propostas da pleds" + "Curreger automaticamain il pled precedent" + "Propostas da pleds" + "Parameters da las propostas per pleds" + "Activar la cumplettaziun automatica durant l\'endataziun" + "Cumplettaziun automatica" + "Engrondir il champ da text" + "Zuppentar propostas da pleds en il format orizontal" + "Maiusclas automaticas" + "Scriver grond l\'entschatta da mintga frasa" + "Interpuncziun automatica" + + "Correcturas sveltas" + "Curregia sbagls da tippar currents" + "Mussar las propostas" + "Mussar pleds proponids durant l\'endataziun" + "Cumplettaziun automatica" + "Inserir auto. il pled marcà cun la tasta da vid/interpuncziun" + + + + + + + + + + + + "Propostas da tip bigram" + "Meglierar la proposta cun agid dal pled precedent" + + "Nagin" + "Simpel" + "Avanzà" + + "%s : Memorisà" + "\"Tegnair smatgà per mussar ils accents (à, é, etc.)\"" + "Smatgar ↶ per serrar la tastatura" + "Acceder a cifras e simbols" + "Smatgar ditg sin il pled dal tut a sanestra per l\'agiuntar al dicziunari" + "Tutgar quest commentari per cuntinuar »" + "\"Tutgar qua, per serrar quest commentari e cumenzar a tippar!\"" + "La tastatura vegn adina averta sche Vus tutgais in champ da text." + "\"""Tegnai smatgà ina tasta per mussar ils segns spezials"\n"(ø, ö, ô, ó etc.).""\"" + "Midai a numers e simbols cun tutgar quest buttun." + "Turnai a letras cun smatgar danovamain quest buttun." + "\"""Tegnai smatgà quest buttun per midar ils parameters da tastatura, sco p. ex. la cumplettaziun automatica.""\"" + "Empruvai!" + "Dai" + "Vinavant" + "Finì" + "Trametter" + "?123" + "123" + "ABC" + "ALT" + "Cumonds vocals" + "\"Cumonds vocals en Vossa lingua na vegnan actualmain betg sustegnids, ma la funcziun è disponibla per englais.\"" + "Ils cumonds vocals èn ina funcziunalitad experimentala che utilisescha la renconuschientscha vocala da rait da Google." + "\"Per deactivar ils cumonds vocals, avri ils parameters da tastatura.\"" + "\"Per utilisar ils cumonds vocals, smatgai il buttun dal microfon u stritgai cun il det sur la tastatura dal visur.\"" + "Ussa discurrer" + "Operaziun en progress" + + "Errur. Empruvai anc ina giada." + "Impussibel da connectar." + "Errur - discurrì memia ditg." + "Problem audio" + "Errur dal server" + "Betg udì ina frasa vocala" + "Betg chattà correspundenzas" + "Betg installà la tschertga vocala" + "Commentari:"" Stritgai cun il det sur la tastatura per discurrer." + "\"""Commentari:"" Empruvai la proxima giada d\'agiuntar segns d\'interpuncziun sco \"\"punct\"\", \"\"comma\"\" u \"\"segn da dumonda\"\" cun cumonds vocals.\"" + "Interrumper" + "OK" + "Cumonds vocals" + + "Sin la tastatura principala" + "Sin la tastatura da simbols" + "Deactivà" + + + "Microfon sin la tastatura principala" + "Microfon sin la tastatura da simbols" + "Ils cumonds vocals èn deactivads" + + "Trametter automaticamain suenter il cumond vocal" + "Smatgai sin la tasta enter sche Vus exequis ina tschertga u siglis al proxim champ." + "Avrir la tastatura"\n\n"Tutgai inqual champ da text." + "\"""Serrar la tastatura"\n\n"Smatgai il buttun \"\"Enavos\"\".\"" + "Tutgar e tegnair smatgà in buttun per acceder a las opziuns"\n\n"Accedi a segns d\'interpuncziun ed accents." + "Parameters da tastatura"\n\n"Tutgai e tegnai smatgà il buttun ""?123""." + ".com" + ".net" + ".org" + ".gov" + ".edu" + + + "Linguas da cumonds vocals" + "Stritgar cun il det sur la tasta da vid per midar la lingua" + "← Tippar danovamain per memorisar" + "Dicziunari disponibel" + "Activar il feedback da l\'utilisader" + "Gidai a meglierar quest editur da la metoda d\'endataziun cun trametter automaticamain datas statisticas davart l\'utilisaziun e rapports da collaps a Google." + + + + + "Design da la tastatura" + "tastatura" + "vusch" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ro/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ro/strings.xml new file mode 100644 index 00000000..580f50dd --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ro/strings.xml @@ -0,0 +1,140 @@ + + + + + "Tastatură Keepass2Android" + "Setările tastaturii Keepass2Android" + "Opţiuni de introducere text" + "Vibrare la apăsarea tastei" + "Sunet la apăsarea tastei" + "Fereastră pop-up la apăsarea tastei" + "Corectaţi erorile de dactilografiere" + "Activaţi corectarea erorii de intrare" + "Erori de introducere în modul peisaj" + "Activaţi corectarea erorii de intrare" + "Sugestii de cuvinte" + "Corecţie automată a cuvântului anterior" + "Sugestii de cuvinte" + "Setările sugestiei de cuvinte" + "Activaţi completarea automată în timpul introducerii textului" + "Completare automată" + "Măriţi dimensiunea câmpului text" + "Ascundeţi sugestiile de cuvinte în vizualizarea de tip peisaj" + "Auto-capitalizare" + "Doresc să se scrie cu majusculă începutul propoziţiilor" + "Punctuaţie automată" + + "Remedieri rapide" + "Corectează greşelile introduse frecvent" + "Afişaţi sugestiile" + "Afişare sugestii de cuvinte în timpul introducerii de text" + "Completare automată" + "Bara de spaţiu şi punctuaţia inserează automat un cuvânt evidenţiat" + "Afişaţi tasta setări" + "Automat" + "Afişaţi întotdeauna" + "Ascundeţi întotdeauna" + + + + "Sugestii pentru cuvinte de două litere" + "Utilizaţi cuvântul anterior pentru a îmbunătăţi sugestia" + + "Niciunul" + "De bază" + "Avansat" + + "%s: salvat" + "Ţineţi o tastă apăsată pentru a vedea accentele (ø, ö, etc.)" + "Apăsaţi tasta Înapoi ↶ pentru a închide oricând tastatura" + "Accesaţi numere şi simboluri" + "Apăsaţi şi ţineţi apăsat pe cuvântul cel mai din stânga, pentru a-l adăuga la dicţionar" + "Atingeţi acest indiciu pentru a continua »" + "Atingeţi aici pentru a închide acest indiciu şi începeţi să introduceţi text!" + "Tastatura se deschide de fiecare dată când atingeţi un câmp text" + "Atingeţi şi ţineţi apăsată o tastă pentru a vizualiza accentele"\n"(ø, ö, ô, ó etc.)" + "Comutaţi între numere şi simboluri atingând această tastă" + "Reveniţi la litere prin atingerea acestei taste din nou" + "Apăsaţi şi ţineţi apăsată această tastă pentru a schimba setările tastaturii, cum ar fi completarea automată" + "Încercaţi!" + "OK" + "Înainte" + "Terminat" + "Trimiteţi" + "?123" + "123" + "ABC" + "ALT" + "Intrare voce" + "Intrarea vocală nu este acceptată în prezent pentru limba dvs., însă funcţionează în limba engleză." + "Intrarea vocală este o funcţie experimentală ce utilizează recunoaşterea vocală în reţea oferită de Google." + "Pentru a dezactiva intrarea vocală, accesaţi setările tastaturii." + "Pentru a utiliza intrarea vocală, apăsaţi butonul de microfon sau glisaţi degetul de-a lungul tastaturii de pe ecran." + "Vorbiţi acum" + "Se analizează" + + "Eroare. Încercaţi din nou." + "Conectare imposibilă" + "Eroare, discurs prea lung." + "Problemă audio" + "Eroare de server" + "Nu s-a auzit vorbirea" + "Nicio potrivire" + "Căutarea vocală nu este instalată" + "Indiciu:"" glisaţi de-a lungul tastaturii pentru a vorbi" + "Indiciu:"" data viitoare, încercaţi să rostiţi şi punctuaţia, cum ar fi „punct”, „virgulă”, sau „semn de întrebare”." + "Anulaţi" + "OK" + "Intrare voce" + + "Pe tastatura principală" + "Pe tastatura de simboluri" + "Dezactivat" + + + "Microfon pe tastatura principală" + "Microfon pe tastatura de simboluri" + "Intrarea vocală este dezactivată" + + "Trimitere automată după intrarea vocală" + "Apăsaţi automat tasta Enter atunci când se face o căutare sau când se trece la câmpul următor." + "Deschideţi tastatura"\n\n"Atingeţi orice câmp de text." + "Închideţi tastatura"\n\n"Apăsaţi pe tasta Înapoi." + "Atingeţi şi ţineţi apăsată o tastă pentru opţiuni"\n\n"Accesaţi punctuaţia şi accentele." + "Setările tastaturii"\n\n"Atingeţi şi ţineţi apăsată tasta ""?123""." + ".com" + ".net" + ".org" + ".gov" + ".edu" + "Selectaţi metoda de introducere a textului" + "Selectaţi limba" + "Glisaţi degetul pe bara de spaţiu pentru a schimba limba" + "← Atingeţi din nou pentru a salva" + "Dicţionar disponibil" + "Activaţi feedback de la utilizatori" + "Ajutaţi la îmbunătăţirea acestui instrument de editare a metodelor de introducere a textului trimiţând în mod automat la Google statistici de utilizare şi rapoarte de blocare." + "Atingeţi pentru a corecta cuvintele" + "Atingeţi cuvintele introduse pentru a le corecta" + "Temă pentru tastatură" + "tastatură" + "voce" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ro/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ro/strings_kp2a.xml new file mode 100644 index 00000000..df9110c5 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ro/strings_kp2a.xml @@ -0,0 +1,20 @@ + + + + Selectaţi o altă înregistrare + Alegeți înregistrarea + Căutaţi înregistrarea \"%1$s\" + Utilizator + Parolă + Setări pentru introducerea datelor + Completarea-auto activată + Completează automat când un câmp gol este selectat, dacă o înregistrare Keepass2Android este disponibilă pentru tastatură și există o valoare care corespunde textului sugestie al câmpului. + Memorează textul de sugestie al câmpurilor + Dacă un câmp text este completat prin selectarea manuală a valorii Keepass2Android, memorează valoarea care era introdusă în câmpul de text. Câmpul de text este redetectat mai târziu de textul său de sugestie. + Tastatură simplă + Arată tastatura simplă de un rând dacă o înregistrare este disponibilă pentru tastatură. Dacă este dezactivat, se afișează un dialog când tasta Keepass2Android este apăsată. + Blochează baza de date când ai terminat + Când apeși tasta Done/Send/Go de pe tastatura simplă de un rând, blochează automat baza de date. + Comută tastatura când ai terminat + După ce ai apăsat tasta Gata/Trimite/Mergi de pe tastatura simplă cu un rând, comută tastatura. + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ru/donottranslate-altchars.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ru/donottranslate-altchars.xml new file mode 100644 index 00000000..46241a62 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ru/donottranslate-altchars.xml @@ -0,0 +1,32 @@ + + + + àáâãäåæ + èéêë + ìíîï + òóôõöœø + ùúûü + §ß + ñ + ç + ýÿ + ё5 + ъ + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ru/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ru/strings.xml new file mode 100644 index 00000000..8d4b0b95 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ru/strings.xml @@ -0,0 +1,140 @@ + + + + + "Клавиатура Keepass2Android" + "Настройки клавиатуры Keepass2Android" + "Параметры ввода" + "Виброотклик клавиш" + "Звук клавиш" + "Увеличение нажатых" + "Исправлять опечатки" + "Включить исправление ошибок при вводе" + "Ошибки при вводе в горизонтальной ориентации" + "Включить исправление ошибок при вводе" + "Предложение слов" + "Автоматически исправлять предыдущее слово" + "Предложение слов" + "Настройки подсказок" + "Включить автоматическое завершение слов при вводе" + "Автоматическое завершение" + "Увеличить размер текстового поля" + "Скрывать предложение слов в горизонтальной ориентации" + "Заглавные автоматически" + "Делать заглавной первую букву предложения" + "Автопунктуация" + + "Быстрое исправление" + "Исправлять распространенные опечатки" + "Предлагать варианты" + "Предлагать варианты слов во время ввода" + "Автозавершение" + "При нажатии пробела вставлять предложенное слово" + "Кнопка настроек" + "Автоматически" + "Всегда показывать" + "Всегда скрывать" + + + + "Биграммные подсказки" + "Используйте предыдущее слово, чтобы исправить подсказку" + + "Нет" + "Основной" + "Дополнительно" + + "%s: сохранено" + "Удерживайте клавишу, чтобы увидеть варианты с диакритическими знаками (ø, ö и т.д.)" + "Нажмите клавишу \"Назад\" ↶, чтобы закрыть клавиатуру в любой момент" + "Открыть цифры и символы" + "Нажмите и удерживайте слово слева, чтобы добавить его в словарь" + "Чтобы продолжить, нажмите на эту подсказку »" + "Нажмите здесь, чтобы закрыть подсказку и начать вводить текст." + "Клавиатура появляется автоматически при касании текстового поля" + "Нажмите и удерживайте клавишу для отображения вариантов с диакритическими знаками "\n"(ø, ö, ô, ó и т. п.)" + "Для переключения между вводом цифр и символов используйте эту клавишу" + "Чтобы вернуться к буквенной клавиатуре, снова нажмите на эту клавишу" + "Чтобы изменить настройки клавиатуры (такие как автозавершение), нажмите и удерживайте эту клавишу" + "Попробуйте!" + "Поиск" + "Далее" + "Готово" + "Отправить" + "?123" + "123" + "АБВ" + "ALT" + "Голосовой ввод" + "В настоящее время функция голосового ввода не поддерживает ваш язык, но вы можете пользоваться ей на английском." + "Голосовой ввод – экспериментальная функция на основе технологии сетевого распознавания речи от Google." + "Функция голосового ввода отключается в настройках клавиатуры." + "Чтобы использовать голосовой ввод, нажмите кнопку микрофона или проведите пальцем по экранной клавиатуре." + "Говорите" + "Обработка запроса" + + "Ошибка. Повторите попытку." + "Ошибка подключения" + "Слишком длинная фраза" + "Неполадка со звуком" + "Ошибка сервера" + "Речи не слышно" + "Соответствий не найдено" + "Голосовой поиск не установлен" + "Совет"". Проведите пальцем по клавиатуре для голосового ввода." + "Совет"". В следующий раз проговаривайте знаки препинания, например \"точка\", \"запятая\", \"вопросительный знак\"." + "Отмена" + "ОК" + "Голосовой ввод" + + "Значок на основной клавиатуре" + "Значок на клавиатуре символов" + "Отключить голосовой ввод" + + + "Значок на основной клавиатуре" + "Значок на клавиатуре символов" + "Голосовой ввод отключен" + + "Автоматически отправлять по окончании голосового ввода" + "Автоматически нажимать \"Ввод\" при поиске или переходе к следующему полю." + "Открытие клавиатуры"\n\n"Нажмите на любое текстовое поле." + "Закрытие клавиатуры"\n\n"Нажмите клавишу \"Назад\"." + "Нажмите и удерживайте клавишу для вызова параметров"\n\n"Доступ к пунктуационным и диакритическим знакам." + "Настройки клавиатуры"\n\n"Нажмите и удерживайте клавишу ""?123""." + ".com" + ".net" + ".org" + ".gov" + ".edu" + "Выбрать способ ввода" + "Языки ввода" + "Для изменения языка проведите пальцем по пробелу" + "← Нажмите еще раз, чтобы сохранить" + "Доступен словарь" + "Включить отправку сведений" + "Помогите усовершенствовать редактор способа ввода, разрешив отправку статистики и отчетов о сбоях в Google." + "Исправление нажатием" + "Нажмите на слово, чтобы исправить его" + "Вид клавиатуры" + "клавиатура" + "голосовой" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ru/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ru/strings_kp2a.xml new file mode 100644 index 00000000..9f95c31a --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-ru/strings_kp2a.xml @@ -0,0 +1,21 @@ + + + + Выбрать другую запись + Выбрать запись + Поиск записи с \"%1$s\" + Пользователь + Пароль + Параметры ввода учетных данных + Автозаполнение включено + Автоматически заполняет текст при входе в пустое поле, если запись Keepass2Android доступна для клавиатуры и есть значение, соответствующее тексту подсказки для поля. + Запоминать тексты подсказки для полей + При ручном заполнении текстового поля выбором значения Keepass2Android запоминает, какое значение было введено в текстовое поле. +Текстовое поле в дальнейшем будет определено по его тексту подсказки. + Простая клавиатура + Показать простую 1-рядную клавиатуру, если элемент доступен для клавиатуры. Если отключено, диалоговое окно отображается при нажатии клавиши Keepass2Android. + Блокировать базу данных после завершения + При нажатии клавиши Готово/Отправить/Перейти на простой 1-рядной клавиатуре, автоматически блокировать базу данных. + Сменить клавиатуру после завершения + При нажатии клавиши Готово/Отправить/Перейти на простой 1-рядной клавиатуре сменить клавиатуру. + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-sk/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-sk/strings.xml new file mode 100644 index 00000000..32019362 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-sk/strings.xml @@ -0,0 +1,140 @@ + + + + + "Klávesnica Keepass2Android" + "Nastavenia klávesnice Keepass2Android" + "Možnosti zadávania textu a údajov" + "Pri stlačení klávesu vibrovať" + "Zvuk pri stlačení klávesu" + "Zobraziť znaky pri stlačení klávesu" + "Opravovať preklepy" + "Povoliť opravu chýb vstupu" + "Chyby vstupu v zobrazení na šírku" + "Povoliť opravu chýb vstupu" + "Návrhy slov" + "Automaticky opraviť predchádzajúce slovo" + "Návrhy slov" + "Nastavenia návrhov slov" + "Povoliť automatické dokončovanie pri písaní" + "Automatické dokončovanie" + "Zväčšiť textové pole" + "Skryť návrhy slov v zobrazení na šírku" + "Veľké písmená automaticky" + "Začať vetu veľkým písmenom" + "Automatická interpunkcia" + + "Rýchle opravy" + "Opravuje najčastejšie chyby pri písaní" + "Zobraziť návrhy" + "Zobrazovať navrhované slová počas písania" + "Automatické dokončovanie" + "Stlačením medzerníka alebo interpunkčného znamienka automaticky vložíte zvýraznené slovo." + "Zobraziť kláves Nastavenia" + "Automaticky" + "Vždy zobrazovať" + "Vždy skrývať" + + + + "Návrh Bigram" + "Na zlepšenie návrhu použiť predchádzajúce slovo" + + "Žiadne" + "Základné" + "Rozšírené" + + "%s : Uložené" + "Podržaním klávesu zobrazíte diakritiku (á, ž atď.)" + "Stlačením klávesu Späť ↶ môžete klávesnicu kedykoľvek zavrieť." + "Prístup k číslam a symbolom" + "Stlačením a podržaním slova úplne vľavo toto slovo pridáte do slovníka." + "Ak chcete pokračovať, dotknite sa tohto tipu »" + "Ak chcete tento tip zavrieť a začať písať, dotknite sa tu." + "Klávesnica sa otvorí vždy, keď sa dotknete textového poľa." + "Pridržaním klávesu zobrazíte diakritiku"\n"(ó, ø, ö, ô apod.)" + "Ak chcete prepnúť na režim zadávania číslic a symbolov, dotknite sa tohto klávesu." + "Ak chcete prejsť späť na zadávanie písmen, dotknite sa znova tohto klávesu." + "Pridržaním tohto klávesu zmeníte nastavenia klávesnice (napr. automatické dokončovanie)." + "Skúste si to." + "Hľadať" + "Ďalej" + "Hotovo" + "Odoslať" + "?123" + "123" + "ABC" + "ALT" + "Hlasový vstup" + "Pre váš jazyk aktuálne nie je hlasový vstup podporovaný, ale funguje v angličtine." + "Hlasový vstup je experimentálna funkcia, ktorá využíva sieťové rozpoznanie reči spoločnosti Google." + "Ak chcete vypnúť hlasový vstup, prejdite na nastavenia klávesnice." + "Ak chcete použiť hlasový vstup, stlačte tlačidlo mikrofónu alebo prejdite prstom po klávesnici na obrazovke." + "Hovorte" + "Prebieha spracovanie" + + "Chyba. Skúste to znova." + "Pripojenie sa nepodarilo." + "Chyba, reč je príliš dlhá." + "Problém so zvukom" + "Chyba servera" + "Nebola zistená žiadna reč." + "Nenašli sa žiadne zhody" + "Hlasové vyhľadávanie nie je nainštalované" + "Tip:"" Ak chcete aktivovať hlasový vstup, prejdite prstom po klávesnici." + "Tip:"" Nabudúce skúste vysloviť interpunkciu, napríklad „bodka“, „čiarka“ alebo „otáznik“." + "Zrušiť" + "OK" + "Hlasový vstup" + + "Na hlavnej klávesnici" + "Na klávesnici so symbolmi" + "Vypnuté" + + + "Mikrofón na hlavnej klávesnici" + "Mikrofón na klávesnici so symbolmi" + "Hlasový vstup je zakázaný" + + "Po hlasovom vstupe automaticky odoslať" + "Pri vyhľadávaní alebo prechode na ďalšie pole automaticky stlačiť kláves Enter." + "Otvorte klávesnicu"\n\n"Dotknite sa ľubovoľného textového poľa." + "Zatvorte klávesnicu"\n\n"Stlačte tlačidlo Späť." + "Dotknutím a pridržaním klávesu zobrazíte možnosti"\n\n"Prístup k interpunkčným znamienkam a diakritike." + "Nastavenia klávesnice"\n\n"Dotknite sa klávesu ""?123"" a podržte ho." + ".com" + ".sk" + ".org" + ".net" + ".eu" + "Výber metódy vstupu" + "Jazyky vstupu" + "Jazyk môžete zmeniť posunutím prsta po medzerníku." + "← Ďalším dotykom slovo uložíte" + "K dispozícii je slovník" + "Povoliť spätnú väzbu od používateľov" + "Automatickým zasielaním štatistík o využívaní editora metódy vstupu a správ o jeho zlyhaní do služby Google môžete prispieť k vylepšeniu tohto nástroja." + "Dotykom opravíte slová" + "Dotykom zadaným slov ich opravíte" + "Motív klávesnice" + "klávesnica" + "hlasová" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-sk/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-sk/strings_kp2a.xml new file mode 100644 index 00000000..cd580cc3 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-sk/strings_kp2a.xml @@ -0,0 +1,20 @@ + + + + Vybrať ďalší záznam + Vybrať záznam + Vyhľadať záznam s \"%1$s\" + Používateľ + Heslo + Nastavenia zadávania údajov + Autom. dopĺňanie zap. + Pri vstupe do prázdneho políčka automaticky doplniť text, ak je dostupný záznam Keepass2Android pre klávesnicu a aj pole ktoré je v zhode s pomocným textom pre pole. + Pamätať si nápovedu poľa + Ak je textové pole vyplnené manuálnym vybraním hodnoty Keepass2Android, pamätať si hodnotu zadanú do poľa. Textové pole bude neskôr detegované podľa pomocného textu. + Jednoduchá klávesnica + Ak je dostupný záznam pre klávesnicu, zobraziť klávesnicu s 1 riadkom. Ak je vypnutá, pri stlačení tlač. Keepass2Android sa zobrazí dialóg. + Po skončení uzamknúť datab. + Automaticky uzamknúť databázu po stlačení tlač. Hotovo/Odoslať/Prejsť na 1-riadkovej klávesnici. + Po skončení prepnúť kláv. + Prepnúť klávesnicu naspäť po stlačení tlačidla Hotovo/Odoslať/Prejsť na 1-riadkovej klávesnici. + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-sl/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-sl/strings.xml new file mode 100644 index 00000000..b8e030c2 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-sl/strings.xml @@ -0,0 +1,140 @@ + + + + + "Tipkovnica Keepass2Android" + "Nastavitve tipkovnice Keepass2Android" + "Možnosti vnosa" + "Vibriranje ob pritisku tipke" + "Zvok ob pritisku tipke" + "Pojavno okno ob pritisku tipke" + "Popravljanje tipkarskih napak" + "Omogoči popravljanje napak pri vnosu" + "Napake pri vnosu v ležečem položaju" + "Omogoči popravljanje napak pri vnosu" + "Predlogi besed" + "Samodejno popravi prejšnjo besedo" + "Predlogi besed" + "Nastavitve za predlaganje besede" + "Omogoči samodokončanje med tipkanjem" + "Samodokončanje" + "Povečaj velikost besedilnega polja" + "Skrij predloge besed v ležečem pogledu" + "Samodejne velike začetnice" + "Napiši začetek stavka z veliko začetnico" + "Samodejno vstavljanje ločil" + + "Hitri popravki" + "Popravi pogoste tipkarske napake" + "Pokaži predloge" + "Prikaži predlagane besede med tipkanjem" + "Samodokončanje" + "Preslednica in ločila samodejno vnesejo označeno besedo" + "Pokaži tipko za nastavitve" + "Samodejno" + "Vedno pokaži" + "Vedno skrij" + + + + "Bigramni predlogi" + "Predlog izboljšaj s prejšnjo besedo" + + "Brez" + "Osnovni" + "Dodatno" + + "%s: shranjeno" + "Držite tipko, da prikažete poudarke (ø, ö itd.)" + "Kadar koli lahko pritisnete tipko »Nazaj« ↶, da zaprete tipkovnico" + "Dostop do številk in simbolov" + "Če besedo želite dodati v slovar, jo pridržite" + "Dotaknite se tega nasveta za nadaljevanje »" + "Dotaknite se tukaj, da zaprete nasvet in začnete tipkati!" + "Tipkovnice se odpre, kadar se dotaknete besedilnega polja" + "Za ogled poudarkov pridržite tipko"\n"(ø, ö, ô, ó itd.)" + "Preklopite na številke in simbole z dotikom te tipke" + "Na črke se vrnete, če se še enkrat dotaknete te tipke" + "Pridržite to tipko, če želite spremeniti nastavitve tipkovnice, npr. samodokončanje" + "Poskusite!" + "Pojdi" + "Naprej" + "Dokončano" + "Pošlji" + "?123" + "123" + "ABC" + "ALT" + "Glasovni vnos" + "Glasovni vnos trenutno ni podprt v vašem jeziku, deluje pa v angleščini." + "Glasovni vnos je poskusna funkcija, ki uporablja Googlovo omrežno prepoznavanje govora." + "Če želite izklopiti glasovni vnos, pojdite na nastavitve tipkovnice." + "Če želite uporabiti glasovni vnos, pritisnite gumb z mikrofonom ali podrsajte s prstom po zaslonski tipkovnici." + "Začnite govoriti" + "Obdelava" + + "Napaka. Poskusite znova." + "Povezava ni mogoča" + "Napaka, preveč govora." + "Težave z zvokom" + "Napaka strežnika" + "Govora se ne sliši" + "Ni rezultatov" + "Glasovno iskanje ni nameščeno" + "Nasvet:"" za govorjenje s prstom povlecite po tipkovnici" + "Nasvet:"" naslednjič poskusite ločila izgovoriti, npr. »pika«, »vejica« ali »vprašaj«." + "Prekliči" + "V redu" + "Glasovni vnos" + + "Na glavni tipkovnici" + "Na tipkovnici s simboli" + "Izklopljeno" + + + "Mikrofon na glavni tipkovnici" + "Mikrofon na tipkovnici s simboli" + "Glasovni vnos je onemogočen" + + "Samodejno pošlji po govoru" + "Samodejno pritisni »Enter« pri iskanju ali prehodu na naslednje polje." + "Odprite tipkovnico"\n\n"Dotaknite se katerega koli besedilnega polja." + "Zaprite tipkovnico"\n\n"Pritisnite tipko »Nazaj«." + "Pridržite tipko za ogled možnosti"\n\n"Dostop do ločil in poudarkov." + "Nastavitve "\n\n"Pridržite tipko ""?123""." + ".com" + ".net" + ".org" + ".gov" + ".edu" + "Izberite način vnosa" + "Jeziki vnosa" + "Podrsajte s prstom po preslednici, da zamenjate jezik" + "← Še enkrat se dotaknite, da shranite" + "Slovar je na voljo" + "Omogoči povratne informacije uporabnikov" + "S samodejnim pošiljanjem statističnih podatkov o uporabi in poročil o zrušitvah Googlu nam lahko pomagate izboljšati urejevalnik načina vnosa." + "Dotaknite se besed in jih popravite" + "Dotaknite se vnesenih besed in jih popravite" + "Tema tipkovnice" + "tipkovnica" + "govor" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-sl/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-sl/strings_kp2a.xml new file mode 100644 index 00000000..80f2b8ce --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-sl/strings_kp2a.xml @@ -0,0 +1,20 @@ + + + + Izberite drug vnos + Izberite vnos + Poišči vnos s/z \"%1$s\" + Uporabnik + Geslo + Nastavitve za vnos poveril + Sam. izpolnjevanje omog. + Samodejno izpolni besedilo, ko izbrano prazno polje, če je za tipkovnico na voljo vnos Keepass2Android in obstaja vrednost, ki se ujema z besedilom namiga polja. + Zap. si bes. namigov polj + Če je besedilo izpolnjeno z ročno izbiro vrednosti Keepass2Android, si zapomni, katera vrednost je bila vnesena v besedilno polje. To polje kasneje ponovno zazna njegovo besedilo namiga. + Preprosta tipkovnica + Prikaži preprosto enovrstično tipkovnico, če je za tipkovnico vnos na voljo vnos. Če je onemogočeno, se ob pritisku na tipko Keepass2Android prikaže pogovorno okno. + Zak. pod. zbirko, ko je kon. + Ob pritisku na tipko Končano/Pošlji/Pojdi na preprosti enovrstični tipkovnici samodejno zakleni podatkovno zbirko. + Pre. tipk., ko je končano + Ob pritisku na tipko Končano/Pošlji/Pojdi na preprosti enovrstični tipkovnici preklopi tipkovnico. + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-sr/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-sr/strings.xml new file mode 100644 index 00000000..99c63b64 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-sr/strings.xml @@ -0,0 +1,140 @@ + + + + + "Keepass2Android тастатура" + "Подешавања Keepass2Android тастатуре" + "Опције уноса" + "Вибрирај на притисак тастера" + "Звук на притисак тастера" + "Искачући прозор приликом притиска тастера" + "Исправи грешке у куцању" + "Омогућавање исправљања грешака током уноса" + "Грешке приликом уноса у положеном приказу" + "Омогућавање исправљања грешака током уноса" + "Предлагање речи" + "Аутоматско исправљање претходне речи" + "Предлагање речи" + "Подешавања за предлагање речи" + "Омогућавање аутоматског довршавања током уноса текста" + "Аутоматско довршавање" + "Повећај величину поља за текст" + "Скривање предложених речи у положеном приказу" + "Аутоматски унос великих слова" + "Унос великог слова на почетку реченице" + "Аутоматска интерпункција" + + "Брзе исправке" + "Исправља честе грешке у куцању" + "Прикажи предлоге" + "Приказивање предложених речи током уноса текста" + "Аутоматско довршавање" + "Означена реч се аутоматски умеће када притиснете размак или знак интерпункције" + "Прикажи тастер за подешавања" + "Аутоматски" + "Увек прикажи" + "Увек сакриј" + + + + "Bigram предлози" + "Користи претходну реч за побољшање предлога" + + "Ништа" + "Основни" + "Напредно" + + "%s : Сачувано" + "Држите тастер да бисте видели акценте (ø, ö итд.)" + "Притисните тастер „Назад“ ↶ у било ком тренутку да бисте затворили тастатуру" + "Приступите бројевима и симболима" + "Притисните и држите прву реч са леве стране да бисте је додали у речник" + "Додирните овај савет да бисте наставили »" + "Додирните овде да бисте затворили овај савет и почели да уносите текст!" + "Тастатура се отвара сваки пут када додирнете поље за текст" + "Додирните и држите тастер да бисте видели акценте"\n"(ø, ö, ô, ó, и тако даље)" + "Пређите на бројеве и симболе тако што ћете додирнути овај тастер" + "Вратите се на слова тако што ћете поново додирнути овај тастер" + "Додирните и држите овај тастер да бисте променили подешавања тастатуре, као што је аутоматско довршавање" + "Пробајте!" + "Иди" + "Следеће" + "Готово" + "Пошаљи" + "?123" + "123" + "ABC" + "ALT" + "Гласовни унос" + "Гласовни унос тренутно није подржан за ваш језик, али функционише на енглеском." + "Гласовни унос је експериментална функција која користи Google-ово мрежно препознавање гласа." + "Да бисте искључили гласовни унос, идите на подешавања тастатуре." + "Да бисте користили гласовни унос, притисните дугме за микрофон или превуците прст преко тастатуре на екрану." + "Говорите сада" + "Обрада" + + "Грешка. Покушајте поново." + "Повезивање није могуће" + "Грешка, говорите предуго." + "Проблем са звуком" + "Грешка сервера" + "Не чује се говор" + "Нема подударања" + "Гласовна претрага није инсталирана" + "Савет:"" Превуците прстом преко тастатуре за гласовни унос" + "Савет:"" Следећи пут покушајте да изговорите знакове интерпункције као што су „тачка“, „зарез“ или „знак питања“." + "Откажи" + "Потврди" + "Гласовни унос" + + "На главној тастатури" + "На тастатури са симболима" + "Искључено" + + + "Микрофон на главној тастатури" + "Микрофон на тастатури са симболима" + "Гласовни унос је онемогућен" + + "Аутоматски пошаљи после гласа" + "Аутоматски притисак на enter приликом претраге или преласка на следеће поље." + "Активирање тастатуре"\n\n"Додирните било које поље за текст." + "Затварање тастатуре"\n\n"Притисните тастер „Назад“." + "Додирните и држите тастер да би се приказале опције"\n\n"Приступ знаковима интерпункције и акцентима." + "Подешавања тастатуре"\n\n"Додирните и држите тастер ""?123""." + ".com" + ".net" + ".org" + ".gov" + ".edu" + "Изаберите метод уноса" + "Језици за унос" + "Превуците прст преко тастера за размак да бисте променили језик" + "← Поново додирните да бисте сачували" + "Речник је доступан" + "Омогући повратну информацију корисника" + "Помозите да се побољша овај уређивач режима уноса тако што ће се аутоматски послати статистика о коришћењу и извештаји о грешкама компанији Google." + "Додирните да бисте исправили речи" + "Додирните унете речи да бисте их исправили" + "Тема тастатуре" + "тастатура" + "глас" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-sr/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-sr/strings_kp2a.xml new file mode 100644 index 00000000..0fb28b48 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-sr/strings_kp2a.xml @@ -0,0 +1,3 @@ + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-sv/donottranslate-altchars.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-sv/donottranslate-altchars.xml new file mode 100644 index 00000000..4d26e6c4 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-sv/donottranslate-altchars.xml @@ -0,0 +1,38 @@ + + + + áàâąã + 3éèêëę€ + íìîï8 + óòôõ9 + úùûū7 + śšşß + ńñň + çćč + ýÿü6 + ðď + ř4 + ťþ5 + źžż + ł + w + æ + øœ + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-sv/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-sv/strings.xml new file mode 100644 index 00000000..2b98ffe8 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-sv/strings.xml @@ -0,0 +1,140 @@ + + + + + "Keepass2Androids tangentbord" + "Inställningar för Keepass2Androids tangentbord" + "Inmatningsalternativ" + "Vibrera vid tangenttryck" + "Knappljud" + "Popup vid knapptryck" + "Rätta skrivfel" + "Aktivera rättning av felaktiga inmatningar" + "Inmatningsfel i liggande vy" + "Aktivera rättning av felaktiga inmatningar" + "Ordförslag" + "Rätta automatiskt föregående ord" + "Ordförslag" + "Inställningar för ordförslag" + "Aktivera Komplettera automatiskt när du skriver" + "Komplettera automatiskt" + "Gör textfältet större" + "Dölj ordförslag i liggande vy" + "Automatiska versaler" + "Använd versal i början av mening" + "Automatiska punkter" + + "Snabba lösningar" + "Åtgärdar automatiskt vanliga misstag" + "Visa förslag" + "Visar ordförslag när du skriver" + "Komplettera automatiskt" + "Blanksteg och punkt infogar automatiskt markerat ord" + "Visa inställningsknapp" + "Automatiskt" + "Visa alltid" + "Dölj alltid" + + + + "Bigramförslag" + "Förbättra förslaget med föregående ord" + + "Inget" + "Grundinställningar" + "Avancerade" + + "%s: sparat" + "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" + "Tryck och håll ned ordet längst till vänster om du vill lägga till det i ordlistan" + "Tryck på tipset för att fortsätta »" + "Tryck här om du vill stänga tipset och börja skriva!" + "Tangentbordet öppnas när du trycker på ett textfält" + "Tryck och håll nere en tangent om du vill visa accenter"\n"(ø, ö, ô, ó och så vidare)" + "Växla till siffror och symboler med den här tangenten" + "Återvänd till bokstäver genom att trycka på tangenten en gång till" + "Tryck och håll ned tangenten om du vill ändra inställningarna för tangentbordet, till exempel Komplettera automatiskt" + "Testa!" + "Kör" + "Nästa" + "Färdig" + "Skicka" + "?123" + "123" + "ABC" + "ALT" + "Röstindata" + "Röstindata stöds inte på ditt språk än, men tjänsten fungerar på engelska." + "Röstinmatning är en funktion på experimentstadiet som använder Googles nätverks taligenkänning." + "Om du vill stänga av röstindata öppnar du inställningarna för tangentbordet." + "Om du vill använda röstinmatning trycker du på mikrofonknappen eller drar fingret över tangentbordet på skärmen." + "Tala nu" + "Fungerar" + + "Fel. Försök igen." + "Det gick inte att ansluta" + "Fel, för mycket tal." + "Ljudproblem" + "Serverfel" + "Hörde inget tal" + "Inga träffar hittades" + "Voice Search är inte installerat" + "Tips!"" Dra över tangentbordet om du vill tala" + "Tips!"" Nästa gång testar du att säga skiljetecknen, som \"punkt\", \"komma\" eller \"frågetecken\"." + "Avbryt" + "OK" + "Röstindata" + + "På huvudtangentbordet" + "På symboltangentbordet" + "Av" + + + "Mikrofon på huvudtangentbordet" + "Mikrofon på symboltangentbordet" + "Röstindata är inaktiverat" + + "Skicka automatiskt efter röst" + "Tryck automatiskt på retur vid sökning eller när du fortsätter till nästa fält." + "Ö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" + "Välj inmatningsmetod" + "Inmatningsspråk" + "Dra med fingret på blanksteg om du vill ändra språk" + "← Tryck igen för att spara" + "En ordlista är tillgänglig" + "Aktivera synpunkter från användare" + "Du kan hjälpa till att förbättra inmatningsmetoden genom att automatiskt skicka användningsstatistik och felrapporter till Google." + "Tryck om du vill korrigera ord" + "Tryck på skrivna ord om du vill korrigera dem" + "Tangentbordstema" + "tangentbord" + "röst" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-sv/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-sv/strings_kp2a.xml new file mode 100644 index 00000000..6c12cfd7 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-sv/strings_kp2a.xml @@ -0,0 +1,13 @@ + + + + Välj en annan post + Välj post + Sök efter post med \"%1$s\" + Användare + Lösenord + Auto-ifyllning aktiverad + Enkelt tangentbord + Lås databasen när jag är klar + Växla tangentbord när jag är klar + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-th/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-th/strings.xml new file mode 100644 index 00000000..783c1149 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-th/strings.xml @@ -0,0 +1,140 @@ + + + + + "แป้นพิมพ์ Keepass2Android" + "การตั้งค่าแป้นพิมพ์ Keepass2Android" + "ตัวเลือกการป้อนข้อมูล" + "สั่นเมื่อกดปุ่ม" + "ส่งเสียงเมื่อกดปุ่ม" + "ป๊อปอัปเมื่อกดแป้น" + "แก้ไขข้อผิดพลาดในการพิมพ์" + "เปิดการใช้งานการแก้ไขข้อผิดพลาดในการป้อนข้อมูล" + "ข้อผิดพลาดในการป้อนข้อมูลแนวนอน" + "เปิดการใช้งานการแก้ไขข้อผิดพลาดในการป้อนข้อมูล" + "การแนะนำคำ" + "แก้ไขคำก่อนหน้าอัตโนมัติ" + "การแนะนำคำ" + "การตั้งค่าการแนะนำคำ" + "เปิดใช้งานการเติมคำอัตโนมัติขณะพิมพ์" + "เติมคำอัตโนมัติ" + "เพิ่มขนาดฟิลด์ข้อความ" + "ซ่อนการแนะนำคำในมุมมองแนวนอน" + "ปรับเป็นตัวพิมพ์ใหญ่อัตโนมัติ" + "ใช้ตัวพิมพ์ใหญ่เมื่อขึ้นต้นประโยค" + "ใส่เครื่องหมายวรรคตอนอัตโนมัติ" + + "แก้ไขด่วน" + "แก้ไขข้อผิดพลาดในการพิมพ์ที่พบบ่อย" + "แสดงคำแนะนำ" + "แสดงคำที่แนะนำขณะพิมพ์" + "เติมคำอัตโนมัติ" + "ใช้แป้นเคาะวรรคและเครื่องหมายวรรคตอนเพื่อแทรกคำที่ไฮไลต์โดยอัตโนมัติ" + "แสดงแป้นการตั้งค่า" + "อัตโนมัติ" + "แสดงตลอดเวลา" + "ซ่อนตลอดเวลา" + + + + "คำแนะนำ Bigram" + "ใช้คำก่อนหน้านี้เพื่อปรับปรุงคำแนะนำ" + + "ไม่มี" + "พื้นฐาน" + "ขั้นสูง" + + "%s : บันทึกแล้ว" + "กดปุ่มค้างไว้เพื่อดูการออกเสียง (ø, ö, ฯลฯ)" + "กดปุ่ม ย้อนกลับ เพื่อปิดแป้นพิมพ์เมื่อใดก็ได้" + "เข้าถึงหมายเลขและสัญลักษณ์" + "กดคำซ้ายสุดค้างไว้เพื่อเพิ่มลงในพจนานุกรม" + "แตะคำแนะนำนี้เพื่อทำงานต่อ »" + "แตะที่นี่เพื่อปิดคำแนะนำนี้และเริ่มพิมพ์!" + "แป้นพิมพ์จะเปิดขึ้นเมื่อคุณแตะฟิลด์ข้อความ" + "แตะปุ่มค้างไว้เพื่อดูการออกเสียง"\n"(ø, ö, ô, ó และอื่นๆ)" + "เปลี่ยนเป็นตัวเลขและสัญลักษณ์เมื่อแตะปุ่มนี้" + "กลับไปที่ตัวอักษรโดยการแตะปุ่มนี้อีกครั้ง" + "แตะปุ่มนี้ค้างไว้เพื่อเปลี่ยนการตั้งค่าแป้นพิมพ์ เช่น การเติมคำอัตโนมัติ" + "ลองดูสิ!" + "ไป" + "ถัดไป" + "เสร็จสิ้น" + "ส่ง" + "?123" + "123" + "ABC" + "ALT" + "การป้อนข้อมูลด้วยเสียง" + "ขณะนี้การป้อนข้อมูลด้วยเสียงยังไม่ได้รับการสนับสนุนในภาษาของคุณ แต่ใช้ได้ในภาษาอังกฤษ" + "การป้อนข้อมูลด้วยเสียงเป็นคุณลักษณะทดลองที่ใช้การจดจำเสียงที่มีการสร้างเครือข่ายไว้ของ Google" + "หากต้องการปิดการป้อนข้อมูลด้วยเสียง ไปที่การตั้งค่าแป้นพิมพ์" + "หากต้องการใช้การป้อนข้อมูลด้วยเสียง กดปุ่มไมโครโฟนหรือเลื่อนนิ้วผ่านแป้นพิมพ์บนหน้าจอ" + "พูดได้เลย" + "กำลังทำงาน" + + "ข้อผิดพลาด โปรดลองอีกครั้ง" + "ไม่สามารถเชื่อมต่อได้" + "ข้อผิดพลาด คำพูดยาวเกินไป" + "ปัญหาด้านเสียง" + "ข้อผิดพลาดของเซิร์ฟเวอร์" + "ไม่ได้ยินเสียง" + "ไม่พบรายการที่ตรงกัน" + "ไม่ได้ติดตั้ง Voice Search" + "คำแนะนำ:"" กวาดผ่านแป้นพิมพ์เพื่อพูด" + "คำแนะนำ:"" ครั้งต่อไป ให้ลองเอ่ยถึงเครื่องหมายวรรคตอน เช่น \"มหัพภาค\" \"จุลภาค\" หรือ \"เครื่องหมายคำถาม\"" + "ยกเลิก" + "ตกลง" + "การป้อนข้อมูลด้วยเสียง" + + "บนแป้นพิมพ์หลัก" + "บนแป้นพิมพ์สัญลักษณ์" + "ปิด" + + + "ไมโครโฟนบนแป้นพิมพ์หลัก" + "ไมโครโฟนบนแป้นพิมพ์สัญลักษณ์" + "การป้อนข้อมูลด้วยเสียงถูกปิดการใช้งาน" + + "ส่งอัตโนมัติหลังบันทึกเสียง" + "กด Enter อัตโนมัติเมื่อค้นหาหรือไปที่ฟิลด์ถัดไป" + "เปิดแป้นพิมพ์"\n\n"แตะฟิลด์ข้อความใดก็ได้" + "ปิดแป้นพิมพ์"\n\n"กดปุ่ม ย้อนกลับ" + "แตะปุ่มค้างไว้เพื่อดูตัวเลือก "\n\n"เข้าถึงเครื่องหมายวรรคตอนและการออกเสียง" + "การตั้งค่าแป้นพิมพ์"\n\n"แตะปุ่ม ""?123""ค้างไว้" + ".com" + ".net" + ".org" + ".gov" + ".edu" + "เลือกวิธีการป้อนข้อมูล" + "ภาษาในการป้อนข้อมูล" + "เลื่อนนิ้วไปบนแป้นเคาะวรรคเพื่อเปลี่ยนภาษา" + "← แตะอีกครั้งเพื่อบันทึก" + "มีพจนานุกรมให้ใช้งาน" + "เปิดใช้งานการแสดงความคิดเห็นจากผู้ใช้" + "ช่วยปรับปรุงตัวแก้ไขวิธีการป้อนข้อมูลนี้โดยการส่งสถิติการใช้งานและรายงานการขัดข้องถึง Google โดยอัตโนมัติ" + "แตะเพื่อแก้ไขคำ" + "แตะคำที่ป้อนไว้เพื่อแก้ไข" + "ชุดรูปแบบแป้นพิมพ์" + "แป้นพิมพ์" + "เสียง" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-tl/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-tl/strings.xml new file mode 100644 index 00000000..d8e46d49 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-tl/strings.xml @@ -0,0 +1,140 @@ + + + + + "Keepass2Android keyboard" + "Mga setting ng Keepass2Android keyboard" + "Mga pagpipilian sa input" + "Mag-vibrate sa keypress" + "Tunog sa keypress" + "Popup sa keypress" + "Itama ang mga error sa pag-type" + "Paganahin ang pagtatama ng error sa pag-input" + "Mga error sa pag-input ng landscape" + "Paganahin ang pagtatama ng error sa pag-input" + "Mga suhestiyon ng salita" + "Awtomatikong itama ang nakaraang salita" + "Mga suhestiyon ng salita" + "Mga setting ng suhestiyon ng salita" + "Paganahin ang awtomatikong pagkumpleto habang nagta-type" + "Awtomatikong pagkumpleto" + "Taasan ang laki ng field ng teksto" + "Itago ang mga suhestiyon ng salita sa lanscape na view" + "Auto-capitalization" + "I-capitalize ang simula ng isang pangungusap" + "I-auto-punctuate" + + "Mga mabilisang pagsasaayos" + "Itinatama ang mga karaniwang na-type na mali" + "Ipakita ang mga suhestiyon" + "Ipakita ang mga iminumungkahing salita habang nagta-type" + "I-auto-complete" + "Awtomatikong ipinapasok ng spacebar at bantas ang naka-highlight na salita" + "Ipakita ang key ng mga setting" + "Awtomatiko" + "Palaging ipakita" + "Palaging itago" + + + + "Mga Suhestiyon na Bigram" + "Gamitin ang nakaraang salita upang pahusayin ang suhestiyon" + + "Wala" + "Batayan" + "Advanced" + + "%s : Na-save" + "Pinduting nang matagal ang isang key pababa upang makita ang mga accent (ø, ö, atbp.)" + "Pindutin ang key na bumalik ↶ upang isara ang keyboard anumang oras" + "I-access ang mga numero at simbolo" + "Pindutin nang matagal ang salita sa kaliwang bahagi upang idagdag ito sa diksyunaryo" + "Galawin ang pahiwatig na ito upang magpatuloy »" + "Galawin dito upang isara ang pahiwatig na ito at simulan ang pag-type!" + "Nagbubukas ang keyboard anumang oras na galawin mo ang field ng teksto" + "Galawin & pinduting nang matagal ang isang key upang tingnan ang mga accent"\n"(ø, ö, ô, ó, at iba pa)" + "Lumipat sa mga numero at simbolo sa pamamagitan ng paggalaw sa key na "" na ito" + "Pumunta muli sa mga titik sa pamamagitan ng muling paggalaw sa key na ito" + "Galawin & pinduting nang matagal ang key na ito upang baguhin ang mga setting ng keyboard, tulad ng awtomatikong pagkumpleto" + "Subukan ito!" + "Punta" + "Susunod" + "Tapos na" + "Ipadala" + "?123" + "123" + "ABC" + "ALT" + "Pag-input ng boses" + "Hindi kasalukuyang suportado ang pag-input ng boses para sa iyong wika, ngunit gumagana sa Ingles." + "Ang pag-input ng boses ay isang tampok na pang-eksperimento na gumagamit ng naka-network na pagkilala sa pananalita ng Google." + "Upang i-off ang pag-input ng boses, pumunta sa mga setting ng keyboard." + "Upang gumamit ng pag-input ng boses, pindutin ang pindutang microphone o i-slide ang iyong daliri sa screen keyboard." + "Magsalita ngayon" + "Nagtatrabaho" + + "Error. Pakisubukang muli." + "Hindi makakonekta" + "Error, masyadong maraming pananalita." + "Problema sa audio" + "Error sa server" + "Walang narinig na pananalita" + "Walang nakitang mga tugma" + "Hindi naka-install ang paghahanap ng boses" + "Pahiwatig:"" Mag-swipe sa keyboard upang magsalita" + "Pahiwatig:"" Sa susunod, subukang magsalita ng bantas tulad ng \"tuldok\", \"kuwit\", o \"tandang pananong\"." + "Kanselahin" + "OK" + "Pag-input ng boses" + + "I-on ang pangunahing keyboard" + "Sa mga simbolo ng keyboard" + "Naka-off" + + + "Mic sa pangunahing keyboard" + "Mic sa keyboard ng mga simbolo" + "Hindi pinagana ang pag-input ng boses" + + "Awtomatikong isumite pagkatapos ng boses" + "Awtomatikong pindutin ang enter kapag naghahanap o pupunta sa susunod na field." + "Buksan ang keyboard"\n\n"Galawin ang kahit anong field ng teksto." + "Isara ang keyboard"\n\n"Pindutin ang key na Bumalik." + "Galawin & pinduting nang matagal ang isang key para sa mga pagpipilian"\n\n"I-access ang bantas at mga accent." + "Mga setting ng keyboard"\n\n"Galawin & pindutin nang matagal ang ""?123"" na key." + ".com" + ".net" + ".org" + ".gov" + ".edu" + "Pumili ng paraan ng pag-input" + "Mag-input ng mga wika" + "I-slide ang daliri sa spacebar upang palitan ang wika" + "← Pinduting muli upang i-save" + "Available ang diksyunaryo" + "Paganahin ang feedback ng user" + "Tumulong na pahusayin ang editor ng paraan ng pag-input na ito sa pamamagitan ng awtomatikong pagpapadala ng mga istatistika ng paggamit at mga ulat ng crash sa Google." + "Pindutin upang itama ang mga salita" + "Pindutin ang mga ipinasok na salita upang itama ang mga ito" + "Tema ng Keyboard" + "keyboard" + "boses" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-tr/donottranslate-altchars.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-tr/donottranslate-altchars.xml new file mode 100644 index 00000000..fb2419c1 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-tr/donottranslate-altchars.xml @@ -0,0 +1,31 @@ + + + + â + 3 + īįíìïîı8 + ōøõóòœôö9 + ūúùûü7 + śşßš + + čćç + 6 + ğ + \ No newline at end of file diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-tr/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-tr/strings.xml new file mode 100644 index 00000000..1649a13e --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-tr/strings.xml @@ -0,0 +1,140 @@ + + + + + "Keepass2Android klavyesi" + "Keepass2Android klavye ayarları" + "Giriş seçenekleri" + "Tuşa basıldığında titret" + "Tuşa basıldığında ses çıkar" + "Tuşa basıldığında pop-up aç" + "Yazım hatalarını düzelt" + "Giriş hatası düzeltmeyi etkinleştir" + "Yatay giriş hataları" + "Giriş hatası düzeltmeyi etkinleştir" + "Kelime önerileri" + "Önceki kelimeyi otomatik olarak düzelt" + "Kelime önerileri" + "Kelime önerme ayarları" + "Yazarken otomatik tamamlamayı etkinleştir" + "Otomatik tamamlama" + "Metin alanı boyutunu artır" + "Yatay görünümde kelime önerilerini gizle" + "Otomatik olarak büyük harf yap" + "Cümlenin baş harfini büyük yap" + "Otomatik noktalama" + + "Hızlı onarımlar" + "Yaygın olarak yapılan yazım hatalarını düzeltir" + "Önerileri göster" + "Yazarken önerilen kelimeleri görüntüle" + "Otomatik tamamla" + "Boşluk tuşu ve noktalama vurgulanan kelimeyi otomatik ekler" + "Ayarları göster tuşu" + "Otomatik" + "Her zaman göster" + "Her zaman gizle" + + + + "Bigram Önerileri" + "Öneriyi geliştirmek için önceki kelimeyi kullanın" + + "Yok" + "Temel" + "Gelişmiş" + + "%s : Kaydedildi" + "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" + "Sözlüğe eklemek için en soldaki kelimeye basın ve basılı tutun" + "Devam etmek için bu ipucuna dokunun »" + "Bu ipucunu kapatmak için buraya dokunun ve yazmaya başlayın!" + "Bir metin alanına dokunduğunuzda klavye açılır" + "Vurguları görüntülemek için bir tuşa basın ve basılı tutun"\n"(ø, ö, ô, ó v.b.)" + "Bu tuşa dokunarak sayılar ve simgeler arasında geçiş yap" + "Bu tuşa tekrar dokunarak harflere geri dönün" + "Otomatik tamamlama gibi klavye ayarlarını değiştirmek için bu tuşa basın ve basılı tutun" + "Deneyin!" + "Git" + "İleri" + "Bitti" + "Gönder" + "?123" + "123" + "ABC" + "ALT" + "Ses girişi" + "Ses girişi, şu anda sizin diliniz için desteklenmiyor ama İngilizce dilinde kullanılabilir." + "Ses girişi, Google\'ın ağ bağlantılı ses tanıma işlevini kullanan deneysel bir özelliktir." + "Ses girişini kapatmak için klavye ayarlarına gidin." + "Ses girişini kullanmak için mikrofon düğmesine basın veya parmağınızı dokunmatik klavye üzerinde kaydırın." + "Şimdi konuşun" + "Çalışıyor" + + "Hata. Lütfen tekrar deneyin." + "Bağlanamadı" + "Hata, çok uzun konuşma." + "Ses sorunu" + "Sunucu hatası" + "Konuşma duyulmadı" + "Eşleşme bulunamadı" + "Sesle arama yüklenmedi" + "İpucu:"" Konuşmak için parmağınızı klavye üzerinde kaydırın" + "İpucu:"" Sonraki sefer, \"nokta\", \"virgül\" veya \"soru işareti\" gibi noktalama işaretlerini telaffuz etmeyi deneyin." + "İptal" + "Tamam" + "Ses girişi" + + "Ana klavyede" + "Simge klavyesinde" + "Kapalı" + + + "Ana klavyedeki mikrofon" + "Simge klavyesindeki mikrofon" + "Sesle giriş devre dışı bırakıldı" + + "Sesten sonra otomatik gönder" + "Arama yaparken veya bir sonraki alana giderken enter tuşuna otomatik olarak basın." + "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" + "Giriş yöntemini seç" + "Giriş dilleri" + "Dili değiştirmek için parmağınızı boşluk çubuğu üzerinde kaydırın" + "← Kaydetmek için tekrar dokunun" + "Sözlük kullanılabilir" + "Kullanıcı geri bildirimini etkinleştir" + "Kullanım istatistiklerini ve kilitlenme raporlarını Google\'a otomatik olarak göndererek bu giriş yöntemi düzenleyicisinin iyileştirilmesine yardımcı olun." + "Kelimeleri düzeltmek için dokunun" + "Düzeltmek için, girilen kelimelere dokunun" + "Klavye Teması" + "klavye" + "ses" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-tr/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-tr/strings_kp2a.xml new file mode 100644 index 00000000..8f47826c --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-tr/strings_kp2a.xml @@ -0,0 +1,14 @@ + + + + Başka bir kayıt seçin + Kayıt seçin + Kayıt \"%1$s\" ile arama + Kullanıcı + Şifre + Giriş kimlik bilgisi ayarları + Otomatik doldurma etkin + Basit klavye + İşiniz bittiğinde veritabanı kilitlensin + İşiniz bittiğinde klavyeyi değiştir + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-uk/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-uk/strings.xml new file mode 100644 index 00000000..2d6b3fbc --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-uk/strings.xml @@ -0,0 +1,140 @@ + + + + + "Клавіатура Keepass2Android" + "Налашт-ня клавіат. Keepass2Android" + "Парам. введення" + "Вібр при натиску клав." + "Звук при натиску клав." + "Сплив. при нат.клав." + "Виправ. помилки вводу" + "Увімкн. виправл. помилок вводу" + "Помилки альбомного вводу" + "Увімкн. виправл. помилок вводу" + "Пропозиції слів" + "Автоматично виправляти попереднє слово" + "Пропозиції слів" + "Налашт-ня пропозицій слів" + "Увімкн. автозаповнення при вводі" + "Автозаповнення" + "Збільш. розмір текст. поля" + "Сховати пропозиції слів в альбом. режимі" + "Авто викор. вел. літер" + "Поч. писати речення з великої літери" + "Авто пунктуація" + + "Шв. виправлення" + "Виправляє поширені помилки" + "Показати пропозиції" + "Відображати при вводі пропоновані слова" + "Автозаповнення" + "Пробіл і пунктуація автоматично вставляє виділене слово" + "Показ. клав. налашт." + "Автоматично" + "Завжди показ." + "Завжди ховати" + + + + "Двобуквені пропозиції" + "Викор. попер. слово для покращ. пропозиції" + + "Немає" + "Базовий" + "Розшир." + + "%s : збережено" + "Утр. клав. натис., щоб див. нагол. (ø, ö, тощо)" + "Натисн. клавішу назад ↶, щоб будь-коли закрити клавіат." + "Доступ до цифр і символів" + "Натисн. і утримуйте ліве крайнє слово, щоб додати його до словн." + "Натис. цю підказку для продовж.»" + "Натисн. тут, щоб закрити цю підказку і почати ввод." + "Клавіатура відривається при торканні текстового поля" + "Натис. і утрим. клавішу для перегл. наголосів"\n"(ø, ö, ô, ó тощо)" + "Перемк. до цифр і символів, натиснувши цю кнопку " + "Поверніться до літер, знову натиснувши цю клавішу" + "Натис. і утрим. клавішу, щоб змін. налашт-ння клавіат., такі як автозапов." + "Спробуйте!" + "Іти" + "Далі" + "Готово" + "Надісл." + "?123" + "123" + "ABC" + "ALT" + "Голос. ввід" + "Голос. ввід наразі не підтрим. для вашої мови, але можна користуватися англійською." + "Голос. ввід є експеремент. ф-цією, яка викор. мережеве розпізнавання голосу Google." + "Щоб вимкн. голос ввід, йдіть до налашт-нь клавіатури." + "Щоб викор. голос. ввід, натисніть кнопку мікрофона або пересуньте палець на екранній клавіатурі." + "Диктуйте" + "Працює" + + "Помилка. Спробуйте ще раз." + "Неможл. під\'єднатися" + "Помилка. Забагато продикт." + "Проблема з аудіо" + "Помилка сервера" + "Не чути диктув." + "Збігів не знайдено" + "Голос. пошук не встановлено" + "Підк:"" горт. на клавіат., щоб продикт." + "Підказка:"" наступного разу продикт. знаки пункт. такі як \"крапка\", \"кома\" чи \"знак пит\"." + "Скасувати" + "OK" + "Голос. ввід" + + "На осн. клавіатурі" + "Символьна клавіатура" + "Вимк." + + + "Miкр. на осн. клавіатурі" + "Miкр. на символ. клавіатурі" + "Голос. ввід вимкнуто" + + "Авто подав. після гол. пош." + "Автомат. натиск. enter під час пошуку або переходу до наступного поля." + "Відкр. клавіатуру"\n\n"Натисн. якесь текст. поле." + "Закрити клавіатуру"\n\n"Натисн. клавішу Назад." + "Натис.і утрим. клавішк для отрим. парам."\n\n"Доступ до пункт. та наголос." + "Налашт-ння клавіатури"\n\n"Натисн. і утрим. клавішу ""?123" + ".com" + ".net" + ".org" + ".gov" + ".edu" + "Вибрати метод введення" + "Мови вводу" + "Переміст. палець на пробіл, щоб змін. мову" + "← Торкн. ще, щоб збер." + "Словник доступний" + "Увімк. відгуки корист." + "Допоможіть покращ. редактор методу введ., автомат. надсилаючи в Google статистику використ. та звіти про збої." + "Торкн., щоб виправ. слова" + "Торкн. введених слів, щоб виправити їх" + "Тема клавіатури" + "клавіатура" + "голос." + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-uk/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-uk/strings_kp2a.xml new file mode 100644 index 00000000..27ea1536 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-uk/strings_kp2a.xml @@ -0,0 +1,20 @@ + + + + Вибрати інший запис + Вибрати запис + Пошук запису з \'%1$s\' + Користувач + Пароль + Налаштування вводу облікових даних + Автозаповнення увімкнуте + Автоматично заповнює текст, коли введене порожнє поле, якщо запис Keepass2Android є доступним для клавіатури та існує значення, що відповідає тексту підказки поля. + Запам\'ятати тексти підказки для полів + Якщо текстове поле заповнене значенням Keepass2Android, що було вибране вручну, запам\'ятовувати, яке значення було введене в текстове поле. Наступного разу це поле буде визначене за його текстом підказки. + Проста клавіатура + Показувати просту 1-рядну клавіатуру, якщо запис є доступним для клавіатури. Якщо вимкнено, відкривається діалог, коли натискається кнопка Keepass2Android. + Блокувати базу даних після завершення + При натисканні кнопки Виконано/Відправити/Перейти на простій 1-рядній клавіатурі, автоматично блокувати базу даних. + Змінити клавіатуру після завершення + При натисканні кнопки Виконано/Відправити/Перейти на простій 1-рядній клавіатурі, змінити клавіатуру. + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-vi/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-vi/strings.xml new file mode 100644 index 00000000..95bc268a --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-vi/strings.xml @@ -0,0 +1,140 @@ + + + + + "Bàn phím Keepass2Android" + "Cài đặt bàn phím Keepass2Android" + "Tùy chọn nhập" + "Rung khi nhấn phím" + "Âm thanh khi nhấn phím" + "Cửa sổ bật lên khi nhấn phím" + "Sửa lỗi đánh máy" + "Bật sửa lỗi nhập" + "Lỗi nhập theo khổ ngang" + "Bật sửa lỗi nhập" + "Đề xuất từ" + "Tự động sửa từ trước đó" + "Đề xuất từ" + "Cài đặt đề xuất từ" + "Bật tự động hoàn tất khi nhập" + "Tự động hoàn tất" + "Tăng kích cỡ trường văn bản" + "Ẩn đề xuất từ trong chế độ xem ngang" + "Tự động viết hoa" + "Viết hoa chữ cái đầu câu" + "Tự động chấm câu" + + "Sửa nhanh" + "Sửa lỗi nhập thông thường" + "Hiển thị đề xuất" + "Hiển thị từ được đề xuất khi nhập" + "Tự động hoàn tất" + "Dấu cách và dấu câu tự động chèn vào từ được đánh dấu" + "Hiển thị phím cài đặt" + "Tự động" + "Luôn hiển thị" + "Luôn ẩn" + + + + "Đề xuất Bigram" + "Sử dụng từ trước đó để cải tiến đề xuất" + + "Không" + "Cơ bản" + "Nâng cao" + + "%s : Đã lưu" + "Giữ phím xuống để xem dấu trọng âm (ø, ö, v.v...)" + "Nhấn phím quay lại ↶ để đóng bàn phím bất kỳ lúc nào" + "Truy cập các số và ký hiệu" + "Nhấn và giữ từ ngoài cùng bên trái để thêm từ đó vào từ điển" + "Chạm vào gợi ý này để tiếp tục »" + "Chạm vào đây để đóng gợi ý này và bắt đầu nhập" + "Bàn phím mở ra bất cứ khi nào bạn chạm vào trường văn bản" + "Chạm & giữ phím để xem dấu trọng âm"\n"(ø, ö, ô, ó, v.v...)" + "Chuyển sang số và ký hiệu bằng cách chạm vào phím này" + "Quay lại các chữ cái bằng cách chạm vào phím này lần nữa" + "Chạm & giữ phím này để thay đổi cài đặt bàn phím, như tự động hoàn tất" + "Hãy dùng thử!" + "Đến" + "Tiếp theo" + "Xong" + "Gửi" + "?123" + "123" + "ABC" + "ALT" + "Nhập liệu bằng giọng nói" + "Nhập liệu bằng giọng nói hiện không được hỗ trợ cho ngôn ngữ của bạn nhưng hoạt động với ngôn ngữ tiếng Anh." + "Nhập liệu bằng giọng nói là tính năng thử nghiệm sử dụng nhận dạng tiếng nói được kết nối mạng của Google." + "Để tắt nhập liệu bằng giọng nói, đi tới cài đặt bàn phím." + "Để sử dụng nhập liệu bằng giọng nói, hãy nhấn nút micrô hoặc trượt ngón tay trên bàn phím ảo." + "Xin mời nói" + "Đang hoạt động" + + "Lỗi. Vui lòng thử lại." + "Không thể kết nối" + "Lỗi, quá nhiều câu thoại." + "Sự cố âm thanh" + "Lỗi máy chủ" + "Không nghe thấy tiếng nói nào" + "Không tìm thấy kết quả phù hợp" + "Tìm kiếm bằng giọng nói chưa được cài đặt" + "Gợi ý:"" Trượt qua bàn phím để nói" + "Gợi ý:"" Lần tới, thử nói dấu câu như \"dấu chấm\", \"dấu phẩy\" hoặc \"dấu hỏi\"." + "Huỷ" + "OK" + "Nhập liệu bằng giọng nói" + + "Trên bàn phím chính" + "Trên bàn phím có biểu tượng" + "Tắt" + + + "Micrô trên bàn phím chính" + "Micrô trên bàn phím có biểu tượng" + "Nhập liệu bằng giọng nói đã bị vô hiệu hoá" + + "Tự động gửi sau thoại" + "Tự đông nhấn enter khi tìm kiếm hoặc đi tới trường tiếp theo." + "Mở bàn phím"\n\n"Chạm vào bất kỳ trường văn bản nào." + "Đóng bàn phím"\n\n"Nhấn phím Quay lại." + "Chạm & giữ phím cho các tuỳ chọn"\n\n"Truy cập dấu câu và dấu trọng âm." + "Cài đặt bàn phím"\n\n"Chạm & giữ phím ""?123""." + ".com" + ".net" + ".org" + ".gov" + ".edu" + "Chọn phương thức nhập" + "Ngôn ngữ nhập" + "Trượt ngón tay trên phím cách để thay đổi ngôn ngữ" + "← Chạm lại để lưu" + "Có sẵn từ điển" + "Bật phản hồi của người dùng" + "Giúp nâng cao trình chỉnh sửa phương thức nhập này bằng cách tự động gửi thống kê sử dụng và báo cáo sự cố cho Google." + "Chạm để sửa từ" + "Chạm các từ đã nhập để sửa" + "Chủ đề bàn phím" + "bàn phím" + "thoại" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-vi/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-vi/strings_kp2a.xml new file mode 100644 index 00000000..1563927a --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-vi/strings_kp2a.xml @@ -0,0 +1,20 @@ + + + + Chọn mục khác + Chọn mục + Tìm kiếm các mục nhập với \"%1$s\" + Người dùng + Mật mã + Cài đặt ủy quyền đăng nhập + Bật Tự động điền + Tự động điền văn bản khi một mục rỗng được nhập, nếu một mục Keepass2Android có sẵn cho bàn phím và có một giá trị phù hợp với văn bản gợi ý của mục đó. + Nhớ văn bản gợi ý của mục + Nếu một mục văn bản được nhập bằng cách chọn thủ công giá trị từ Keepass2Android, hãy nhớ rằng giá trị đó đã được nhập vô mục văn bản. Mục văn bản sau đó được phát hiện lại bởi văn bản gợi ý của nó. + Bàn phím đơn giản + Hiển thị bàn phím 1-hàng đơn giản nếu mục có sẵn cho bàn phím. Nếu vô hiệu hoá, một hộp thoại được hiển thị khi bấm phím Keepass2Android. + Khóa cơ sở dữ liệu chừng nào xong + Khi bấm phím Thực hiện/Gởi/Đi trên bàn phím 1-hàng đơn giản, tự động khóa cơ sở dữ liệu. + Chuyển đổi bàn phím chừng nào xong + Khi bấm phím Thực hiện/Gởi/Đi trên bàn phím 1-hàng đơn giản, chuyển đổi bàn phím. + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-zh-rCN/donottranslate-altchars.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-zh-rCN/donottranslate-altchars.xml new file mode 100644 index 00000000..b3486f4e --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-zh-rCN/donottranslate-altchars.xml @@ -0,0 +1,30 @@ + + + + àáâãäåæ + 3èéêë + 8ìíîï + 9òóôõöœø + 7ùúûü + §ß + ñ + ç + 6ýÿ + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-zh-rCN/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-zh-rCN/strings.xml new file mode 100644 index 00000000..ffdff64b --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-zh-rCN/strings.xml @@ -0,0 +1,140 @@ + + + + + "Keepass2Android 键盘" + "Keepass2Android 键盘设置" + "输入选项" + "按键时振动" + "按键时播放音效" + "按键时显示弹出窗口" + "纠正输入错误" + "启用输入错误纠正功能" + "横向输入错误" + "启用输入错误纠正功能" + "字词建议" + "自动纠正前面的字词" + "字词建议" + "字词建议设置" + "输入时启用自动填写功能" + "自动完成" + "扩大文字字段" + "在横向视图中隐藏字词建议" + "自动大写" + "句首字母大写" + "自动加标点" + + "快速纠正" + "纠正常见的输入错误" + "显示建议" + "输入时启用联想提示" + "自动填写" + "按空格键和标点符号时自动插入突出显示的字词" + "显示设置键" + "自动" + "始终显示" + "始终隐藏" + + + + "双连词建议" + "使用以前的字词改进建议" + + "无" + "基本模式" + "高级" + + "%s:已保存" + "按住某个键可看到重音符号(例如 ø、ö 等)" + "随时可以通过按后退键 ↶ 关闭键盘" + "访问数字和符号" + "长按最左侧的字可将其添加到词典中" + "轻触此提示继续 »" + "轻触此处可关闭该提示,然后便可开始输入内容!" + "您可以随时通过触摸文字字段打开键盘" + "轻触并按住某个键可以查看重音符号"\n"(ø、ö、ô、ó 等)" + "轻触该键即可切换到数字和符号键盘" + "再次轻触该键即可返回字母键盘" + "触摸并按住该键可更改键盘设置,例如自动完成" + "试试吧!" + "开始" + "下一步" + "完成" + "发送" + "?123" + "123" + "ABC" + "ALT" + "语音输入" + "语音输入功能当前还不支持您的语言,您只能输入英语语音。" + "语音输入是一项试验性的功能,它采用了 Google 的网络语音识别功能。" + "要关闭语音输入功能,请转至键盘设置。" + "要使用语音输入,请按麦克风按钮或者在屏幕键盘上滑动手指。" + "请开始说话" + "正在处理" + + "出错,请重试。" + "无法连接" + "出错,语音过长。" + "音频问题" + "服务器出错" + "未听到语音" + "未找到匹配项" + "未安装语音搜索" + "提示:""在键盘上滑动手指可激活语音功能" + "提示:""稍后,请尝试使用语音输入标点符号,如“句号”、“逗号”或“问号”。" + "取消" + "确定" + "语音输入" + + "主键盘上" + "符号键盘上" + "关" + + + "主键盘上的麦克风" + "符号键盘上的麦克风" + "已停用语音输入" + + "语音结束后自动提交" + "搜索或转到下一字段时自动按 Enter。" + "打开键盘"\n\n"触摸任意文本字段。" + "关闭键盘"\n\n"按“返回”键。" + "触摸并按住选项键"\n\n"进入标点/重音符号界面。" + "键盘设置"\n\n"触摸并按住 ""?123"" 键。" + ".com" + ".net" + ".org" + ".gov" + ".edu" + "选择输入法" + "输入语言" + "在空格键上滑动手指可更改语言" + "← 再次触摸即可保存" + "提供字典" + "启用用户反馈" + "自动向 Google 发送使用情况统计信息和崩溃报告,帮助改进该输入法编辑器。" + "触摸以更正字词" + "触摸所输入字词以进行更正" + "键盘主题" + "键盘" + "语音" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-zh-rCN/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-zh-rCN/strings_kp2a.xml new file mode 100644 index 00000000..ad92a758 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-zh-rCN/strings_kp2a.xml @@ -0,0 +1,20 @@ + + + + 选择另一条目 + 选择条目 + 搜索带有「%1$s」的条目 + 用户名 + 密码 + 输入凭据设置 + 自动填充已启用 + 当进入一个空白字段时自动填充文字,如果 Keepass2Android 是激活键盘,且有一个相匹配字段的提示文本。 + 记忆字段提示文本 + 如果通过手动选择 Keepass2Android 填充字段,请记住哪个字段在对应字段中输入。该字段是后来由其提示文本重新检测到。 + 简单键盘 + 当一个条目是可用时显示单行键盘。如果禁用,当按 Keepass2Android 键时则是显示一个对话框。 + 完成时锁定数据库 + 当点击单行键盘上的完成或发送键时,自动锁定数据库。 + 完成后切换键盘 + 当点击单行键盘上的完成或发送键时,自动切换键盘。 + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-zh-rTW/donottranslate-altchars.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-zh-rTW/donottranslate-altchars.xml new file mode 100644 index 00000000..b3486f4e --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-zh-rTW/donottranslate-altchars.xml @@ -0,0 +1,30 @@ + + + + àáâãäåæ + 3èéêë + 8ìíîï + 9òóôõöœø + 7ùúûü + §ß + ñ + ç + 6ýÿ + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-zh-rTW/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-zh-rTW/strings.xml new file mode 100644 index 00000000..e5a10e1c --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-zh-rTW/strings.xml @@ -0,0 +1,140 @@ + + + + + "Keepass2Android 鍵盤" + "Keepass2Android 鍵盤設定" + "輸入選項" + "按鍵時震動" + "按鍵時播放音效" + "按鍵時顯示彈出式視窗" + "修正輸入錯誤" + "啟用輸入錯誤修正功能" + "橫向輸入錯誤" + "啟用輸入錯誤修正功能" + "字詞建議" + "自動修正前一個字詞" + "字詞建議" + "字詞建議設定" + "輸入時啟用自動完成" + "自動完成" + "放大文字欄位大小" + "在橫向檢視模式中隱藏字詞建議" + "自動大寫" + "句首字母大寫" + "自動標點" + + "快速修正" + "修正一般打字錯誤" + "顯示建議" + "打字時顯示建議字詞" + "自動完成" + "在反白顯示的字詞處自動插入空白鍵和標點符號鍵盤" + "顯示設定金鑰" + "自動" + "一律顯示" + "永遠隱藏" + + + + "雙連詞建議" + "根據前一個字詞自動找出更適合的建議" + + "無" + "基本模式" + "進階模式" + + "%s:已儲存" + "按住按鍵可查看重音符號 (ø、ö 等)" + "隨時可以透過按後退鍵 ↶ 關閉鍵盤" + "使用數字和符號" + "按住最左邊的字詞,將其新增到字典中" + "輕觸此提示繼續 »" + "輕觸此處以關閉提示,並開始打字!" + "輕觸文字欄位時即會開啟鍵盤" + "輕觸並按住某個鍵即可查看聲調"\n"(ø、ö、ô、ó 等)" + "輕觸此鍵即可切換到數字和符號鍵盤" + "再次輕觸此鍵即可返回到字母鍵盤" + "輕觸並按住此鍵即可變更鍵盤設定,例如自動完成" + "試試看!" + "開始" + "繼續" + "完成" + "傳送" + "?123" + "123" + "ABC" + "ALT" + "語音輸入" + "語音輸入目前不支援您的語言,但是可以辨識英文。" + "語音輸入這項實驗功能運用了 Google 的網路語音辨識系統。" + "請前往鍵盤設定來關閉語音輸入。" + "如要使用語音輸入,按下 [麥克風] 按鈕,或將手指滑過螢幕小鍵盤即可。" + "請說話" + "辨識中" + + "發生錯誤,請再試一次。" + "無法連線" + "錯誤:語音內容過長。" + "音訊問題" + "伺服器錯誤" + "沒有聽到任何聲音" + "找不到相符的項目" + "未安裝語音搜尋" + "提示:""滑過鍵盤即可說話" + "提示:""下次可嘗試說出標點符號,例如「句號」、「逗號」或「問號」。" + "取消" + "確定" + "語音輸入" + + "於主鍵盤" + "符號鍵盤上" + "關閉" + + + "主鍵盤上的麥克風" + "符號鍵盤上的麥克風" + "已停用語音輸入" + + "說話後自動提交" + "搜尋或前往下一個欄位時自動按下輸入。" + "開啟鍵盤"\n\n"輕觸任何文字欄位。" + "關閉鍵盤"\n\n"按下 Back 鍵。" + \n"輕觸並按住按鍵開啟選項"\n"輸入標點與輕重音。" + "鍵盤設定"\n\n"輕觸並按住 ""?123"" 鍵。" + ".com" + ".net" + ".org" + ".gov" + ".edu" + "選取輸入法" + "輸入語言" + "以手指在空白鍵上滑動可變更語言" + "← 再次輕觸即可儲存" + "可使用字典" + "啟用使用者意見回饋" + "自動將使用統計資料和當機報告傳送給 Google,協助改善這個輸入法編輯器。" + "輕觸此處可修正字詞" + "輕觸輸入的字詞即可加以修正" + "鍵盤主題" + "鍵盤" + "語音" + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-zh-rTW/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-zh-rTW/strings_kp2a.xml new file mode 100644 index 00000000..2bccb9b5 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values-zh-rTW/strings_kp2a.xml @@ -0,0 +1,20 @@ + + + + 請選擇另一輸入項 + 選擇輸入項 + 搜索有\"%1$s\"的輸入項 + 使用者 + 密碼 + 憑證輸入設置 + 自動輸入啟用 + 當選擇空白欄位時,若有可用鍵盤的 Keepass2Android 輸入項且當值符合欄位關鍵字,自動填入文字。 + 記得欄位提示文字 + 如果通過手動選擇 Keepass2Android 值填充文字欄位,請記住哪個值被輸入到文字欄位。文字欄位將由其提示文字重新檢偵測。 + 簡易鍵盤 + 若輸入項可使用鍵盤則顯示簡單的 1 行鍵盤。若禁用,按下 Keepass2Android 鍵會顯示一個對話方塊。 + 完成後鎖定資料庫 + 使用簡單的 1 行鍵盤上按 完成/發送/好 鍵後,自動鎖定資料庫。 + 完成後切換鍵盤 + 使用簡單的 1 行鍵盤上按做/發送/好 鍵,切換鍵盤。 + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/attrs.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/attrs.xml new file mode 100644 index 00000000..995373e8 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/attrs.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/bools.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/bools.xml new file mode 100644 index 00000000..5a24e4c6 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/bools.xml @@ -0,0 +1,33 @@ + + + + + true + + false + + true + true + + true + true + true + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/colors.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/colors.xml new file mode 100644 index 00000000..0161589a --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/colors.xml @@ -0,0 +1,32 @@ + + + + #FFFFFFFF + #FFFCAE00 + #FFFCAE00 + #00000000 + #80000000 + #80FFFFFF + #FFC0C0C0 + #A0000000 + #FFFFFFFF + #FFFFFFFF + #FF000000 + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/config.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/config.xml new file mode 100644 index 00000000..edb6cd84 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/config.xml @@ -0,0 +1,32 @@ + + + + + 0 + 10 + 0 + 70 + 0 + 100 + 400 + 50 + 400 + 800 + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/dimens.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/dimens.xml new file mode 100644 index 00000000..86eb55f0 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/dimens.xml @@ -0,0 +1,41 @@ + + + + + 49.109985dip + 5.0dip + 52.0dip + 9.599976dip + 22.0dip + 42.0dip + 63.0dip + 4.0dip + 423.32812dip + 22.00998sp + 14.049988sp + 40.0sp + 0.0dip + 80.0sp + 88.47998dip + -52.0dip + 8.0dip + -8.0dip + 48.0dip + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/donottranslate-altchars.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/donottranslate-altchars.xml new file mode 100644 index 00000000..bba7282c --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/donottranslate-altchars.xml @@ -0,0 +1,46 @@ + + + + àáâãäåæ + èéêë + ìíîï + òóôõöœø + ùúûü + §ß + ñ + ç + ýÿ + 1 + 2 + + 4 + 5 + + + + 0 + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/donottranslate.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/donottranslate.xml new file mode 100644 index 00000000..93660992 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/donottranslate.xml @@ -0,0 +1,35 @@ + + + + + .\u0009\u0020,;:!?\n()[]*&@{}/<>_+=|\u0022 + + .,!?) + + !?,\u0022\u0027:()-/@_ + + + + 0 + + 1 + + 2 + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/durations.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/durations.xml new file mode 100644 index 00000000..92af68e3 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/durations.xml @@ -0,0 +1,25 @@ + + + + + + 40 + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/keycodes.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/keycodes.xml new file mode 100644 index 00000000..3dd1f36f --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/keycodes.xml @@ -0,0 +1,40 @@ + + + + + 9 + 10 + 32 + -1 + -2 + -5 + + -100 + -102 + -103 + -200 + -201 + -202 + -203 + -204 + -205 + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/strings.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/strings.xml new file mode 100644 index 00000000..314dd261 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/strings.xml @@ -0,0 +1,379 @@ + + + + + Keepass2Android keyboard + + Android keyboard settings + + Input options + + + Vibrate on keypress + + + Sound on keypress + + + Popup on keypress + + + Correct typing errors + + + Enable input error correction + + + Landscape input errors + + + Enable input error correction + + + Word suggestions + + + Automatically correct the previous word + + + Word suggestions + + Word suggestion settings + + Enable auto completion while typing + + + Auto completion + + + Increase text field size + + Hide word suggestions in landscape view + + + Auto-capitalization + + Capitalize the start of a sentence + + Auto-punctuate + + + + + Quick fixes + + Corrects commonly typed mistakes + + + Show suggestions + + Display suggested words while typing + + + Auto-complete + + Spacebar and punctuation automatically insert highlighted word + + + Show settings key + + + @string/settings_key_mode_auto + @string/settings_key_mode_always_show + @string/settings_key_mode_always_hide + + + Automatic + + Always show + + Always hide + + + @string/settings_key_mode_auto_name + @string/settings_key_mode_always_show_name + @string/settings_key_mode_always_hide_name + + + + Bigram Suggestions + + Use previous word to improve suggestion + + + + None + Basic + Advanced + + + + 0 + + 1 + + 2 + + + @string/prediction_none + @string/prediction_basic + @string/prediction_full + + + + %s : Saved + + + Hold a key down to see accents (ø, ö, etc.) + + Press the back key \u21B6 to close the keyboard at any point + + Access numbers and symbols + + Press and hold the left-most word to add it to the dictionary + + + + Touch this hint to continue » + + + Touch here to close this hint and start typing! + + + The keyboard opens any time you touch a text field + + + Touch & hold a key to view accents\n(ø, ö, ô, ó, and so on) + + + + Switch to numbers and symbols by touching this key + + + Go back to letters by touching this key again + + + Touch & hold this key to change keyboard settings, like auto complete + + + Try it! + + + + Go + + Next + + Done + + Send + + \?123 + + 123 + + ABC + + ALT + + + + + Voice input + + + Voice input is not currently supported for your language, but does work in English. + + + Voice input is an experimental feature using Google\'s networked speech recognition. + + + To turn off voice input, go to keyboard settings. + + + To use voice input, press the microphone button or slide your finger across the on-screen keyboard. + + + Speak now + + + Working + + + + + + Error. Please try again. + + + Couldn\'t connect + + + Error, too much speech. + + + Audio problem + + + Server error + + + No speech heard + + + No matches found + + + Voice search not installed + + + Hint: Swipe across keyboard to speak + + + Hint: Next time, try speaking punctuation like \"period\", \"comma\", or \"question mark\". + + + Cancel + + + OK + + + Voice input + + + + On main keyboard + On symbols keyboard + Off + + + + 0 + + 1 + + 2 + + + @string/voice_mode_main + @string/voice_mode_symbols + @string/voice_mode_off + + + + + Mic on main keyboard + Mic on symbols keyboard + Voice input is disabled + + + + Auto submit after voice + + + Automatically press enter when searching or going to the next field. + + + + Open the keyboard\n\nTouch any text field. + + + Close the keyboard\n\nPress the Back key. + + + Touch \u0026 hold a key for options\n\nAccess punctuation and accents. + + + Keyboard settings\n\nTouch \u0026 hold the \?123\ key. + + + ".com" + + ".net" + + ".org" + + ".gov" + + ".edu" + + + Select input method + + + Input languages + + Slide finger on spacebar to change language + + + \u2190 Touch again to save + + + Dictionary available + + + Enable user feedback + + Help improve this input method editor by automatically sending usage statistics and crash reports to Google. + + Touch to correct words + + Touch entered words to correct them + + + Keyboard Theme + Basic + Basic (High Contrast) + Stone (bold) + Stone (normal) + Gingerbread + + + @string/layout_basic + @string/layout_high_contrast + @string/layout_stone_normal + @string/layout_stone_bold + @string/layout_gingerbread + + + + 0 + 1 + 2 + 3 + 4 + + + keyboard + voice + + + Android keyboard Debug settings + Debug Mode + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/strings_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/strings_kp2a.xml new file mode 100644 index 00000000..b6303c0a --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/strings_kp2a.xml @@ -0,0 +1,23 @@ + + + Select another entry + Select entry + Search for entry with "%1$s" + User + Password + + Credential input settings + Auto-Fill enabled + Automatically fill in text when an empty field is entered, if a Keepass2Android entry is available for the keyboard and there is a value which matches the field\'s hint text. + Remember field hint texts + If a text field is filled by manually selecting the Keepass2Android value, remember which value was entered into the text field. The text field is later redetected by its hint text. + Simple keyboard + Show the simple 1-row keyboard if an entry is available for the keyboard. If disabled, a dialog is shown when the Keepass2Android key is pressed. + + Lock database when done + When pressing the Done/Send/Go key on the simple 1-row keyboard, automatically lock the database. + + Switch keyboard when done + When pressing the Done/Send/Go key on the simple 1-row keyboard, switch the keyboard. + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/styles.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/styles.xml new file mode 100644 index 00000000..0372b07c --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/values/styles.xml @@ -0,0 +1,44 @@ + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-da/kbd_qwerty.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-da/kbd_qwerty.xml new file mode 100644 index 00000000..bec5e04e --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-da/kbd_qwerty.xml @@ -0,0 +1,541 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-da/kbd_qwerty_black.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-da/kbd_qwerty_black.xml new file mode 100644 index 00000000..c25c23d5 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-da/kbd_qwerty_black.xml @@ -0,0 +1,478 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-de/kbd_qwerty.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-de/kbd_qwerty.xml new file mode 100644 index 00000000..2c281a68 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-de/kbd_qwerty.xml @@ -0,0 +1,520 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-de/kbd_qwerty_black.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-de/kbd_qwerty_black.xml new file mode 100644 index 00000000..f8143c44 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-de/kbd_qwerty_black.xml @@ -0,0 +1,457 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-fr/kbd_qwerty.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-fr/kbd_qwerty.xml new file mode 100644 index 00000000..fb65db8b --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-fr/kbd_qwerty.xml @@ -0,0 +1,521 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-fr/kbd_qwerty_black.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-fr/kbd_qwerty_black.xml new file mode 100644 index 00000000..d32ae757 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-fr/kbd_qwerty_black.xml @@ -0,0 +1,458 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-iw/kbd_qwerty.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-iw/kbd_qwerty.xml new file mode 100644 index 00000000..f84e1619 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-iw/kbd_qwerty.xml @@ -0,0 +1,479 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-iw/kbd_qwerty_black.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-iw/kbd_qwerty_black.xml new file mode 100644 index 00000000..ecf4e3d6 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-iw/kbd_qwerty_black.xml @@ -0,0 +1,416 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-nb/kbd_qwerty.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-nb/kbd_qwerty.xml new file mode 100644 index 00000000..0774af33 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-nb/kbd_qwerty.xml @@ -0,0 +1,541 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-nb/kbd_qwerty_black.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-nb/kbd_qwerty_black.xml new file mode 100644 index 00000000..951837c4 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-nb/kbd_qwerty_black.xml @@ -0,0 +1,478 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-pl/kbd_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-pl/kbd_kp2a.xml new file mode 100644 index 00000000..98a37c8c --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-pl/kbd_kp2a.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-ru/kbd_qwerty.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-ru/kbd_qwerty.xml new file mode 100644 index 00000000..8e7feab5 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-ru/kbd_qwerty.xml @@ -0,0 +1,519 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-ru/kbd_qwerty_black.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-ru/kbd_qwerty_black.xml new file mode 100644 index 00000000..4e17d488 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-ru/kbd_qwerty_black.xml @@ -0,0 +1,456 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-sr/kbd_qwerty.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-sr/kbd_qwerty.xml new file mode 100644 index 00000000..34caa1dc --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-sr/kbd_qwerty.xml @@ -0,0 +1,512 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-sr/kbd_qwerty_black.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-sr/kbd_qwerty_black.xml new file mode 100644 index 00000000..8a740bd0 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-sr/kbd_qwerty_black.xml @@ -0,0 +1,449 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-sv/kbd_qwerty.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-sv/kbd_qwerty.xml new file mode 100644 index 00000000..e43e5702 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-sv/kbd_qwerty.xml @@ -0,0 +1,542 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-sv/kbd_qwerty_black.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-sv/kbd_qwerty_black.xml new file mode 100644 index 00000000..9a62e43a --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml-sv/kbd_qwerty_black.xml @@ -0,0 +1,480 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/dictionary.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/dictionary.xml new file mode 100644 index 00000000..7b770a8b --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/dictionary.xml @@ -0,0 +1,23 @@ + + + + + + \ No newline at end of file diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_kp2a.xml new file mode 100644 index 00000000..2a2c3029 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_kp2a.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_kp2a_black.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_kp2a_black.xml new file mode 100644 index 00000000..cba42bf1 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_kp2a_black.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_phone.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_phone.xml new file mode 100644 index 00000000..01010774 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_phone.xml @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_phone_black.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_phone_black.xml new file mode 100644 index 00000000..4b50be37 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_phone_black.xml @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_phone_symbols.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_phone_symbols.xml new file mode 100644 index 00000000..4c928a8d --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_phone_symbols.xml @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_phone_symbols_black.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_phone_symbols_black.xml new file mode 100644 index 00000000..4d686e14 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_phone_symbols_black.xml @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_popup_narrow_template.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_popup_narrow_template.xml new file mode 100644 index 00000000..23c686e8 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_popup_narrow_template.xml @@ -0,0 +1,27 @@ + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_popup_template.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_popup_template.xml new file mode 100644 index 00000000..a287be1f --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_popup_template.xml @@ -0,0 +1,27 @@ + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_qwerty.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_qwerty.xml new file mode 100644 index 00000000..16abbc9b --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_qwerty.xml @@ -0,0 +1,515 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_qwerty_black.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_qwerty_black.xml new file mode 100644 index 00000000..6c9a071e --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_qwerty_black.xml @@ -0,0 +1,452 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_symbols.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_symbols.xml new file mode 100644 index 00000000..e9781786 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_symbols.xml @@ -0,0 +1,215 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_symbols_black.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_symbols_black.xml new file mode 100644 index 00000000..7a245b28 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_symbols_black.xml @@ -0,0 +1,203 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_symbols_shift.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_symbols_shift.xml new file mode 100644 index 00000000..6a900d7c --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_symbols_shift.xml @@ -0,0 +1,191 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_symbols_shift_black.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_symbols_shift_black.xml new file mode 100644 index 00000000..7cbebfc7 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/kbd_symbols_shift_black.xml @@ -0,0 +1,178 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/language_prefs.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/language_prefs.xml new file mode 100644 index 00000000..b7a4c07d --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/language_prefs.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/method.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/method.xml new file mode 100644 index 00000000..3cf8d2dd --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/method.xml @@ -0,0 +1,26 @@ + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/popup_at.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/popup_at.xml new file mode 100644 index 00000000..197eea44 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/popup_at.xml @@ -0,0 +1,39 @@ + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/popup_comma.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/popup_comma.xml new file mode 100644 index 00000000..7666f4b6 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/popup_comma.xml @@ -0,0 +1,39 @@ + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/popup_domains.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/popup_domains.xml new file mode 100644 index 00000000..4e9789ff --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/popup_domains.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/popup_kp2a.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/popup_kp2a.xml new file mode 100644 index 00000000..a06eee1e --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/popup_kp2a.xml @@ -0,0 +1,20 @@ + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/popup_mic.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/popup_mic.xml new file mode 100644 index 00000000..5bbd7dfa --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/popup_mic.xml @@ -0,0 +1,40 @@ + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/popup_punctuation.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/popup_punctuation.xml new file mode 100644 index 00000000..c429e38b --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/popup_punctuation.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/popup_slash.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/popup_slash.xml new file mode 100644 index 00000000..a38fde0e --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/popup_slash.xml @@ -0,0 +1,39 @@ + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/popup_smileys.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/popup_smileys.xml new file mode 100644 index 00000000..1a14e1df --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/popup_smileys.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/prefs.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/prefs.xml new file mode 100644 index 00000000..d748765e --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/prefs.xml @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/prefs_for_debug.xml b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/prefs_for_debug.xml new file mode 100644 index 00000000..8177d3c6 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/app/src/main/res/xml/prefs_for_debug.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + diff --git a/src/java/KP2ASoftkeyboard_AS/build.gradle b/src/java/KP2ASoftkeyboard_AS/build.gradle new file mode 100644 index 00000000..88d246d4 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/build.gradle @@ -0,0 +1,15 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:1.2.3' + } +} + +allprojects { + repositories { + jcenter() + } +} diff --git a/src/java/KP2ASoftkeyboard_AS/build/intermediates/gradle_project_sync_data.bin b/src/java/KP2ASoftkeyboard_AS/build/intermediates/gradle_project_sync_data.bin new file mode 100644 index 00000000..87f1940e Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/build/intermediates/gradle_project_sync_data.bin differ diff --git a/src/java/KP2ASoftkeyboard_AS/gradle/wrapper/gradle-wrapper.jar b/src/java/KP2ASoftkeyboard_AS/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..8c0fb64a Binary files /dev/null and b/src/java/KP2ASoftkeyboard_AS/gradle/wrapper/gradle-wrapper.jar differ diff --git a/src/java/KP2ASoftkeyboard_AS/gradle/wrapper/gradle-wrapper.properties b/src/java/KP2ASoftkeyboard_AS/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..0c71e760 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Wed Apr 10 15:27:10 PDT 2013 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip diff --git a/src/java/KP2ASoftkeyboard_AS/gradlew b/src/java/KP2ASoftkeyboard_AS/gradlew new file mode 100644 index 00000000..91a7e269 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/gradlew @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched. +if $cygwin ; then + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` +fi + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/src/java/KP2ASoftkeyboard_AS/gradlew.bat b/src/java/KP2ASoftkeyboard_AS/gradlew.bat new file mode 100644 index 00000000..8a0b282a --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/src/java/KP2ASoftkeyboard_AS/settings.gradle b/src/java/KP2ASoftkeyboard_AS/settings.gradle new file mode 100644 index 00000000..e7b4def4 --- /dev/null +++ b/src/java/KP2ASoftkeyboard_AS/settings.gradle @@ -0,0 +1 @@ +include ':app'