From 8f3105ff9bc331a3d664cf06793d47f4763db3c5 Mon Sep 17 00:00:00 2001 From: Gilles Debunne Date: Mon, 3 Oct 2011 18:28:59 -0700 Subject: 5402566: Copy/cut icons do not appear if the text is Japanese only When the word iterator return an empty range, select an arbitrary character so that cut/copy icons are available. Change-Id: I16e5a3c7f10886db967d870706da7f2d690af013 --- core/java/android/widget/TextView.java | 47 ++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index f833bb5590cf..478158f9b2a5 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -8925,10 +8925,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // If a URLSpan (web address, email, phone...) is found at that position, select it. URLSpan[] urlSpans = ((Spanned) mText).getSpans(minOffset, maxOffset, URLSpan.class); - if (urlSpans.length == 1) { - URLSpan url = urlSpans[0]; - selectionStart = ((Spanned) mText).getSpanStart(url); - selectionEnd = ((Spanned) mText).getSpanEnd(url); + if (urlSpans.length >= 1) { + URLSpan urlSpan = urlSpans[0]; + selectionStart = ((Spanned) mText).getSpanStart(urlSpan); + selectionEnd = ((Spanned) mText).getSpanEnd(urlSpan); } else { final int shift = prepareWordIterator(minOffset, maxOffset); @@ -8939,10 +8939,42 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener selectionEnd = mWordIterator.getEnd(maxOffset - shift); if (selectionEnd == BreakIterator.DONE) return false; selectionEnd += shift; + + if (selectionStart == selectionEnd) { + // Possible when the word iterator does not properly handle the text's language + long range = getCharRange(selectionStart); + selectionStart = extractRangeStartFromLong(range); + selectionEnd = extractRangeEndFromLong(range); + } } Selection.setSelection((Spannable) mText, selectionStart, selectionEnd); - return true; + return selectionEnd > selectionStart; + } + + private long getCharRange(int offset) { + final int textLength = mText.length(); + if (offset + 1 < textLength) { + final char currentChar = mText.charAt(offset); + final char nextChar = mText.charAt(offset + 1); + if (Character.isSurrogatePair(currentChar, nextChar)) { + return packRangeInLong(offset, offset + 2); + } + } + if (offset < textLength) { + return packRangeInLong(offset, offset + 1); + } + if (offset - 2 >= 0) { + final char previousChar = mText.charAt(offset - 1); + final char previousPreviousChar = mText.charAt(offset - 2); + if (Character.isSurrogatePair(previousPreviousChar, previousChar)) { + return packRangeInLong(offset - 2, offset); + } + } + if (offset - 1 >= 0) { + return packRangeInLong(offset - 1, offset); + } + return packRangeInLong(offset, offset); } int prepareWordIterator(int start, int end) { @@ -9330,7 +9362,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // Start a new selection if (!handled) { - handled = startSelectionActionMode(); + vibrate = handled = startSelectionActionMode(); } if (vibrate) { @@ -10166,8 +10198,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (!hasSelection()) { // There may already be a selection on device rotation - boolean currentWordSelected = selectCurrentWord(); - if (!currentWordSelected) { + if (!selectCurrentWord()) { // No word found under cursor or text selection not permitted. return false; } -- cgit v1.2.3-59-g8ed1b