From 83162821c7a721382791acddf5be136d1130f8b1 Mon Sep 17 00:00:00 2001 From: Justin Ghan Date: Tue, 4 Oct 2022 12:17:28 -0700 Subject: [PATCH] Fix whitespace removal bug The implementation of whitespace removal in performHandwritingDeleteGesture had a bug causing an IndexOutOfBoundsException when the whitespace was at the start or end of the text. This also fixes the whitespace removal code in performHandwritingJoinOrSplitGesture to properly handle supplementary characters. Bug: 243983058 Test: atest android.widget.cts.TextViewHandwritingGestureTest Change-Id: I3cfef91d05d5619668ccfc0d1259b6b1fd96bed9 --- core/java/android/widget/TextView.java | 27 +++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index da786f3a95be7..b339d76938afe 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -9358,10 +9358,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // - The deleted text is at the end of the text // e.g. "one [deleted]" -> "one |" -> "one|" // (The pipe | indicates the cursor position.) - while (start > 0 && TextUtils.isWhitespaceExceptNewline(codePointBeforeStart)) { + do { start -= Character.charCount(codePointBeforeStart); + if (start == 0) break; codePointBeforeStart = Character.codePointBefore(mText, start); - } + } while (TextUtils.isWhitespaceExceptNewline(codePointBeforeStart)); } else if (TextUtils.isWhitespaceExceptNewline(codePointAtEnd) && (TextUtils.isWhitespace(codePointBeforeStart) || TextUtils.isPunctuation(codePointBeforeStart))) { @@ -9373,11 +9374,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // - The deleted text is at the start of the text // e.g. "[deleted] two" -> "| two" -> "|two" // (The pipe | indicates the cursor position.) - while (end < mText.length() - && TextUtils.isWhitespaceExceptNewline(codePointAtEnd)) { + do { end += Character.charCount(codePointAtEnd); + if (end == mText.length()) break; codePointAtEnd = Character.codePointAt(mText, end); - } + } while (TextUtils.isWhitespaceExceptNewline(codePointAtEnd)); } } @@ -9487,11 +9488,19 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } int endOffset = startOffset; - while (startOffset > 0 && Character.isWhitespace(mText.charAt(startOffset - 1))) { - startOffset--; + while (startOffset > 0) { + int codePointBeforeStart = Character.codePointBefore(mText, startOffset); + if (!TextUtils.isWhitespace(codePointBeforeStart)) { + break; + } + startOffset -= Character.charCount(codePointBeforeStart); } - while (endOffset < mText.length() && Character.isWhitespace(mText.charAt(endOffset))) { - endOffset++; + while (endOffset < mText.length()) { + int codePointAtEnd = Character.codePointAt(mText, endOffset); + if (!TextUtils.isWhitespace(codePointAtEnd)) { + break; + } + endOffset += Character.charCount(codePointAtEnd); } if (startOffset < endOffset) { getEditableText().delete(startOffset, endOffset);