diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1bc73ffda..207280e5f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -57,7 +57,8 @@ To support a new language one needs to: - `name` is the native name of the language (e.g. "English", "Deutsch", "Українська"). - `locale` contains the language and the country codes (e.g. "en-US", "es-AR", "it-IT"). Refer to the list of [supported locales in Java](https://www.oracle.com/java/technologies/javase/jdk8-jre8-suported-locales.html#util-text). - `dictionaryFile` is the name of the dictionary in `assets/` folder. - - `icon`, `abcLowerCaseIcon` and `abcUpperCaseIcon` are the respective status icons for Predictive mode, ABC (lowercase) and ABC (uppercase). + - `icon` is the status icon for Predictive mode. + - `abcLowerCaseIcon` and `abcUpperCaseIcon` are the respective status icons for ABC (non-predictive) modes. Note that, you must not set `abcUpperCaseIcon`, if your language has no uppercase and lowercase letters (like Arabic, Asian scripts and Hebrew). - Set `isPunctuationPartOfWords` to `true`, if the dictionary contains words with apostrophes or dashes, such as: `it's`, `you'll`, `a'tje` or `п'ят`. This will allow using 1-key for typing them (they will appear as suggestions). `false` will enable faster typing when apostrophes or other punctuation are not part of the words (no such words will be suggested). - `characterMap` contains the letters and punctuation marks associated with each key. - Finally, add the new language to the list in `LanguageCollection.java`. You only need to add it in one place, in the constructor. Please, be nice and maintain the alphabetical order. diff --git a/src/io/github/sspanak/tt9/ime/TraditionalT9.java b/src/io/github/sspanak/tt9/ime/TraditionalT9.java index a6bf392cc..8f5f9f82d 100644 --- a/src/io/github/sspanak/tt9/ime/TraditionalT9.java +++ b/src/io/github/sspanak/tt9/ime/TraditionalT9.java @@ -51,7 +51,7 @@ public static Context getMainContext() { private void loadSettings() { mLanguage = LanguageCollection.getLanguage(settings.getInputLanguage()); mEnabledLanguages = settings.getEnabledLanguageIds(); - mInputMode = InputMode.getInstance(settings, settings.getInputMode()); + mInputMode = InputMode.getInstance(settings, mLanguage, settings.getInputMode()); mInputMode.setTextCase(settings.getTextCase()); } @@ -96,9 +96,10 @@ private void initTyping() { // some input fields support only numbers or are not suited for predictions (e.g. password fields) determineAllowedInputModes(); - mInputMode = InputModeValidator.validateMode(settings, mInputMode, allowedInputModes); - + int modeId = InputModeValidator.validateMode(settings, mInputMode, allowedInputModes); + mInputMode = InputMode.getInstance(settings, mLanguage, modeId); mInputMode.setTextFieldCase(textField.determineTextCase(inputType)); + // Some modes may want to change the default text case based on grammar rules. determineNextTextCase(); InputModeValidator.validateTextCase(settings, mInputMode, settings.getTextCase()); @@ -197,7 +198,7 @@ public boolean onOK() { String word = mSuggestionView.getCurrentSuggestion(); - mInputMode.onAcceptSuggestion(mLanguage, word); + mInputMode.onAcceptSuggestion(word); commitCurrentSuggestion(); autoCorrectSpace(word, true, -1, false, false); resetKeyRepeat(); @@ -208,7 +209,7 @@ public boolean onOK() { protected boolean onUp() { if (previousSuggestion()) { - mInputMode.setWordStem(mLanguage, mSuggestionView.getCurrentSuggestion(), true); + mInputMode.setWordStem(mSuggestionView.getCurrentSuggestion(), true); textField.setComposingTextWithHighlightedStem(mSuggestionView.getCurrentSuggestion(), mInputMode); return true; } @@ -219,7 +220,7 @@ protected boolean onUp() { protected boolean onDown() { if (nextSuggestion()) { - mInputMode.setWordStem(mLanguage, mSuggestionView.getCurrentSuggestion(), true); + mInputMode.setWordStem(mSuggestionView.getCurrentSuggestion(), true); textField.setComposingTextWithHighlightedStem(mSuggestionView.getCurrentSuggestion(), mInputMode); return true; } @@ -230,7 +231,7 @@ protected boolean onDown() { protected boolean onLeft() { if (mInputMode.clearWordStem()) { - mInputMode.loadSuggestions(handleSuggestionsAsync, mLanguage, getComposingText()); + mInputMode.loadSuggestions(handleSuggestionsAsync, getComposingText()); } else { jumpBeforeComposingText(); } @@ -247,8 +248,8 @@ protected boolean onRight(boolean repeat) { filter = getComposingText(); } - if (mInputMode.setWordStem(mLanguage, filter, repeat)) { - mInputMode.loadSuggestions(handleSuggestionsAsync, mLanguage, filter); + if (mInputMode.setWordStem(filter, repeat)) { + mInputMode.loadSuggestions(handleSuggestionsAsync, filter); } else if (filter.length() == 0) { mInputMode.reset(); } @@ -270,8 +271,8 @@ protected boolean onNumber(int key, boolean hold, int repeat) { // Automatically accept the current word, when the next one is a space or whatnot, // instead of requiring "OK" before that. - if (mInputMode.shouldAcceptCurrentSuggestion(mLanguage, key, hold, repeat > 0)) { - mInputMode.onAcceptSuggestion(mLanguage, currentWord); + if (mInputMode.shouldAcceptCurrentSuggestion(key, hold, repeat > 0)) { + mInputMode.onAcceptSuggestion(currentWord); commitCurrentSuggestion(false); autoCorrectSpace(currentWord, false, key, hold, repeat > 0); currentWord = ""; @@ -283,7 +284,7 @@ protected boolean onNumber(int key, boolean hold, int repeat) { determineNextTextCase(); } - if (!mInputMode.onNumber(mLanguage, key, hold, repeat)) { + if (!mInputMode.onNumber(key, hold, repeat)) { return false; } @@ -295,7 +296,7 @@ protected boolean onNumber(int key, boolean hold, int repeat) { if (mInputMode.getWord() != null) { currentWord = mInputMode.getWord(); - mInputMode.onAcceptSuggestion(mLanguage, currentWord); + mInputMode.onAcceptSuggestion(currentWord); textField.setText(currentWord); clearSuggestions(); autoCorrectSpace(currentWord, true, key, hold, repeat > 0); @@ -333,6 +334,7 @@ protected boolean onKeyAddWord() { protected boolean onKeyNextLanguage() { if (nextLang()) { commitCurrentSuggestion(false); + mInputMode.changeLanguage(mLanguage); mInputMode.reset(); resetKeyRepeat(); clearSuggestions(); @@ -430,14 +432,14 @@ private void clearSuggestions() { private void getSuggestions() { - if (!mInputMode.loadSuggestions(handleSuggestionsAsync, mLanguage, mSuggestionView.getCurrentSuggestion())) { + if (!mInputMode.loadSuggestions(handleSuggestionsAsync, mSuggestionView.getCurrentSuggestion())) { handleSuggestions(); } } private void handleSuggestions() { - setSuggestions(mInputMode.getSuggestions(mLanguage)); + setSuggestions(mInputMode.getSuggestions()); // Put the first suggestion in the text field, // but cut it off to the length of the sequence (how many keys were pressed), @@ -489,7 +491,7 @@ private void refreshComposingText() { private void nextInputMode() { if (mEditing == EDITING_STRICT_NUMERIC || mEditing == EDITING_DIALER) { - mInputMode = !mInputMode.is123() ? InputMode.getInstance(settings, InputMode.MODE_123) : mInputMode; + mInputMode = !mInputMode.is123() ? InputMode.getInstance(settings, mLanguage, InputMode.MODE_123) : mInputMode; } // when typing a word or viewing scrolling the suggestions, only change the case else if (!isSuggestionViewHidden()) { @@ -498,9 +500,9 @@ else if (!isSuggestionViewHidden()) { // When we are in AUTO mode and the dictionary word is in uppercase, // the mode would switch to UPPERCASE, but visually, the word would not change. // This is why we retry, until there is a visual change. - for (int retries = 0; retries < 2; retries++) { + for (int retries = 0; retries < 2 && mLanguage.hasUpperCase(); retries++) { mInputMode.nextTextCase(); - setSuggestions(mInputMode.getSuggestions(mLanguage), mSuggestionView.getCurrentIndex()); + setSuggestions(mInputMode.getSuggestions(), mSuggestionView.getCurrentIndex()); refreshComposingText(); if (!currentSuggestionBefore.equals(getComposingText())) { @@ -509,17 +511,17 @@ else if (!isSuggestionViewHidden()) { } } // make "abc" and "ABC" separate modes from user perspective - else if (mInputMode.isABC() && mInputMode.getTextCase() == InputMode.CASE_LOWER) { + else if (mInputMode.isABC() && mInputMode.getTextCase() == InputMode.CASE_LOWER && mLanguage.hasUpperCase()) { mInputMode.nextTextCase(); } else { int modeIndex = (allowedInputModes.indexOf(mInputMode.getId()) + 1) % allowedInputModes.size(); - mInputMode = InputMode.getInstance(settings, allowedInputModes.get(modeIndex)); + mInputMode = InputMode.getInstance(settings, mLanguage, allowedInputModes.get(modeIndex)); mInputMode.defaultTextCase(); } // save the settings for the next time - settings.saveInputMode(mInputMode); + settings.saveInputMode(mInputMode.getId()); settings.saveTextCase(mInputMode.getTextCase()); UI.updateStatusIcon(this, mLanguage, mInputMode); @@ -558,7 +560,7 @@ private void jumpBeforeComposingText() { textField.setComposingText(word, 0); textField.finishComposingText(); - mInputMode.onAcceptSuggestion(mLanguage, word); + mInputMode.onAcceptSuggestion(word); mInputMode.reset(); setSuggestions(null); } @@ -569,11 +571,11 @@ private void determineAllowedInputModes() { int lastInputModeId = settings.getInputMode(); if (allowedInputModes.contains(lastInputModeId)) { - mInputMode = InputMode.getInstance(settings, lastInputModeId); + mInputMode = InputMode.getInstance(settings, mLanguage, lastInputModeId); } else if (allowedInputModes.contains(InputMode.MODE_ABC)) { - mInputMode = InputMode.getInstance(settings, InputMode.MODE_ABC); + mInputMode = InputMode.getInstance(settings, mLanguage, InputMode.MODE_ABC); } else { - mInputMode = InputMode.getInstance(settings, allowedInputModes.get(0)); + mInputMode = InputMode.getInstance(settings, mLanguage, allowedInputModes.get(0)); } if (inputType.isDialer()) { diff --git a/src/io/github/sspanak/tt9/ime/helpers/InputModeValidator.java b/src/io/github/sspanak/tt9/ime/helpers/InputModeValidator.java index 029c2b56d..e73eb38a7 100644 --- a/src/io/github/sspanak/tt9/ime/helpers/InputModeValidator.java +++ b/src/io/github/sspanak/tt9/ime/helpers/InputModeValidator.java @@ -41,23 +41,19 @@ public static Language validateLanguage(SettingsStore settings, Language languag return validLanguage; } - public static InputMode validateMode(SettingsStore settings, InputMode inputMode, ArrayList allowedModes) { + public static int validateMode(SettingsStore settings, InputMode inputMode, ArrayList allowedModes) { if (allowedModes.size() > 0 && allowedModes.contains(inputMode.getId())) { - inputMode.reset(); - return inputMode; + return inputMode.getId(); } - InputMode newMode = InputMode.getInstance( - settings, - allowedModes.size() > 0 ? allowedModes.get(0) : InputMode.MODE_123 - ); - settings.saveInputMode(newMode); + int newModeId = allowedModes.size() > 0 ? allowedModes.get(0) : InputMode.MODE_123; + settings.saveInputMode(newModeId); - if (newMode.getId() != inputMode.getId()) { - Logger.w("tt9/validateMode", "Invalid input mode: " + inputMode.getId() + " Enforcing: " + newMode.getId()); + if (newModeId != inputMode.getId()) { + Logger.w("tt9/validateMode", "Invalid input mode: " + inputMode.getId() + " Enforcing: " + newModeId); } - return newMode; + return newModeId; } public static void validateTextCase(SettingsStore settings, InputMode inputMode, int newTextCase) { diff --git a/src/io/github/sspanak/tt9/ime/modes/InputMode.java b/src/io/github/sspanak/tt9/ime/modes/InputMode.java index 3f83b6d62..9e4cc6049 100644 --- a/src/io/github/sspanak/tt9/ime/modes/InputMode.java +++ b/src/io/github/sspanak/tt9/ime/modes/InputMode.java @@ -27,16 +27,17 @@ abstract public class InputMode { protected int textFieldTextCase = CASE_UNDEFINED; // data + protected Language language; protected ArrayList suggestions = new ArrayList<>(); protected String word = null; - public static InputMode getInstance(SettingsStore settings, int mode) { + public static InputMode getInstance(SettingsStore settings, Language language, int mode) { switch (mode) { case MODE_PREDICTIVE: - return new ModePredictive(settings); + return new ModePredictive(settings, language); case MODE_ABC: - return new ModeABC(); + return new ModeABC(language); default: Logger.w("tt9/InputMode", "Defaulting to mode: " + Mode123.class.getName() + " for unknown InputMode: " + mode); case MODE_123: @@ -46,17 +47,17 @@ public static InputMode getInstance(SettingsStore settings, int mode) { // Key handlers. Return "true" when handling the key or "false", when is nothing to do. public boolean onBackspace() { return false; } - abstract public boolean onNumber(Language language, int key, boolean hold, int repeat); + abstract public boolean onNumber(int key, boolean hold, int repeat); // Suggestions - public void onAcceptSuggestion(Language language, String suggestion) {} + public void onAcceptSuggestion(String suggestion) {} protected void onSuggestionsUpdated(Handler handler) { handler.sendEmptyMessage(0); } - public boolean loadSuggestions(Handler handler, Language language, String currentWord) { return false; } + public boolean loadSuggestions(Handler handler, String currentWord) { return false; } - public ArrayList getSuggestions(Language language) { + public ArrayList getSuggestions() { ArrayList newSuggestions = new ArrayList<>(); for (String s : suggestions) { - newSuggestions.add(adjustSuggestionTextCase(s, textCase, language)); + newSuggestions.add(adjustSuggestionTextCase(s, textCase)); } return newSuggestions; @@ -73,9 +74,14 @@ public ArrayList getSuggestions(Language language) { // Utility abstract public int getId(); abstract public int getSequenceLength(); // The number of key presses for the current word. + public void changeLanguage(Language newLanguage) { + if (newLanguage != null) { + language = newLanguage; + } + } // Interaction with the IME. Return "true" if it should perform the respective action. - public boolean shouldAcceptCurrentSuggestion(Language language, int key, boolean hold, boolean repeat) { return false; } + public boolean shouldAcceptCurrentSuggestion(int key, boolean hold, boolean repeat) { return false; } public boolean shouldAddAutoSpace(InputType inputType, TextField textField, boolean isWordAcceptedManually, int incomingKey, boolean hold, boolean repeat) { return false; } public boolean shouldDeletePrecedingSpace(InputType inputType) { return false; } public boolean shouldSelectNextSuggestion() { return false; } @@ -116,12 +122,12 @@ public void nextTextCase() { public void determineNextWordTextCase(SettingsStore settings, boolean isThereText, String textBeforeCursor) {} // Based on the internal logic of the mode (punctuation or grammar rules), re-adjust the text case for when getSuggestions() is called. - protected String adjustSuggestionTextCase(String word, int newTextCase, Language language) { return word; } + protected String adjustSuggestionTextCase(String word, int newTextCase) { return word; } // Stem filtering. // Where applicable, return "true" if the mode supports it and the operation was possible. public boolean clearWordStem() { return false; } public boolean isStemFilterFuzzy() { return false; } public String getWordStem() { return ""; } - public boolean setWordStem(Language language, String stem, boolean exact) { return false; } + public boolean setWordStem(String stem, boolean exact) { return false; } } diff --git a/src/io/github/sspanak/tt9/ime/modes/Mode123.java b/src/io/github/sspanak/tt9/ime/modes/Mode123.java index b83366c17..e3f5bb49f 100644 --- a/src/io/github/sspanak/tt9/ime/modes/Mode123.java +++ b/src/io/github/sspanak/tt9/ime/modes/Mode123.java @@ -2,8 +2,6 @@ import java.util.ArrayList; -import io.github.sspanak.tt9.languages.Language; - public class Mode123 extends InputMode { public int getId() { return MODE_123; } @@ -12,7 +10,7 @@ public class Mode123 extends InputMode { } - public boolean onNumber(Language l, int key, boolean hold, int repeat) { + public boolean onNumber(int key, boolean hold, int repeat) { if (key != 0) { return false; } diff --git a/src/io/github/sspanak/tt9/ime/modes/ModeABC.java b/src/io/github/sspanak/tt9/ime/modes/ModeABC.java index f2e81404d..631740c88 100644 --- a/src/io/github/sspanak/tt9/ime/modes/ModeABC.java +++ b/src/io/github/sspanak/tt9/ime/modes/ModeABC.java @@ -9,13 +9,13 @@ public class ModeABC extends InputMode { private boolean shouldSelectNextLetter = false; - ModeABC() { - allowedTextCases.add(CASE_LOWER); - allowedTextCases.add(CASE_UPPER); + ModeABC(Language lang) { + changeLanguage(lang); } - public boolean onNumber(Language language, int key, boolean hold, int repeat) { + @Override + public boolean onNumber(int key, boolean hold, int repeat) { shouldSelectNextLetter = false; suggestions = language.getKeyCharacters(key); word = null; @@ -31,18 +31,29 @@ public boolean onNumber(Language language, int key, boolean hold, int repeat) { } - protected String adjustSuggestionTextCase(String word, int newTextCase, Language language) { + @Override + protected String adjustSuggestionTextCase(String word, int newTextCase) { return newTextCase == CASE_UPPER ? word.toUpperCase(language.getLocale()) : word.toLowerCase(language.getLocale()); } + @Override + public void changeLanguage(Language language) { + super.changeLanguage(language); + + allowedTextCases.clear(); + allowedTextCases.add(CASE_LOWER); + if (language.hasUpperCase()) { + allowedTextCases.add(CASE_UPPER); + } + } - final public boolean isABC() { return true; } - public int getSequenceLength() { return 1; } + @Override final public boolean isABC() { return true; } + @Override public int getSequenceLength() { return 1; } - public boolean shouldAcceptCurrentSuggestion(Language l, int key, boolean hold, boolean repeat) { return hold || !repeat; } - public boolean shouldTrackUpDown() { return true; } - public boolean shouldTrackLeftRight() { return true; } - public boolean shouldSelectNextSuggestion() { + @Override public boolean shouldAcceptCurrentSuggestion(int key, boolean hold, boolean repeat) { return hold || !repeat; } + @Override public boolean shouldTrackUpDown() { return true; } + @Override public boolean shouldTrackLeftRight() { return true; } + @Override public boolean shouldSelectNextSuggestion() { return shouldSelectNextLetter; } } diff --git a/src/io/github/sspanak/tt9/ime/modes/ModePredictive.java b/src/io/github/sspanak/tt9/ime/modes/ModePredictive.java index ef6887d28..36b01bc95 100644 --- a/src/io/github/sspanak/tt9/ime/modes/ModePredictive.java +++ b/src/io/github/sspanak/tt9/ime/modes/ModePredictive.java @@ -32,7 +32,6 @@ public class ModePredictive extends InputMode { private String stem = ""; // async suggestion handling - private Language currentLanguage = null; private String currentInputFieldWord = ""; private static Handler handleSuggestionsExternal; @@ -44,10 +43,8 @@ public class ModePredictive extends InputMode { private final String maxEmojiSequence; - ModePredictive(SettingsStore settings) { - allowedTextCases.add(CASE_LOWER); - allowedTextCases.add(CASE_CAPITALIZE); - allowedTextCases.add(CASE_UPPER); + ModePredictive(SettingsStore settings, Language lang) { + changeLanguage(lang); emptyDbWarning = new EmptyDatabaseWarning(settings); this.settings = settings; @@ -81,13 +78,13 @@ public boolean onBackspace() { @Override - public boolean onNumber(Language language, int key, boolean hold, int repeat) { + public boolean onNumber(int key, boolean hold, int repeat) { if (hold) { // hold to type any digit reset(); word = String.valueOf(key); } else if (key == 0 && repeat > 0) { - onDouble0(language); + onDouble0(); } else { // words super.reset(); @@ -102,7 +99,7 @@ public boolean onNumber(Language language, int key, boolean hold, int repeat) { * onDouble0 * Double "0" is a shortcut for the preferred character. */ - private void onDouble0(Language language) { + private void onDouble0() { try { reset(); word = settings.getDoubleZeroChar(); @@ -115,6 +112,19 @@ private void onDouble0(Language language) { } + @Override + public void changeLanguage(Language language) { + super.changeLanguage(language); + + allowedTextCases.clear(); + allowedTextCases.add(CASE_LOWER); + if (language.hasUpperCase()) { + allowedTextCases.add(CASE_CAPITALIZE); + allowedTextCases.add(CASE_UPPER); + } + } + + @Override public void reset() { super.reset(); @@ -156,7 +166,7 @@ public boolean clearWordStem() { * Note that you need to manually get the suggestions again to obtain a filtered list. */ @Override - public boolean setWordStem(Language language, String wordStem, boolean exact) { + public boolean setWordStem(String wordStem, boolean exact) { if (language == null || wordStem == null || wordStem.length() < 1) { return false; } @@ -202,7 +212,7 @@ public boolean isStemFilterFuzzy() { * Similar to "loadSuggestions()", but loads suggestions that are not in the database. * Returns "false", when there are no static suggestions for the current digitSequence. */ - private boolean loadStaticSuggestions(Language language) { + private boolean loadStaticSuggestions() { if (digitSequence.equals("0")) { stem = ""; suggestions = language.getKeyCharacters(0, false); @@ -231,8 +241,8 @@ private boolean loadStaticSuggestions(Language language) { * See: generatePossibleCompletions() */ @Override - public boolean loadSuggestions(Handler handler, Language language, String currentWord) { - if (loadStaticSuggestions(language)) { + public boolean loadSuggestions(Handler handler, String currentWord) { + if (loadStaticSuggestions()) { super.onSuggestionsUpdated(handler); return true; } @@ -244,7 +254,6 @@ public boolean loadSuggestions(Handler handler, Language language, String curren handleSuggestionsExternal = handler; currentInputFieldWord = currentWord.toLowerCase(language.getLocale()); - currentLanguage = language; super.reset(); DictionaryDb.getSuggestions( @@ -272,13 +281,13 @@ public void handleMessage(Message msg) { dbSuggestions = dbSuggestions == null ? new ArrayList<>() : dbSuggestions; if (dbSuggestions.size() == 0 && digitSequence.length() > 0) { - emptyDbWarning.emitOnce(currentLanguage); - dbSuggestions = generatePossibleCompletions(currentLanguage, currentInputFieldWord); + emptyDbWarning.emitOnce(language); + dbSuggestions = generatePossibleCompletions(currentInputFieldWord); } suggestions.clear(); suggestStem(); - suggestions.addAll(generatePossibleStemVariations(currentLanguage, dbSuggestions)); + suggestions.addAll(generatePossibleStemVariations(dbSuggestions)); suggestMoreWords(dbSuggestions); ModePredictive.super.onSuggestionsUpdated(handleSuggestionsExternal); @@ -295,7 +304,7 @@ public void handleMessage(Message msg) { * For example, if the word is "missin_" and the last pressed key is "4", the results would be: * | missing | missinh | missini | */ - private ArrayList generatePossibleCompletions(Language language, String baseWord) { + private ArrayList generatePossibleCompletions(String baseWord) { ArrayList generatedWords = new ArrayList<>(); // Make sure the displayed word and the digit sequence, we will be generating suggestions from, @@ -334,14 +343,14 @@ private ArrayList generatePossibleCompletions(Language language, String * generate: "extrb" and "extrc". This is useful for typing an unknown word, that is similar to * the ones in the dictionary. */ - private ArrayList generatePossibleStemVariations(Language language, ArrayList dbSuggestions) { + private ArrayList generatePossibleStemVariations(ArrayList dbSuggestions) { ArrayList variations = new ArrayList<>(); if (stem.length() == 0) { return variations; } if (isStemFuzzy && stem.length() == digitSequence.length() - 1) { - ArrayList allPossibleVariations = generatePossibleCompletions(language, stem); + ArrayList allPossibleVariations = generatePossibleCompletions(stem); // first add the known words, because it makes more sense to see them first for (String word : allPossibleVariations) { @@ -391,7 +400,7 @@ private void suggestMoreWords(ArrayList newSuggestions) { * Bring this word up in the suggestions list next time. */ @Override - public void onAcceptSuggestion(Language language, String currentWord) { + public void onAcceptSuggestion(String currentWord) { lastAcceptedWord = currentWord; lastAcceptedSequence = digitSequence; reset(); @@ -425,7 +434,7 @@ public void onAcceptSuggestion(Language language, String currentWord) { * or Dutch words such as: "'s-Hertogenbosch". */ @Override - protected String adjustSuggestionTextCase(String word, int newTextCase, Language language) { + protected String adjustSuggestionTextCase(String word, int newTextCase) { switch (newTextCase) { case CASE_UPPER: return word.toUpperCase(language.getLocale()); @@ -492,7 +501,7 @@ public void nextTextCase() { * we also increase its' priority. This function determines whether we want to do all this or not. */ @Override - public boolean shouldAcceptCurrentSuggestion(Language language, int key, boolean hold, boolean repeat) { + public boolean shouldAcceptCurrentSuggestion(int key, boolean hold, boolean repeat) { return hold // Quickly accept suggestions using "space" instead of pressing "ok" then "space" diff --git a/src/io/github/sspanak/tt9/languages/Language.java b/src/io/github/sspanak/tt9/languages/Language.java index 80158d8ba..d62120fc9 100644 --- a/src/io/github/sspanak/tt9/languages/Language.java +++ b/src/io/github/sspanak/tt9/languages/Language.java @@ -68,6 +68,11 @@ final public int getAbcIcon(boolean lowerCase) { final public boolean isPunctuationPartOfWords() { return isPunctuationPartOfWords; } + final public boolean hasUpperCase() { + return abcUpperCaseIcon != 0; + } + + /* ************ utility ************ */ /** diff --git a/src/io/github/sspanak/tt9/preferences/SettingsStore.java b/src/io/github/sspanak/tt9/preferences/SettingsStore.java index 4a1711408..504092499 100644 --- a/src/io/github/sspanak/tt9/preferences/SettingsStore.java +++ b/src/io/github/sspanak/tt9/preferences/SettingsStore.java @@ -140,14 +140,18 @@ public int getInputMode() { return prefs.getInt("pref_input_mode", InputMode.MODE_PREDICTIVE); } - public void saveInputMode(InputMode mode) { - if (mode == null) { - Logger.w("tt9/saveInputMode", "Not saving NULL input mode"); - return; - } + public void saveInputMode(int mode) { + boolean isModeValid = isIntInList( + mode, + new ArrayList<>(Arrays.asList(InputMode.MODE_123, InputMode.MODE_PREDICTIVE, InputMode.MODE_ABC)), + "tt9/saveInputMode", + "Not saving invalid input mode: " + mode + ); - prefsEditor.putInt("pref_input_mode", mode.getId()); - prefsEditor.apply(); + if (isModeValid) { + prefsEditor.putInt("pref_input_mode", mode); + prefsEditor.apply(); + } }