Merge "Make the sentence separator a resource."

main
Jean Chalard 2013-10-08 06:44:20 +00:00 committed by Android (Google) Code Review
commit 36c56caee3
7 changed files with 73 additions and 62 deletions

View File

@ -26,4 +26,7 @@
<!-- Symbols that separate words. Adding armenian period and comma. --> <!-- Symbols that separate words. Adding armenian period and comma. -->
<!-- Don't remove the enclosing double quotes, they protect whitespace (not just U+0020) --> <!-- Don't remove the enclosing double quotes, they protect whitespace (not just U+0020) -->
<string name="symbols_word_separators">"&#x0009;&#x0020;\n"()[]{}*&amp;&lt;&gt;+=|.,;:!?/_\"&#x0589;&#x055D;</string> <string name="symbols_word_separators">"&#x0009;&#x0020;\n"()[]{}*&amp;&lt;&gt;+=|.,;:!?/_\"&#x0589;&#x055D;</string>
<!-- The sentence separator code point, for capitalization -->
<!-- U+0589: "։" ARMENIAN FULL STOP ; 589h = 1417d -->
<integer name="sentence_separator">1417</integer>
</resources> </resources>

View File

@ -31,6 +31,9 @@
<string name="symbols_word_separators">"&#x0009;&#x0020;\n"()[]{}*&amp;&lt;&gt;+=|.,;:!?/_\"</string> <string name="symbols_word_separators">"&#x0009;&#x0020;\n"()[]{}*&amp;&lt;&gt;+=|.,;:!?/_\"</string>
<!-- Word connectors --> <!-- Word connectors -->
<string name="symbols_word_connectors">\'-</string> <string name="symbols_word_connectors">\'-</string>
<!-- The sentence separator code point, for capitalization -->
<!-- U+002E: "." FULL STOP ; 2Eh = 46d -->
<integer name="sentence_separator">46</integer>
<!-- Whether this language uses spaces between words --> <!-- Whether this language uses spaces between words -->
<bool name="current_language_has_spaces">true</bool> <bool name="current_language_has_spaces">true</bool>

View File

@ -1411,14 +1411,15 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Called from the KeyboardSwitcher which needs to know auto caps state to display // Called from the KeyboardSwitcher which needs to know auto caps state to display
// the right layout. // the right layout.
public int getCurrentAutoCapsState() { public int getCurrentAutoCapsState() {
if (!mSettings.getCurrent().mAutoCap) return Constants.TextUtils.CAP_MODE_OFF; final SettingsValues currentSettingsValues = mSettings.getCurrent();
if (!currentSettingsValues.mAutoCap) return Constants.TextUtils.CAP_MODE_OFF;
final EditorInfo ei = getCurrentInputEditorInfo(); final EditorInfo ei = getCurrentInputEditorInfo();
if (ei == null) return Constants.TextUtils.CAP_MODE_OFF; if (ei == null) return Constants.TextUtils.CAP_MODE_OFF;
final int inputType = ei.inputType; final int inputType = ei.inputType;
// Warning: this depends on mSpaceState, which may not be the most current value. If // Warning: this depends on mSpaceState, which may not be the most current value. If
// mSpaceState gets updated later, whoever called this may need to be told about it. // mSpaceState gets updated later, whoever called this may need to be told about it.
return mConnection.getCursorCapsMode(inputType, mSubtypeSwitcher.getCurrentSubtypeLocale(), return mConnection.getCursorCapsMode(inputType, currentSettingsValues,
SPACE_STATE_PHANTOM == mSpaceState); SPACE_STATE_PHANTOM == mSpaceState);
} }
@ -1459,9 +1460,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} }
private boolean maybeDoubleSpacePeriod() { private boolean maybeDoubleSpacePeriod() {
final SettingsValues settingsValues = mSettings.getCurrent(); final SettingsValues currentSettingsValues = mSettings.getCurrent();
if (!settingsValues.mCorrectionEnabled) return false; if (!currentSettingsValues.mCorrectionEnabled) return false;
if (!settingsValues.mUseDoubleSpacePeriod) return false; if (!currentSettingsValues.mUseDoubleSpacePeriod) return false;
if (!mHandler.isAcceptingDoubleSpacePeriod()) return false; if (!mHandler.isAcceptingDoubleSpacePeriod()) return false;
// We only do this when we see two spaces and an accepted code point before the cursor. // We only do this when we see two spaces and an accepted code point before the cursor.
// The code point may be a surrogate pair but the two spaces may not, so we need 4 chars. // The code point may be a surrogate pair but the two spaces may not, so we need 4 chars.
@ -1480,7 +1481,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (canBeFollowedByDoubleSpacePeriod(firstCodePoint)) { if (canBeFollowedByDoubleSpacePeriod(firstCodePoint)) {
mHandler.cancelDoubleSpacePeriodTimer(); mHandler.cancelDoubleSpacePeriodTimer();
mConnection.deleteSurroundingText(2, 0); mConnection.deleteSurroundingText(2, 0);
final String textToInsert = ". "; final String textToInsert = new String(
new int[] { currentSettingsValues.mSentenceSeparator, Constants.CODE_SPACE },
0, 2);
mConnection.commitText(textToInsert, 1); mConnection.commitText(textToInsert, 1);
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
ResearchLogger.latinIME_maybeDoubleSpacePeriod(textToInsert, ResearchLogger.latinIME_maybeDoubleSpacePeriod(textToInsert,

View File

@ -245,11 +245,11 @@ public final class RichInputConnection {
* American English, it's just the most common set of rules for English). * American English, it's just the most common set of rules for English).
* *
* @param inputType a mask of the caps modes to test for. * @param inputType a mask of the caps modes to test for.
* @param locale what language should be considered. * @param settingsValues the values of the settings to use for locale and separators.
* @param hasSpaceBefore if we should consider there should be a space after the string. * @param hasSpaceBefore if we should consider there should be a space after the string.
* @return the caps modes that should be on as a set of bits * @return the caps modes that should be on as a set of bits
*/ */
public int getCursorCapsMode(final int inputType, final Locale locale, public int getCursorCapsMode(final int inputType, final SettingsValues settingsValues,
final boolean hasSpaceBefore) { final boolean hasSpaceBefore) {
mIC = mParent.getCurrentInputConnection(); mIC = mParent.getCurrentInputConnection();
if (null == mIC) return Constants.TextUtils.CAP_MODE_OFF; if (null == mIC) return Constants.TextUtils.CAP_MODE_OFF;
@ -277,8 +277,8 @@ public final class RichInputConnection {
} }
// This never calls InputConnection#getCapsMode - in fact, it's a static method that // This never calls InputConnection#getCapsMode - in fact, it's a static method that
// never blocks or initiates IPC. // never blocks or initiates IPC.
return CapsModeUtils.getCapsMode(mCommittedTextBeforeComposingText, inputType, locale, return CapsModeUtils.getCapsMode(mCommittedTextBeforeComposingText, inputType,
hasSpaceBefore); settingsValues, hasSpaceBefore);
} }
public int getCodePointBeforeCursor() { public int getCodePointBeforeCursor() {

View File

@ -24,6 +24,7 @@ import android.view.inputmethod.EditorInfo;
import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.keyboard.internal.KeySpecParser; import com.android.inputmethod.keyboard.internal.KeySpecParser;
import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.Dictionary; import com.android.inputmethod.latin.Dictionary;
import com.android.inputmethod.latin.InputAttributes; import com.android.inputmethod.latin.InputAttributes;
import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.R;
@ -57,6 +58,7 @@ public final class SettingsValues {
public final int[] mWordConnectors; public final int[] mWordConnectors;
public final SuggestedWords mSuggestPuncList; public final SuggestedWords mSuggestPuncList;
public final String mWordSeparators; public final String mWordSeparators;
public final int mSentenceSeparator;
public final CharSequence mHintToSaveText; public final CharSequence mHintToSaveText;
public final boolean mCurrentLanguageHasSpaces; public final boolean mCurrentLanguageHasSpaces;
@ -120,6 +122,7 @@ public final class SettingsValues {
R.string.suggested_punctuations)); R.string.suggested_punctuations));
mSuggestPuncList = createSuggestPuncList(suggestPuncsSpec); mSuggestPuncList = createSuggestPuncList(suggestPuncsSpec);
mWordSeparators = res.getString(R.string.symbols_word_separators); mWordSeparators = res.getString(R.string.symbols_word_separators);
mSentenceSeparator = res.getInteger(R.integer.sentence_separator);
mHintToSaveText = res.getText(R.string.hint_add_to_dictionary); mHintToSaveText = res.getText(R.string.hint_add_to_dictionary);
mCurrentLanguageHasSpaces = res.getBoolean(R.bool.current_language_has_spaces); mCurrentLanguageHasSpaces = res.getBoolean(R.bool.current_language_has_spaces);
@ -187,6 +190,7 @@ public final class SettingsValues {
Arrays.sort(mSymbolsFollowedBySpace); Arrays.sort(mSymbolsFollowedBySpace);
mWordConnectors = new int[] { '\'', '-' }; mWordConnectors = new int[] { '\'', '-' };
Arrays.sort(mWordConnectors); Arrays.sort(mWordConnectors);
mSentenceSeparator = Constants.CODE_PERIOD;
final String[] suggestPuncsSpec = new String[] { "!", "?", ",", ":", ";" }; final String[] suggestPuncsSpec = new String[] { "!", "?", ",", ":", ";" };
mSuggestPuncList = createSuggestPuncList(suggestPuncsSpec); mSuggestPuncList = createSuggestPuncList(suggestPuncsSpec);
mWordSeparators = "&\t \n()[]{}*&<>+=|.,;:!?/_\""; mWordSeparators = "&\t \n()[]{}*&<>+=|.,;:!?/_\"";

View File

@ -21,6 +21,7 @@ import android.text.TextUtils;
import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.WordComposer; import com.android.inputmethod.latin.WordComposer;
import com.android.inputmethod.latin.settings.SettingsValues;
import java.util.Locale; import java.util.Locale;
@ -60,11 +61,6 @@ public final class CapsModeUtils {
|| WordComposer.CAPS_MODE_AUTO_SHIFT_LOCKED == mode; || WordComposer.CAPS_MODE_AUTO_SHIFT_LOCKED == mode;
} }
private static boolean isPeriod(final int codePoint) {
// TODO: make this a resource.
return codePoint == Constants.CODE_PERIOD || codePoint == Constants.CODE_ARMENIAN_PERIOD;
}
/** /**
* 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
@ -78,7 +74,7 @@ public final class CapsModeUtils {
* @param reqModes The modes to be checked: may be any combination of * @param reqModes The modes to be checked: may be any combination of
* {@link TextUtils#CAP_MODE_CHARACTERS}, {@link TextUtils#CAP_MODE_WORDS}, and * {@link TextUtils#CAP_MODE_CHARACTERS}, {@link TextUtils#CAP_MODE_WORDS}, and
* {@link TextUtils#CAP_MODE_SENTENCES}. * {@link TextUtils#CAP_MODE_SENTENCES}.
* @param locale The locale to consider for capitalization rules * @param settingsValues The current settings values.
* @param hasSpaceBefore Whether we should consider there is a space inserted at the end of cs * @param hasSpaceBefore Whether we should consider there is a space inserted at the end of cs
* *
* @return Returns the actual capitalization modes that can be in effect * @return Returns the actual capitalization modes that can be in effect
@ -86,8 +82,8 @@ public final class CapsModeUtils {
* {@link TextUtils#CAP_MODE_CHARACTERS}, {@link TextUtils#CAP_MODE_WORDS}, and * {@link TextUtils#CAP_MODE_CHARACTERS}, {@link TextUtils#CAP_MODE_WORDS}, and
* {@link TextUtils#CAP_MODE_SENTENCES}. * {@link TextUtils#CAP_MODE_SENTENCES}.
*/ */
public static int getCapsMode(final CharSequence cs, final int reqModes, final Locale locale, public static int getCapsMode(final CharSequence cs, final int reqModes,
final boolean hasSpaceBefore) { final SettingsValues settingsValues, final boolean hasSpaceBefore) {
// Quick description of what we want to do: // Quick description of what we want to do:
// CAP_MODE_CHARACTERS is always on. // CAP_MODE_CHARACTERS is always on.
// CAP_MODE_WORDS is on if there is some whitespace before the cursor. // CAP_MODE_WORDS is on if there is some whitespace before the cursor.
@ -172,7 +168,7 @@ public final class CapsModeUtils {
// mark as the exact thing quoted and handling the surrounding punctuation independently, // mark as the exact thing quoted and handling the surrounding punctuation independently,
// e.g. <<Did he say, "let's go home"?>> // e.g. <<Did he say, "let's go home"?>>
// Hence, specifically for English, we treat this special case here. // Hence, specifically for English, we treat this special case here.
if (Locale.ENGLISH.getLanguage().equals(locale.getLanguage())) { if (Locale.ENGLISH.getLanguage().equals(settingsValues.mLocale.getLanguage())) {
for (; j > 0; j--) { for (; j > 0; j--) {
// Here we look to go over any closing punctuation. This is because in dominant // Here we look to go over any closing punctuation. This is because in dominant
// variants of English, the final period is placed within double quotes and maybe // variants of English, the final period is placed within double quotes and maybe
@ -195,7 +191,7 @@ public final class CapsModeUtils {
if (c == Constants.CODE_QUESTION_MARK || c == Constants.CODE_EXCLAMATION_MARK) { if (c == Constants.CODE_QUESTION_MARK || c == Constants.CODE_EXCLAMATION_MARK) {
return (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_SENTENCES) & reqModes; return (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_SENTENCES) & reqModes;
} }
if (!isPeriod(c) || j <= 0) { if (settingsValues.mSentenceSeparator != c || j <= 0) {
return (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS) & reqModes; return (TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS) & reqModes;
} }
@ -245,7 +241,7 @@ public final class CapsModeUtils {
case WORD: case WORD:
if (Character.isLetter(c)) { if (Character.isLetter(c)) {
state = WORD; state = WORD;
} else if (isPeriod(c)) { } else if (settingsValues.mSentenceSeparator == c) {
state = PERIOD; state = PERIOD;
} else { } else {
return caps; return caps;
@ -261,7 +257,7 @@ public final class CapsModeUtils {
case LETTER: case LETTER:
if (Character.isLetter(c)) { if (Character.isLetter(c)) {
state = LETTER; state = LETTER;
} else if (isPeriod(c)) { } else if (settingsValues.mSentenceSeparator == c) {
state = PERIOD; state = PERIOD;
} else { } else {
return noCaps; return noCaps;

View File

@ -16,6 +16,8 @@
package com.android.inputmethod.latin.utils; package com.android.inputmethod.latin.utils;
import com.android.inputmethod.latin.settings.SettingsValues;
import android.test.AndroidTestCase; import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest; import android.test.suitebuilder.annotation.SmallTest;
import android.text.TextUtils; import android.text.TextUtils;
@ -25,64 +27,64 @@ import java.util.Locale;
@SmallTest @SmallTest
public class CapsModeUtilsTests extends AndroidTestCase { public class CapsModeUtilsTests extends AndroidTestCase {
private static void onePathForCaps(final CharSequence cs, final int expectedResult, private static void onePathForCaps(final CharSequence cs, final int expectedResult,
final int mask, final Locale l, final boolean hasSpaceBefore) { final int mask, final SettingsValues sv, final boolean hasSpaceBefore) {
int oneTimeResult = expectedResult & mask; int oneTimeResult = expectedResult & mask;
assertEquals("After >" + cs + "<", oneTimeResult, assertEquals("After >" + cs + "<", oneTimeResult,
CapsModeUtils.getCapsMode(cs, mask, l, hasSpaceBefore)); CapsModeUtils.getCapsMode(cs, mask, sv, hasSpaceBefore));
} }
private static void allPathsForCaps(final CharSequence cs, final int expectedResult, private static void allPathsForCaps(final CharSequence cs, final int expectedResult,
final Locale l, final boolean hasSpaceBefore) { final SettingsValues sv, final boolean hasSpaceBefore) {
final int c = TextUtils.CAP_MODE_CHARACTERS; final int c = TextUtils.CAP_MODE_CHARACTERS;
final int w = TextUtils.CAP_MODE_WORDS; final int w = TextUtils.CAP_MODE_WORDS;
final int s = TextUtils.CAP_MODE_SENTENCES; final int s = TextUtils.CAP_MODE_SENTENCES;
onePathForCaps(cs, expectedResult, c | w | s, l, hasSpaceBefore); onePathForCaps(cs, expectedResult, c | w | s, sv, hasSpaceBefore);
onePathForCaps(cs, expectedResult, w | s, l, hasSpaceBefore); onePathForCaps(cs, expectedResult, w | s, sv, hasSpaceBefore);
onePathForCaps(cs, expectedResult, c | s, l, hasSpaceBefore); onePathForCaps(cs, expectedResult, c | s, sv, hasSpaceBefore);
onePathForCaps(cs, expectedResult, c | w, l, hasSpaceBefore); onePathForCaps(cs, expectedResult, c | w, sv, hasSpaceBefore);
onePathForCaps(cs, expectedResult, c, l, hasSpaceBefore); onePathForCaps(cs, expectedResult, c, sv, hasSpaceBefore);
onePathForCaps(cs, expectedResult, w, l, hasSpaceBefore); onePathForCaps(cs, expectedResult, w, sv, hasSpaceBefore);
onePathForCaps(cs, expectedResult, s, l, hasSpaceBefore); onePathForCaps(cs, expectedResult, s, sv, hasSpaceBefore);
} }
public void testGetCapsMode() { public void testGetCapsMode() {
final int c = TextUtils.CAP_MODE_CHARACTERS; final int c = TextUtils.CAP_MODE_CHARACTERS;
final int w = TextUtils.CAP_MODE_WORDS; final int w = TextUtils.CAP_MODE_WORDS;
final int s = TextUtils.CAP_MODE_SENTENCES; final int s = TextUtils.CAP_MODE_SENTENCES;
Locale l = Locale.ENGLISH; SettingsValues sv = SettingsValues.makeDummySettingsValuesForTest(Locale.ENGLISH);
allPathsForCaps("", c | w | s, l, false); allPathsForCaps("", c | w | s, sv, false);
allPathsForCaps("Word", c, l, false); allPathsForCaps("Word", c, sv, false);
allPathsForCaps("Word.", c, l, false); allPathsForCaps("Word.", c, sv, false);
allPathsForCaps("Word ", c | w, l, false); allPathsForCaps("Word ", c | w, sv, false);
allPathsForCaps("Word. ", c | w | s, l, false); allPathsForCaps("Word. ", c | w | s, sv, false);
allPathsForCaps("Word..", c, l, false); allPathsForCaps("Word..", c, sv, false);
allPathsForCaps("Word.. ", c | w | s, l, false); allPathsForCaps("Word.. ", c | w | s, sv, false);
allPathsForCaps("Word... ", c | w | s, l, false); allPathsForCaps("Word... ", c | w | s, sv, false);
allPathsForCaps("Word ... ", c | w | s, l, false); allPathsForCaps("Word ... ", c | w | s, sv, false);
allPathsForCaps("Word . ", c | w, l, false); allPathsForCaps("Word . ", c | w, sv, false);
allPathsForCaps("In the U.S ", c | w, l, false); allPathsForCaps("In the U.S ", c | w, sv, false);
allPathsForCaps("In the U.S. ", c | w, l, false); allPathsForCaps("In the U.S. ", c | w, sv, false);
allPathsForCaps("Some stuff (e.g. ", c | w, l, false); allPathsForCaps("Some stuff (e.g. ", c | w, sv, false);
allPathsForCaps("In the U.S.. ", c | w | s, l, false); allPathsForCaps("In the U.S.. ", c | w | s, sv, false);
allPathsForCaps("\"Word.\" ", c | w | s, l, false); allPathsForCaps("\"Word.\" ", c | w | s, sv, false);
allPathsForCaps("\"Word\". ", c | w | s, l, false); allPathsForCaps("\"Word\". ", c | w | s, sv, false);
allPathsForCaps("\"Word\" ", c | w, l, false); allPathsForCaps("\"Word\" ", c | w, sv, false);
// Test for phantom space // Test for phantom space
allPathsForCaps("Word", c | w, l, true); allPathsForCaps("Word", c | w, sv, true);
allPathsForCaps("Word.", c | w | s, l, true); allPathsForCaps("Word.", c | w | s, sv, true);
// Tests after some whitespace // Tests after some whitespace
allPathsForCaps("Word\n", c | w | s, l, false); allPathsForCaps("Word\n", c | w | s, sv, false);
allPathsForCaps("Word\n", c | w | s, l, true); allPathsForCaps("Word\n", c | w | s, sv, true);
allPathsForCaps("Word\n ", c | w | s, l, true); allPathsForCaps("Word\n ", c | w | s, sv, true);
allPathsForCaps("Word.\n", c | w | s, l, false); allPathsForCaps("Word.\n", c | w | s, sv, false);
allPathsForCaps("Word.\n", c | w | s, l, true); allPathsForCaps("Word.\n", c | w | s, sv, true);
allPathsForCaps("Word.\n ", c | w | s, l, true); allPathsForCaps("Word.\n ", c | w | s, sv, true);
l = Locale.FRENCH; sv = SettingsValues.makeDummySettingsValuesForTest(Locale.FRENCH);
allPathsForCaps("\"Word.\" ", c | w, l, false); allPathsForCaps("\"Word.\" ", c | w, sv, false);
allPathsForCaps("\"Word\". ", c | w | s, l, false); allPathsForCaps("\"Word\". ", c | w | s, sv, false);
allPathsForCaps("\"Word\" ", c | w, l, false); allPathsForCaps("\"Word\" ", c | w, sv, false);
} }
} }