Added support for Unicode surrogate characters in word selection
Inspired by https://review.source.android.com/#change,16606 Change-Id: I896354f5aba83c1919c008f07b6d0b2abf0b8e01
This commit is contained in:
@@ -7645,9 +7645,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
hasPrimaryClip());
|
||||
}
|
||||
|
||||
private boolean isWordCharacter(int position) {
|
||||
final char c = mTransformed.charAt(position);
|
||||
final int type = Character.getType(c);
|
||||
private boolean isWordCharacter(int c, int type) {
|
||||
return (c == '\'' || c == '"' ||
|
||||
type == Character.UPPERCASE_LETTER ||
|
||||
type == Character.LOWERCASE_LETTER ||
|
||||
@@ -7696,35 +7694,32 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
|
||||
int start = end;
|
||||
|
||||
for (; start > 0; start--) {
|
||||
if (start == end) {
|
||||
final char c = mTransformed.charAt(start - 1);
|
||||
final int type = Character.getType(c);
|
||||
if (start == end && type == Character.OTHER_PUNCTUATION) {
|
||||
// Cases where the text ends with a '.' and we select from the end of the line
|
||||
// (right after the dot), or when we select from the space character in "aaa, bbb".
|
||||
final char c = mTransformed.charAt(start - 1);
|
||||
final int type = Character.getType(c);
|
||||
if (type == Character.OTHER_PUNCTUATION) continue;
|
||||
continue;
|
||||
}
|
||||
if (type == Character.SURROGATE) { // Two Character codepoint
|
||||
end = start - 1; // Recheck as a pair when scanning forward
|
||||
continue;
|
||||
}
|
||||
if (!isWordCharacter(start - 1)) break;
|
||||
if (!isWordCharacter(c, type)) break;
|
||||
if ((end - start) > MAX_LENGTH) return -1;
|
||||
}
|
||||
|
||||
for (; end < len; end++) {
|
||||
if (!isWordCharacter(end)) break;
|
||||
final int c = Character.codePointAt(mTransformed, end);
|
||||
final int type = Character.getType(c);
|
||||
if (!isWordCharacter(c, type)) break;
|
||||
if ((end - start) > MAX_LENGTH) return -1;
|
||||
}
|
||||
|
||||
if (start == end) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
boolean hasLetter = false;
|
||||
for (int i = start; i < end; i++) {
|
||||
if (Character.isLetter(mTransformed.charAt(i))) {
|
||||
hasLetter = true;
|
||||
break;
|
||||
if (c > 0xFFFF) { // Two Character codepoint
|
||||
end++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasLetter) {
|
||||
if (start == end) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -231,12 +231,22 @@ public class TextViewWordLimitsTest extends AndroidTestCase {
|
||||
final String SURROGATE_SYMBOL = "\uD83D\uDE01\uD83D\uDE02\uD83D\uDE03"; // Three smileys
|
||||
|
||||
// Letter Other is included even when coded as surrogate pairs
|
||||
verifyWordLimits(SURROGATE_LETTER, 1, -1, -1);
|
||||
verifyWordLimits(SURROGATE_LETTER, 2, -1, -1);
|
||||
verifyWordLimits(SURROGATE_LETTER, 0, 0, 6);
|
||||
verifyWordLimits(SURROGATE_LETTER, 1, 0, 6);
|
||||
verifyWordLimits(SURROGATE_LETTER, 2, 0, 6);
|
||||
verifyWordLimits(SURROGATE_LETTER, 3, 0, 6);
|
||||
verifyWordLimits(SURROGATE_LETTER, 4, 0, 6);
|
||||
verifyWordLimits(SURROGATE_LETTER, 5, 0, 6);
|
||||
verifyWordLimits(SURROGATE_LETTER, 6, 0, 6);
|
||||
|
||||
// Not included classes are ignored even when coded as surrogate pairs
|
||||
verifyWordLimits(SURROGATE_SYMBOL, 0, -1, -1);
|
||||
verifyWordLimits(SURROGATE_SYMBOL, 1, -1, -1);
|
||||
verifyWordLimits(SURROGATE_SYMBOL, 2, -1, -1);
|
||||
verifyWordLimits(SURROGATE_SYMBOL, 3, -1, -1);
|
||||
verifyWordLimits(SURROGATE_SYMBOL, 4, -1, -1);
|
||||
verifyWordLimits(SURROGATE_SYMBOL, 5, -1, -1);
|
||||
verifyWordLimits(SURROGATE_SYMBOL, 6, -1, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user