am 52fdaa2c: Merge "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"

* commit '52fdaa2cd8b6903fcf1dcab23b786e917323241c':
  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
main
Jean Chalard 2014-05-23 09:45:48 +00:00 committed by Android Git Automerger
commit f4d447e40a
3 changed files with 72 additions and 5 deletions

View File

@ -192,7 +192,6 @@ public final class Constants {
public static final int CODE_SPACE = ' '; public static final int CODE_SPACE = ' ';
public static final int CODE_PERIOD = '.'; public static final int CODE_PERIOD = '.';
public static final int CODE_COMMA = ','; 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_DASH = '-';
public static final int CODE_SINGLE_QUOTE = '\''; public static final int CODE_SINGLE_QUOTE = '\'';
public static final int CODE_DOUBLE_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_SQUARE_BRACKET = ']';
public static final int CODE_CLOSING_CURLY_BRACKET = '}'; public static final int CODE_CLOSING_CURLY_BRACKET = '}';
public static final int CODE_CLOSING_ANGLE_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. * Special keys code. Must be negative.

View File

@ -61,6 +61,22 @@ public final class CapsModeUtils {
|| WordComposer.CAPS_MODE_AUTO_SHIFT_LOCKED == mode; || 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 * 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 * the text. Only the mode bits set in <var>reqModes</var> will be
@ -115,8 +131,7 @@ public final class CapsModeUtils {
} else { } else {
for (i = cs.length(); i > 0; i--) { for (i = cs.length(); i > 0; i--) {
final char c = cs.charAt(i - 1); final char c = cs.charAt(i - 1);
if (c != Constants.CODE_DOUBLE_QUOTE && c != Constants.CODE_SINGLE_QUOTE if (!isStartPunctuation(c)) {
&& Character.getType(c) != Character.START_PUNCTUATION) {
break; 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 // 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 // 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 : // 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) // On START : (just before the first period)
// letter => WORD // letter => WORD
// digit => NUMBER if German; end with caps otherwise
// whitespace => end with no caps (it was a stand-alone period) // whitespace => end with no caps (it was a stand-alone period)
// otherwise => end with caps (several periods/symbols in a row) // otherwise => end with caps (several periods/symbols in a row)
// On WORD : (within the word just before the first period) // On WORD : (within the word just before the first period)
@ -228,6 +246,11 @@ public final class CapsModeUtils {
// letter => LETTER // letter => LETTER
// period => PERIOD // period => PERIOD
// otherwise => end with no caps (it was an abbreviation) // 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 // "Not an abbreviation" in the above chart essentially covers cases like "...yes.". This
// should capitalize. // should capitalize.
@ -235,6 +258,7 @@ public final class CapsModeUtils {
final int WORD = 1; final int WORD = 1;
final int PERIOD = 2; final int PERIOD = 2;
final int LETTER = 3; final int LETTER = 3;
final int NUMBER = 4;
final int caps = (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS final int caps = (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS
| TextUtils.CAP_MODE_SENTENCES) & reqModes; | TextUtils.CAP_MODE_SENTENCES) & reqModes;
final int noCaps = (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS) & reqModes; final int noCaps = (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS) & reqModes;
@ -247,6 +271,8 @@ public final class CapsModeUtils {
state = WORD; state = WORD;
} else if (Character.isWhitespace(c)) { } else if (Character.isWhitespace(c)) {
return noCaps; return noCaps;
} else if (Character.isDigit(c) && spacingAndPunctuations.mUsesGermanRules) {
state = NUMBER;
} else { } else {
return caps; return caps;
} }
@ -275,6 +301,15 @@ public final class CapsModeUtils {
} else { } else {
return noCaps; 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. // Here we arrived at the start of the line. This should behave exactly like whitespace.

View File

@ -78,4 +78,35 @@ public class ShiftModeTests extends InputTestsBase {
runMessages(); runMessages();
assertTrue("Caps after a while after repeating Backspace a lot", isCapsModeAutoShifted()); 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());
}
} }