Fix some auto-caps problems:
- (mainly for Spanish) auto-caps after inverted bang and what - (German only) don't auto-cap after digits-period-space Bug: 15177663 Bug: 12206753 Change-Id: Ia214bc067319469d9debbbfbdcb1dcff980847f0
This commit is contained in:
parent
fd8c3792d9
commit
cfdb1b8d26
3 changed files with 72 additions and 5 deletions
|
@ -192,7 +192,6 @@ public final class Constants {
|
|||
public static final int CODE_SPACE = ' ';
|
||||
public static final int CODE_PERIOD = '.';
|
||||
public static final int CODE_COMMA = ',';
|
||||
public static final int CODE_ARMENIAN_PERIOD = 0x0589;
|
||||
public static final int CODE_DASH = '-';
|
||||
public static final int CODE_SINGLE_QUOTE = '\'';
|
||||
public static final int CODE_DOUBLE_QUOTE = '"';
|
||||
|
@ -208,6 +207,8 @@ public final class Constants {
|
|||
public static final int CODE_CLOSING_SQUARE_BRACKET = ']';
|
||||
public static final int CODE_CLOSING_CURLY_BRACKET = '}';
|
||||
public static final int CODE_CLOSING_ANGLE_BRACKET = '>';
|
||||
public static final int CODE_INVERTED_QUESTION_MARK = 0xBF; // ¿
|
||||
public static final int CODE_INVERTED_EXCLAMATION_MARK = 0xA1; // ¡
|
||||
|
||||
/**
|
||||
* Special keys code. Must be negative.
|
||||
|
|
|
@ -61,6 +61,22 @@ public final class CapsModeUtils {
|
|||
|| WordComposer.CAPS_MODE_AUTO_SHIFT_LOCKED == mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to find out if a code point is starting punctuation.
|
||||
*
|
||||
* This include the Unicode START_PUNCTUATION category, but also some other symbols that are
|
||||
* starting, like the inverted question mark or the double quote.
|
||||
*
|
||||
* @param codePoint the code point
|
||||
* @return true if it's starting punctuation, false otherwise.
|
||||
*/
|
||||
private static boolean isStartPunctuation(final int codePoint) {
|
||||
return (codePoint == Constants.CODE_DOUBLE_QUOTE || codePoint == Constants.CODE_SINGLE_QUOTE
|
||||
|| codePoint == Constants.CODE_INVERTED_QUESTION_MARK
|
||||
|| codePoint == Constants.CODE_INVERTED_EXCLAMATION_MARK
|
||||
|| Character.getType(codePoint) == Character.START_PUNCTUATION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine what caps mode should be in effect at the current offset in
|
||||
* the text. Only the mode bits set in <var>reqModes</var> will be
|
||||
|
@ -115,8 +131,7 @@ public final class CapsModeUtils {
|
|||
} else {
|
||||
for (i = cs.length(); i > 0; i--) {
|
||||
final char c = cs.charAt(i - 1);
|
||||
if (c != Constants.CODE_DOUBLE_QUOTE && c != Constants.CODE_SINGLE_QUOTE
|
||||
&& Character.getType(c) != Character.START_PUNCTUATION) {
|
||||
if (!isStartPunctuation(c)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -210,11 +225,14 @@ public final class CapsModeUtils {
|
|||
|
||||
// We found out that we have a period. We need to determine if this is a full stop or
|
||||
// otherwise sentence-ending period, or an abbreviation like "e.g.". An abbreviation
|
||||
// looks like (\w\.){2,}
|
||||
// looks like (\w\.){2,}. Moreover, in German, you put periods after digits for dates
|
||||
// and some other things, and in German specifically we need to not go into autocaps after
|
||||
// a whitespace-digits-period sequence.
|
||||
// To find out, we will have a simple state machine with the following states :
|
||||
// START, WORD, PERIOD, ABBREVIATION
|
||||
// START, WORD, PERIOD, ABBREVIATION, NUMBER
|
||||
// On START : (just before the first period)
|
||||
// letter => WORD
|
||||
// digit => NUMBER if German; end with caps otherwise
|
||||
// whitespace => end with no caps (it was a stand-alone period)
|
||||
// otherwise => end with caps (several periods/symbols in a row)
|
||||
// On WORD : (within the word just before the first period)
|
||||
|
@ -228,6 +246,11 @@ public final class CapsModeUtils {
|
|||
// letter => LETTER
|
||||
// period => PERIOD
|
||||
// otherwise => end with no caps (it was an abbreviation)
|
||||
// On NUMBER : (period immediately preceded by one or more digits)
|
||||
// digit => NUMBER
|
||||
// letter => LETTER (promote to word)
|
||||
// otherwise => end with no caps (it was a whitespace-digits-period sequence,
|
||||
// or a punctuation-digits-period sequence like "11.11.")
|
||||
// "Not an abbreviation" in the above chart essentially covers cases like "...yes.". This
|
||||
// should capitalize.
|
||||
|
||||
|
@ -235,6 +258,7 @@ public final class CapsModeUtils {
|
|||
final int WORD = 1;
|
||||
final int PERIOD = 2;
|
||||
final int LETTER = 3;
|
||||
final int NUMBER = 4;
|
||||
final int caps = (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS
|
||||
| TextUtils.CAP_MODE_SENTENCES) & reqModes;
|
||||
final int noCaps = (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS) & reqModes;
|
||||
|
@ -247,6 +271,8 @@ public final class CapsModeUtils {
|
|||
state = WORD;
|
||||
} else if (Character.isWhitespace(c)) {
|
||||
return noCaps;
|
||||
} else if (Character.isDigit(c) && spacingAndPunctuations.mUsesGermanRules) {
|
||||
state = NUMBER;
|
||||
} else {
|
||||
return caps;
|
||||
}
|
||||
|
@ -275,6 +301,15 @@ public final class CapsModeUtils {
|
|||
} else {
|
||||
return noCaps;
|
||||
}
|
||||
break;
|
||||
case NUMBER:
|
||||
if (Character.isLetter(c)) {
|
||||
state = WORD;
|
||||
} else if (Character.isDigit(c)) {
|
||||
state = NUMBER;
|
||||
} else {
|
||||
return noCaps;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Here we arrived at the start of the line. This should behave exactly like whitespace.
|
||||
|
|
|
@ -78,4 +78,35 @@ public class ShiftModeTests extends InputTestsBase {
|
|||
runMessages();
|
||||
assertTrue("Caps after a while after repeating Backspace a lot", isCapsModeAutoShifted());
|
||||
}
|
||||
|
||||
public void testAutoCapsAfterDigitsPeriod() {
|
||||
changeLanguage("en");
|
||||
type("On 22.11.");
|
||||
assertFalse("(English) Auto caps after digits-period", isCapsModeAutoShifted());
|
||||
type(" ");
|
||||
assertTrue("(English) Auto caps after digits-period-whitespace", isCapsModeAutoShifted());
|
||||
mEditText.setText("");
|
||||
changeLanguage("fr");
|
||||
type("Le 22.");
|
||||
assertFalse("(French) Auto caps after digits-period", isCapsModeAutoShifted());
|
||||
type(" ");
|
||||
assertTrue("(French) Auto caps after digits-period-whitespace", isCapsModeAutoShifted());
|
||||
mEditText.setText("");
|
||||
changeLanguage("de");
|
||||
type("Am 22.");
|
||||
assertFalse("(German) Auto caps after digits-period", isCapsModeAutoShifted());
|
||||
type(" ");
|
||||
// For German, no auto-caps in this case
|
||||
assertFalse("(German) Auto caps after digits-period-whitespace", isCapsModeAutoShifted());
|
||||
}
|
||||
|
||||
public void testAutoCapsAfterInvertedMarks() {
|
||||
changeLanguage("es");
|
||||
assertTrue("(Spanish) Auto caps at start", isCapsModeAutoShifted());
|
||||
type("Hey. ¿");
|
||||
assertTrue("(Spanish) Auto caps after inverted what", isCapsModeAutoShifted());
|
||||
mEditText.setText("");
|
||||
type("¡");
|
||||
assertTrue("(Spanish) Auto caps after inverted bang", isCapsModeAutoShifted());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue