diff --git a/app/src/main/java/helium314/keyboard/keyboard/KeyboardActionListenerImpl.kt b/app/src/main/java/helium314/keyboard/keyboard/KeyboardActionListenerImpl.kt index 2f7d01e41..0ed503958 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/KeyboardActionListenerImpl.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/KeyboardActionListenerImpl.kt @@ -113,15 +113,17 @@ class KeyboardActionListenerImpl(private val latinIME: LatinIME, private val inp var actualSteps = 0 // corrected steps to avoid splitting chars belonging to the same codepoint if (steps > 0) { - val text = inputLogic.mConnection.getSelectedText(0) ?: return steps - loopOverCodePoints(text) { - actualSteps += Character.charCount(it) + val text = inputLogic.mConnection.getSelectedText(0) + if (text == null) actualSteps = steps + else loopOverCodePoints(text) { cp, charCount -> + actualSteps += charCount actualSteps >= steps } } else { - val text = inputLogic.mConnection.getTextBeforeCursor(-steps * 4, 0) ?: return steps - loopOverCodePointsBackwards(text) { - actualSteps -= Character.charCount(it) + val text = inputLogic.mConnection.getTextBeforeCursor(-steps * 4, 0) + if (text == null) actualSteps = steps + else loopOverCodePointsBackwards(text) { cp, charCount -> + actualSteps -= charCount actualSteps <= steps } } @@ -217,12 +219,12 @@ class KeyboardActionListenerImpl(private val latinIME: LatinIME, private val inp private fun positiveMoveSteps(text: CharSequence, steps: Int): Int { var actualSteps = 0 // corrected steps to avoid splitting chars belonging to the same codepoint - loopOverCodePoints(text) { - if (StringUtils.mightBeEmoji(it)) { + loopOverCodePoints(text) { cp, charCount -> + if (StringUtils.mightBeEmoji(cp)) { actualSteps = 0 true } - actualSteps += Character.charCount(it) + actualSteps += charCount actualSteps >= steps } return min(actualSteps, text.length) @@ -231,12 +233,12 @@ class KeyboardActionListenerImpl(private val latinIME: LatinIME, private val inp private fun negativeMoveSteps(text: CharSequence, steps: Int): Int { var actualSteps = 0 // corrected steps to avoid splitting chars belonging to the same codepoint - loopOverCodePointsBackwards(text) { - if (StringUtils.mightBeEmoji(it)) { + loopOverCodePointsBackwards(text) { cp, charCount -> + if (StringUtils.mightBeEmoji(cp)) { actualSteps = 0 true } - actualSteps -= Character.charCount(it) + actualSteps -= charCount actualSteps <= steps } return -min(-actualSteps, text.length) diff --git a/app/src/main/java/helium314/keyboard/latin/common/StringUtils.kt b/app/src/main/java/helium314/keyboard/latin/common/StringUtils.kt index 56fd515bb..302128080 100644 --- a/app/src/main/java/helium314/keyboard/latin/common/StringUtils.kt +++ b/app/src/main/java/helium314/keyboard/latin/common/StringUtils.kt @@ -9,33 +9,35 @@ import helium314.keyboard.latin.settings.SpacingAndPunctuations import java.math.BigInteger import java.util.Locale -fun loopOverCodePoints(text: CharSequence, loop: (cp: Int) -> Boolean) { +fun loopOverCodePoints(text: CharSequence, loop: (cp: Int, charCount: Int) -> Boolean) { val s = text.toString() var offset = 0 while (offset < s.length) { val cp = s.codePointAt(offset) - if (loop(cp)) return - offset += Character.charCount(cp) + val charCount = Character.charCount(cp) + if (loop(cp, charCount)) return + offset += charCount } } -fun loopOverCodePointsBackwards(text: CharSequence, loop: (cp: Int) -> Boolean) { +fun loopOverCodePointsBackwards(text: CharSequence, loop: (cp: Int, charCount: Int) -> Boolean) { val s = text.toString() var offset = s.length while (offset > 0) { val cp = s.codePointBefore(offset) - if (loop(cp)) return - offset -= Character.charCount(cp) + val charCount = Character.charCount(cp) + if (loop(cp, charCount)) return + offset -= charCount } } fun nonWordCodePointAndNoSpaceBeforeCursor(text: CharSequence, spacingAndPunctuations: SpacingAndPunctuations): Boolean { var space = false var nonWordCodePoint = false - loopOverCodePointsBackwards(text) { - if (!space && Character.isWhitespace(it)) space = true + loopOverCodePointsBackwards(text) { cp, charCount -> + if (!space && Character.isWhitespace(cp)) space = true // treat double quote like a word codepoint for the purpose of this function (not great, maybe clarify name, or extend list of chars?) - if (!nonWordCodePoint && !spacingAndPunctuations.isWordCodePoint(it) && it != '"'.code) { + if (!nonWordCodePoint && !spacingAndPunctuations.isWordCodePoint(cp) && cp != '"'.code) { nonWordCodePoint = true } space && nonWordCodePoint // stop if both are found @@ -45,9 +47,9 @@ fun nonWordCodePointAndNoSpaceBeforeCursor(text: CharSequence, spacingAndPunctua fun hasLetterBeforeLastSpaceBeforeCursor(text: CharSequence): Boolean { var letter = false - loopOverCodePointsBackwards(text) { - if (Character.isWhitespace(it)) true - else if (Character.isLetter(it)) { + loopOverCodePointsBackwards(text) { cp, charCount -> + if (Character.isWhitespace(cp)) true + else if (Character.isLetter(cp)) { letter = true true }