From ee19f08b4305f4641a20bb15e4879047a14dc148 Mon Sep 17 00:00:00 2001 From: sspanak Date: Tue, 17 Jun 2025 15:18:59 +0300 Subject: [PATCH] restricted the text case changes at the beginning of a line, before typing anything, when 'Automatic Capital Letters after a Newline' option is on --- .../io/github/sspanak/tt9/ime/CommandHandler.java | 8 ++++---- .../io/github/sspanak/tt9/ime/modes/InputMode.java | 7 ++++++- .../github/sspanak/tt9/ime/modes/ModeIdeograms.java | 2 +- .../io/github/sspanak/tt9/ime/modes/ModeWords.java | 12 +++++++++--- 4 files changed, 20 insertions(+), 9 deletions(-) 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 3a23b79d..f52f9733 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,13 +209,13 @@ abstract public class CommandHandler extends TextEditingHandler { protected boolean nextTextCase() { - if (!mInputMode.nextTextCase()) { + if (!mInputMode.nextTextCase(true)) { return false; } // if there are no suggestions or they are special chars, we don't need to adjust their text case - final String before = suggestionOps.isEmpty() || mInputMode.getSequence().isEmpty() ? "" : suggestionOps.getCurrent(); - if (before.isEmpty() || !Character.isAlphabetic(before.charAt(0))) { + final String currentWord = suggestionOps.isEmpty() || mInputMode.getSequence().isEmpty() ? "" : suggestionOps.getCurrent(); + if (currentWord.isEmpty() || !Character.isAlphabetic(currentWord.charAt(0))) { settings.saveTextCase(mInputMode.getTextCase()); return true; } @@ -227,7 +227,7 @@ abstract public class CommandHandler extends TextEditingHandler { currentSuggestionIndex = suggestionOps.containsStem() ? currentSuggestionIndex - 1 : currentSuggestionIndex; for (int retries = 0; retries <= 2; retries++) { - if (!before.equals(mInputMode.getSuggestions().get(currentSuggestionIndex)) || !mInputMode.nextTextCase()) { + if (!currentWord.equals(mInputMode.getSuggestions().get(currentSuggestionIndex)) || !mInputMode.nextTextCase(false)) { break; } } 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 bb38bb81..a0cb5d8a 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 @@ -203,7 +203,12 @@ abstract public class InputMode { textCase = allowedTextCases.get(0); } - public boolean nextTextCase() { + /** + * Switches to the next available text case. Returns "false" when the language has no upper case. + * 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(boolean analyzeSurroundingText) { 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..9c0400d1 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(boolean analyzeSurroundingText) { 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 df67d8e3..35247b73 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 @@ -381,10 +381,16 @@ class ModeWords extends ModeCheonjiin { }; } - @Override - public boolean nextTextCase() { - boolean changed = super.nextTextCase(); + public boolean nextTextCase(boolean analyzeSurroundingText) { + boolean changed = super.nextTextCase(analyzeSurroundingText); + + // Prevent lowercase at the beginning of a line when the respective setting is enabled. + // "analyzeSurroundingText" is true only when Shift is pressed to avoid expensive + // calls to getStringBeforeCursor(). + if (analyzeSurroundingText && textCase == CASE_LOWER && language.hasUpperCase() && settings.getAutoCapitalsAfterNewline() && textField.getStringBeforeCursor(1).equals("\n")) { + changed = super.nextTextCase(analyzeSurroundingText); + } // since it's a user's choice, the default matters no more textFieldTextCase = changed ? CASE_UNDEFINED : textFieldTextCase;