diff --git a/app/src/main/java/io/github/sspanak/tt9/ime/CommandHandler.java b/app/src/main/java/io/github/sspanak/tt9/ime/CommandHandler.java index 6e7f1f08..5f46f05d 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ime/CommandHandler.java +++ b/app/src/main/java/io/github/sspanak/tt9/ime/CommandHandler.java @@ -209,36 +209,27 @@ abstract public class CommandHandler extends TextEditingHandler { protected boolean nextTextCase() { - if (!mInputMode.nextTextCase()) { + final String currentWord = suggestionOps.isEmpty() || mInputMode.getSequence().isEmpty() ? "" : suggestionOps.getCurrent(); + + if (!mInputMode.nextTextCase(currentWord)) { return false; } mInputMode.skipNextTextCaseDetection(); + settings.saveTextCase(mInputMode.getTextCase()); // if there are no suggestions or they are special chars, we don't need to adjust their text case - final String currentWord = suggestionOps.isEmpty() || mInputMode.getSequence().isEmpty() ? "" : suggestionOps.getCurrent(); - if (currentWord.isEmpty() || !Character.isAlphabetic(currentWord.charAt(0))) { - settings.saveTextCase(mInputMode.getTextCase()); + if (currentWord.isEmpty() || (currentWord.length() == 1 && !Character.isAlphabetic(currentWord.charAt(0)))) { return true; } - // When we are in AUTO mode and current dictionary word is in uppercase, - // the mode would switch to UPPERCASE, but visually, the word would not change. - // This is why we retry using the code below, until there is a visual change. + // if there are suggestions, we need to adjust their text case to acknowledge the change int currentSuggestionIndex = suggestionOps.getCurrentIndex(); currentSuggestionIndex = suggestionOps.containsStem() ? currentSuggestionIndex - 1 : currentSuggestionIndex; - for (int retries = 0; retries <= 2; retries++) { - if (!currentWord.equals(mInputMode.getSuggestions().get(currentSuggestionIndex)) || !mInputMode.nextTextCase()) { - break; - } - } - suggestionOps.set(mInputMode.getSuggestions(), currentSuggestionIndex, mInputMode.containsGeneratedSuggestions()); textField.setComposingText(suggestionOps.getCurrent()); - settings.saveTextCase(mInputMode.getTextCase()); - return true; } diff --git a/app/src/main/java/io/github/sspanak/tt9/ime/modes/InputMode.java b/app/src/main/java/io/github/sspanak/tt9/ime/modes/InputMode.java index 6bfdb06b..de7d22d0 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ime/modes/InputMode.java +++ b/app/src/main/java/io/github/sspanak/tt9/ime/modes/InputMode.java @@ -206,7 +206,7 @@ abstract public class InputMode { * If "analyzeSurroundingText" is true, and when the mode supports text analyzing, it may apply * additional logic to determine the next valid text case. */ - public boolean nextTextCase() { + public boolean nextTextCase(@Nullable String currentWord) { if (!language.hasUpperCase()) { return false; } diff --git a/app/src/main/java/io/github/sspanak/tt9/ime/modes/ModeIdeograms.java b/app/src/main/java/io/github/sspanak/tt9/ime/modes/ModeIdeograms.java index 269238b5..b7e187c9 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ime/modes/ModeIdeograms.java +++ b/app/src/main/java/io/github/sspanak/tt9/ime/modes/ModeIdeograms.java @@ -30,7 +30,7 @@ public class ModeIdeograms extends ModeWords { @Override protected String adjustSuggestionTextCase(String word, int newTextCase) { return word; } @Override public void determineNextWordTextCase(int nextDigit) {} - @Override public boolean nextTextCase() { return false; } + @Override public boolean nextTextCase(@Nullable String currentWord) { return false; } @Override diff --git a/app/src/main/java/io/github/sspanak/tt9/ime/modes/ModeWords.java b/app/src/main/java/io/github/sspanak/tt9/ime/modes/ModeWords.java index 5034606a..905bd707 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ime/modes/ModeWords.java +++ b/app/src/main/java/io/github/sspanak/tt9/ime/modes/ModeWords.java @@ -382,12 +382,18 @@ class ModeWords extends ModeCheonjiin { } @Override - public boolean nextTextCase() { - // convert any internally used text cases to user-friendly, because this is what the user - // is allowed to choose from. - textCase = getTextCase(); + public boolean nextTextCase(@Nullable String currentWord) { + if (currentWord == null || currentWord.isEmpty() || (currentWord.length() == 1 && !Character.isAlphabetic(currentWord.charAt(0)))) { + textCase = getTextCase(); + } else { + textCase = new Text(language, currentWord).getTextCase(); + } - boolean changed = super.nextTextCase(); + // Skip capitalized text for words like: 've, 's, 'll, etc... only allow upper and lower cases. + boolean changed = super.nextTextCase(currentWord); + if (textCase != CASE_LOWER && textCase != CASE_UPPER && currentWord != null && currentWord.length() > 1 && !Character.isAlphabetic(currentWord.charAt(0))) { + changed = super.nextTextCase(currentWord); + } // since it's a user's choice, the default matters no more textFieldTextCase = changed ? CASE_UNDEFINED : textFieldTextCase; diff --git a/app/src/main/java/io/github/sspanak/tt9/util/Text.java b/app/src/main/java/io/github/sspanak/tt9/util/Text.java index d568d7ae..e84090c4 100644 --- a/app/src/main/java/io/github/sspanak/tt9/util/Text.java +++ b/app/src/main/java/io/github/sspanak/tt9/util/Text.java @@ -36,7 +36,7 @@ public class Text extends TextTools { public String capitalize() { - if (language == null || text == null || text.isEmpty() || !language.hasUpperCase()) { + if (language == null || text == null || text.isEmpty() || !language.hasUpperCase() || !Character.isAlphabetic(text.charAt(0))) { return text; } @@ -141,12 +141,24 @@ public class Text extends TextTools { return false; } - if (!Character.isUpperCase(text.charAt(0))) { - return false; - } + char[] chars = text.toCharArray(); + boolean firstLetterFound = false; - for (int i = 1, end = text.length(); i < end; i++) { - if (Character.isUpperCase(text.charAt(i))) { + for (int i = 0, end = text.length(); i < end; i++) { + if (!Character.isAlphabetic(chars[i])) { + continue; + } + + if (!firstLetterFound) { + if (Character.isUpperCase(chars[i])) { + firstLetterFound = true; + continue; + } else { + return false; + } + } + + if (Character.isUpperCase(chars[i])) { return false; } }