Merge "Use memmove for all place src and dest can be same."
diff --git a/java/res/values-fr-rCA/config-spacing-and-punctuations.xml b/java/res/values-fr-rCA/config-spacing-and-punctuations.xml
index 0625480..c3a1a0a 100644
--- a/java/res/values-fr-rCA/config-spacing-and-punctuations.xml
+++ b/java/res/values-fr-rCA/config-spacing-and-punctuations.xml
@@ -25,7 +25,7 @@
     <string name="symbols_followed_by_space" translatable="false">.,;:!?)]}&amp;</string>
     <!-- Symbols that separate words -->
     <!-- Don't remove the enclosing double quotes, they protect whitespace (not just U+0020) -->
-    <string name="symbols_word_separators" translatable="false">"&#x0009;&#x0020;\n"()[]{}*&amp;&lt;&gt;+=|.,;:!?/_\"</string>
+    <string name="symbols_word_separators" translatable="false">"&#x0009;&#x0020;&#x000A;"()[]{}*&amp;&lt;&gt;+=|.,;:!?/_\"</string>
     <!-- Word connectors -->
     <string name="symbols_word_connectors" translatable="false">\'-</string>
 </resources>
diff --git a/java/res/values-fr/config-spacing-and-punctuations.xml b/java/res/values-fr/config-spacing-and-punctuations.xml
index 33e0236..8b53fb3 100644
--- a/java/res/values-fr/config-spacing-and-punctuations.xml
+++ b/java/res/values-fr/config-spacing-and-punctuations.xml
@@ -24,7 +24,7 @@
     <string name="symbols_followed_by_space" translatable="false">.,;:!?)]}&amp;</string>
     <!-- Symbols that separate words -->
     <!-- Don't remove the enclosing double quotes, they protect whitespace (not just U+0020) -->
-    <string name="symbols_word_separators" translatable="false">"&#x0009;&#x0020;\n"()[]{}*&amp;&lt;&gt;+=|.,;:!?/_\"</string>
+    <string name="symbols_word_separators" translatable="false">"&#x0009;&#x0020;&#x000A;"()[]{}*&amp;&lt;&gt;+=|.,;:!?/_\"</string>
     <!-- Word connectors -->
     <string name="symbols_word_connectors" translatable="false">\'-</string>
 </resources>
diff --git a/java/res/values-hy-rAM/config-spacing-and-punctuations.xml b/java/res/values-hy-rAM/config-spacing-and-punctuations.xml
index f26a30d..8bc1b85 100644
--- a/java/res/values-hy-rAM/config-spacing-and-punctuations.xml
+++ b/java/res/values-hy-rAM/config-spacing-and-punctuations.xml
@@ -25,7 +25,7 @@
     <string name="symbols_followed_by_space" translatable="false">.,;:!?)]}&amp;&#x0589;&#x055D;</string>
     <!-- Symbols that separate words. Adding armenian period and comma. -->
     <!-- Don't remove the enclosing double quotes, they protect whitespace (not just U+0020) -->
-    <string name="symbols_word_separators" translatable="false">"&#x0009;&#x0020;\n"()[]{}*&amp;&lt;&gt;+=|.,;:!?/_\"&#x0589;&#x055D;</string>
+    <string name="symbols_word_separators" translatable="false">"&#x0009;&#x0020;&#x000A;"()[]{}*&amp;&lt;&gt;+=|.,;:!?/_\"&#x0589;&#x055D;</string>
     <!-- The sentence separator code point, for capitalization -->
     <!-- U+0589: "։" ARMENIAN FULL STOP   ; 589h = 1417d -->
     <integer name="sentence_separator" translatable="false">1417</integer>
diff --git a/java/res/values/config-spacing-and-punctuations.xml b/java/res/values/config-spacing-and-punctuations.xml
index f10f810..2f52edd 100644
--- a/java/res/values/config-spacing-and-punctuations.xml
+++ b/java/res/values/config-spacing-and-punctuations.xml
@@ -28,7 +28,7 @@
     <string name="symbols_followed_by_space" translatable="false">.,;:!?)]}&amp;</string>
     <!-- Symbols that separate words -->
     <!-- Don't remove the enclosing double quotes, they protect whitespace (not just U+0020) -->
-    <string name="symbols_word_separators" translatable="false">"&#x0009;&#x0020;\n"()[]{}*&amp;&lt;&gt;+=|.,;:!?/_\"</string>
+    <string name="symbols_word_separators" translatable="false">"&#x0009;&#x0020;&#x000A;"()[]{}*&amp;&lt;&gt;+=|.,;:!?/_\"</string>
     <!-- Word connectors -->
     <string name="symbols_word_connectors" translatable="false">\'-</string>
     <!-- The sentence separator code point, for capitalization -->
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 3fca4fd..d3e6a1b 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -1407,7 +1407,7 @@
 
     // TODO[IL]: Move this to InputLogic
     public SuggestedWords maybeRetrieveOlderSuggestions(final String typedWord,
-            final SuggestedWords suggestedWords) {
+            final SuggestedWords suggestedWords, final SuggestedWords previousSuggestedWords) {
         // TODO: consolidate this into getSuggestedWords
         // We update the suggestion strip only when we have some suggestions to show, i.e. when
         // the suggestion count is > 1; else, we leave the old suggestions, with the typed word
@@ -1420,30 +1420,24 @@
                 || mSuggestionStripView.isShowingAddToDictionaryHint()) {
             return suggestedWords;
         } else {
-            return getOlderSuggestions(typedWord);
+            final SuggestedWords punctuationList =
+                    mSettings.getCurrent().mSpacingAndPunctuations.mSuggestPuncList;
+            final SuggestedWords oldSuggestedWords = previousSuggestedWords == punctuationList
+                            ? SuggestedWords.EMPTY : previousSuggestedWords;
+            if (TextUtils.isEmpty(typedWord)) {
+                return oldSuggestedWords;
+            }
+            final ArrayList<SuggestedWords.SuggestedWordInfo> typedWordAndPreviousSuggestions =
+                    SuggestedWords.getTypedWordAndPreviousSuggestions(typedWord, oldSuggestedWords);
+            return new SuggestedWords(typedWordAndPreviousSuggestions,
+                    false /* typedWordValid */,
+                    false /* hasAutoCorrectionCandidate */,
+                    false /* isPunctuationSuggestions */,
+                    true /* isObsoleteSuggestions */,
+                    false /* isPrediction */);
         }
     }
 
-    private SuggestedWords getOlderSuggestions(final String typedWord) {
-        SuggestedWords previousSuggestedWords = mInputLogic.mSuggestedWords;
-        if (previousSuggestedWords
-                == mSettings.getCurrent().mSpacingAndPunctuations.mSuggestPuncList) {
-            previousSuggestedWords = SuggestedWords.EMPTY;
-        }
-        if (typedWord == null) {
-            return previousSuggestedWords;
-        }
-        final ArrayList<SuggestedWords.SuggestedWordInfo> typedWordAndPreviousSuggestions =
-                SuggestedWords.getTypedWordAndPreviousSuggestions(typedWord,
-                        previousSuggestedWords);
-        return new SuggestedWords(typedWordAndPreviousSuggestions,
-                false /* typedWordValid */,
-                false /* hasAutoCorrectionCandidate */,
-                false /* isPunctuationSuggestions */,
-                true /* isObsoleteSuggestions */,
-                false /* isPrediction */);
-    }
-
     private void showSuggestionStripWithTypedWord(final SuggestedWords suggestedWords,
             final String typedWord) {
       if (suggestedWords.isEmpty()) {
diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java
index a5b147a..325a0d9 100644
--- a/java/src/com/android/inputmethod/latin/RichInputConnection.java
+++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java
@@ -35,6 +35,7 @@
 import com.android.inputmethod.latin.utils.TextRange;
 import com.android.inputmethod.research.ResearchLogger;
 
+import java.util.Arrays;
 import java.util.regex.Pattern;
 
 /**
@@ -557,8 +558,8 @@
         return getNthPreviousWord(prev, spacingAndPunctuations, n);
     }
 
-    private static boolean isSeparator(int code, String sep) {
-        return sep.indexOf(code) != -1;
+    private static boolean isSeparator(final int code, final int[] sortedSeparators) {
+        return Arrays.binarySearch(sortedSeparators, code) >= 0;
     }
 
     // Get the nth word before cursor. n = 1 retrieves the word immediately before the cursor,
@@ -597,29 +598,29 @@
     }
 
     /**
-     * @param separators characters which may separate words
+     * @param sortedSeparators a sorted array of code points which may separate words
      * @return the word that surrounds the cursor, including up to one trailing
      *   separator. For example, if the field contains "he|llo world", where |
      *   represents the cursor, then "hello " will be returned.
      */
-    public CharSequence getWordAtCursor(String separators) {
+    public CharSequence getWordAtCursor(final int[] sortedSeparators) {
         // getWordRangeAtCursor returns null if the connection is null
-        TextRange r = getWordRangeAtCursor(separators, 0);
+        final TextRange r = getWordRangeAtCursor(sortedSeparators, 0);
         return (r == null) ? null : r.mWord;
     }
 
     /**
      * Returns the text surrounding the cursor.
      *
-     * @param sep a string of characters that split words.
+     * @param sortedSeparators a sorted array of code points that split words.
      * @param additionalPrecedingWordsCount the number of words before the current word that should
      *   be included in the returned range
      * @return a range containing the text surrounding the cursor
      */
-    public TextRange getWordRangeAtCursor(final String sep,
+    public TextRange getWordRangeAtCursor(final int[] sortedSeparators,
             final int additionalPrecedingWordsCount) {
         mIC = mParent.getCurrentInputConnection();
-        if (mIC == null || sep == null) {
+        if (mIC == null) {
             return null;
         }
         final CharSequence before = mIC.getTextBeforeCursor(Constants.EDITOR_CONTENTS_CACHE_SIZE,
@@ -638,7 +639,7 @@
         while (true) { // see comments below for why this is guaranteed to halt
             while (startIndexInBefore > 0) {
                 final int codePoint = Character.codePointBefore(before, startIndexInBefore);
-                if (isStoppingAtWhitespace == isSeparator(codePoint, sep)) {
+                if (isStoppingAtWhitespace == isSeparator(codePoint, sortedSeparators)) {
                     break;  // inner loop
                 }
                 --startIndexInBefore;
@@ -659,7 +660,7 @@
         int endIndexInAfter = -1;
         while (++endIndexInAfter < after.length()) {
             final int codePoint = Character.codePointAt(after, endIndexInAfter);
-            if (isSeparator(codePoint, sep)) {
+            if (isSeparator(codePoint, sortedSeparators)) {
                 break;
             }
             if (Character.isSupplementaryCodePoint(codePoint)) {
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index 3ff2079..375a42e 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -970,7 +970,8 @@
             if (TextUtils.isEmpty(selectedText)) return; // Race condition with the input connection
             mRecapitalizeStatus.initialize(mConnection.getExpectedSelectionStart(),
                     mConnection.getExpectedSelectionEnd(), selectedText.toString(),
-                    settingsValues.mLocale, settingsValues.mSpacingAndPunctuations.mWordSeparators);
+                    settingsValues.mLocale,
+                    settingsValues.mSpacingAndPunctuations.mSortedWordSeparators);
             // We trim leading and trailing whitespace.
             mRecapitalizeStatus.trim();
         }
@@ -1031,7 +1032,8 @@
                     public void onGetSuggestedWords(final SuggestedWords suggestedWords) {
                         final SuggestedWords suggestedWordsWithMaybeOlderSuggestions =
                                 mLatinIME.maybeRetrieveOlderSuggestions(
-                                        mWordComposer.getTypedWord(), suggestedWords);
+                                        mWordComposer.getTypedWord(), suggestedWords,
+                                        mSuggestedWords);
                         holder.set(suggestedWordsWithMaybeOlderSuggestions);
                     }
                 }
@@ -1072,7 +1074,7 @@
         final int expectedCursorPosition = mConnection.getExpectedSelectionStart();
         if (!mConnection.isCursorTouchingWord(settingsValues.mSpacingAndPunctuations)) return;
         final TextRange range = mConnection.getWordRangeAtCursor(
-                settingsValues.mSpacingAndPunctuations.mWordSeparators,
+                settingsValues.mSpacingAndPunctuations.mSortedWordSeparators,
                 0 /* additionalPrecedingWordsCount */);
         if (null == range) return; // Happens if we don't have an input connection at all
         if (range.length() <= 0) return; // Race condition. No text to resume on, so bail out.
diff --git a/java/src/com/android/inputmethod/latin/makedict/Ver2DictEncoder.java b/java/src/com/android/inputmethod/latin/makedict/Ver2DictEncoder.java
index e543042..a3a6c2c 100644
--- a/java/src/com/android/inputmethod/latin/makedict/Ver2DictEncoder.java
+++ b/java/src/com/android/inputmethod/latin/makedict/Ver2DictEncoder.java
@@ -16,6 +16,7 @@
 
 package com.android.inputmethod.latin.makedict;
 
+import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.latin.makedict.BinaryDictDecoderUtils.CharEncoding;
 import com.android.inputmethod.latin.makedict.FormatSpec.FormatOptions;
 import com.android.inputmethod.latin.makedict.FusionDictionary.PtNode;
@@ -33,6 +34,7 @@
 /**
  * An implementation of DictEncoder for version 2 binary dictionary.
  */
+@UsedForTesting
 public class Ver2DictEncoder implements DictEncoder {
 
     private final File mDictFile;
@@ -40,6 +42,7 @@
     private byte[] mBuffer;
     private int mPosition;
 
+    @UsedForTesting
     public Ver2DictEncoder(final File dictFile) {
         mDictFile = dictFile;
         mOutStream = null;
@@ -49,6 +52,7 @@
     // This constructor is used only by BinaryDictOffdeviceUtilsTests.
     // If you want to use this in the production code, you should consider keeping consistency of
     // the interface of Ver3DictDecoder by using factory.
+    @UsedForTesting
     public Ver2DictEncoder(final OutputStream outStream) {
         mDictFile = null;
         mOutStream = outStream;
diff --git a/java/src/com/android/inputmethod/latin/settings/Settings.java b/java/src/com/android/inputmethod/latin/settings/Settings.java
index 7db1071..9bf269b 100644
--- a/java/src/com/android/inputmethod/latin/settings/Settings.java
+++ b/java/src/com/android/inputmethod/latin/settings/Settings.java
@@ -181,10 +181,6 @@
         return mSettingsValues.mIsInternal;
     }
 
-    public String getWordSeparators() {
-        return mSettingsValues.mSpacingAndPunctuations.mWordSeparators;
-    }
-
     public boolean isWordSeparator(final int code) {
         return mSettingsValues.isWordSeparator(code);
     }
diff --git a/java/src/com/android/inputmethod/latin/settings/SpacingAndPunctuations.java b/java/src/com/android/inputmethod/latin/settings/SpacingAndPunctuations.java
index 29bd3e7..8ba32ff 100644
--- a/java/src/com/android/inputmethod/latin/settings/SpacingAndPunctuations.java
+++ b/java/src/com/android/inputmethod/latin/settings/SpacingAndPunctuations.java
@@ -32,11 +32,11 @@
 import java.util.Locale;
 
 public final class SpacingAndPunctuations {
-    private final int[] mSymbolsPrecededBySpace;
-    private final int[] mSymbolsFollowedBySpace;
-    private final int[] mWordConnectors;
+    private final int[] mSortedSymbolsPrecededBySpace;
+    private final int[] mSortedSymbolsFollowedBySpace;
+    private final int[] mSortedWordConnectors;
+    public final int[] mSortedWordSeparators;
     public final SuggestedWords mSuggestPuncList;
-    public final String mWordSeparators;
     private final int mSentenceSeparator;
     public final String mSentenceSeparatorAndSpace;
     public final boolean mCurrentLanguageHasSpaces;
@@ -44,19 +44,20 @@
     public final boolean mUsesGermanRules;
 
     public SpacingAndPunctuations(final Resources res) {
-        mSymbolsPrecededBySpace =
-                StringUtils.toCodePointArray(res.getString(R.string.symbols_preceded_by_space));
-        Arrays.sort(mSymbolsPrecededBySpace);
-        mSymbolsFollowedBySpace =
-                StringUtils.toCodePointArray(res.getString(R.string.symbols_followed_by_space));
-        Arrays.sort(mSymbolsFollowedBySpace);
-        mWordConnectors =
-                StringUtils.toCodePointArray(res.getString(R.string.symbols_word_connectors));
-        Arrays.sort(mWordConnectors);
+        // To be able to binary search the code point. See {@link #isUsuallyPrecededBySpace(int)}.
+        mSortedSymbolsPrecededBySpace = StringUtils.toSortedCodePointArray(
+                res.getString(R.string.symbols_preceded_by_space));
+        // To be able to binary search the code point. See {@link #isUsuallyFollowedBySpace(int)}.
+        mSortedSymbolsFollowedBySpace = StringUtils.toSortedCodePointArray(
+                res.getString(R.string.symbols_followed_by_space));
+        // To be able to binary search the code point. See {@link #isWordConnector(int)}.
+        mSortedWordConnectors = StringUtils.toSortedCodePointArray(
+                res.getString(R.string.symbols_word_connectors));
+        mSortedWordSeparators = StringUtils.toSortedCodePointArray(
+                res.getString(R.string.symbols_word_separators));
         final String[] suggestPuncsSpec = KeySpecParser.splitKeySpecs(res.getString(
                 R.string.suggested_punctuations));
         mSuggestPuncList = createSuggestPuncList(suggestPuncsSpec);
-        mWordSeparators = res.getString(R.string.symbols_word_separators);
         mSentenceSeparator = res.getInteger(R.integer.sentence_separator);
         mSentenceSeparatorAndSpace = new String(new int[] {
                 mSentenceSeparator, Constants.CODE_SPACE }, 0, 2);
@@ -74,6 +75,7 @@
         if (puncs != null) {
             for (final String puncSpec : puncs) {
                 // TODO: Stop using KeySpceParser.getLabel().
+                // TODO: Punctuation suggestions should honor RTL languages.
                 puncList.add(new SuggestedWordInfo(KeySpecParser.getLabel(puncSpec),
                         SuggestedWordInfo.MAX_SCORE, SuggestedWordInfo.KIND_HARDCODED,
                         Dictionary.DICTIONARY_HARDCODED,
@@ -90,11 +92,11 @@
     }
 
     public boolean isWordSeparator(final int code) {
-        return mWordSeparators.contains(String.valueOf((char)code));
+        return Arrays.binarySearch(mSortedWordSeparators, code) >= 0;
     }
 
     public boolean isWordConnector(final int code) {
-        return Arrays.binarySearch(mWordConnectors, code) >= 0;
+        return Arrays.binarySearch(mSortedWordConnectors, code) >= 0;
     }
 
     public boolean isWordCodePoint(final int code) {
@@ -102,11 +104,11 @@
     }
 
     public boolean isUsuallyPrecededBySpace(final int code) {
-        return Arrays.binarySearch(mSymbolsPrecededBySpace, code) >= 0;
+        return Arrays.binarySearch(mSortedSymbolsPrecededBySpace, code) >= 0;
     }
 
     public boolean isUsuallyFollowedBySpace(final int code) {
-        return Arrays.binarySearch(mSymbolsFollowedBySpace, code) >= 0;
+        return Arrays.binarySearch(mSortedSymbolsFollowedBySpace, code) >= 0;
     }
 
     public boolean isSentenceSeparator(final int code) {
diff --git a/java/src/com/android/inputmethod/latin/utils/RecapitalizeStatus.java b/java/src/com/android/inputmethod/latin/utils/RecapitalizeStatus.java
index 0f5cd80..4521ec5 100644
--- a/java/src/com/android/inputmethod/latin/utils/RecapitalizeStatus.java
+++ b/java/src/com/android/inputmethod/latin/utils/RecapitalizeStatus.java
@@ -37,12 +37,12 @@
         CAPS_MODE_ALL_UPPER
     };
 
-    private static final int getStringMode(final String string, final String separators) {
+    private static final int getStringMode(final String string, final int[] sortedSeparators) {
         if (StringUtils.isIdenticalAfterUpcase(string)) {
             return CAPS_MODE_ALL_UPPER;
         } else if (StringUtils.isIdenticalAfterDowncase(string)) {
             return CAPS_MODE_ALL_LOWER;
-        } else if (StringUtils.isIdenticalAfterCapitalizeEachWord(string, separators)) {
+        } else if (StringUtils.isIdenticalAfterCapitalizeEachWord(string, sortedSeparators)) {
             return CAPS_MODE_FIRST_WORD_UPPER;
         } else {
             return CAPS_MODE_ORIGINAL_MIXED_CASE;
@@ -60,26 +60,28 @@
     private int mRotationStyleCurrentIndex;
     private boolean mSkipOriginalMixedCaseMode;
     private Locale mLocale;
-    private String mSeparators;
+    private int[] mSortedSeparators;
     private String mStringAfter;
     private boolean mIsActive;
 
+    private static final int[] EMPTY_STORTED_SEPARATORS = {};
+
     public RecapitalizeStatus() {
         // By default, initialize with dummy values that won't match any real recapitalize.
-        initialize(-1, -1, "", Locale.getDefault(), "");
+        initialize(-1, -1, "", Locale.getDefault(), EMPTY_STORTED_SEPARATORS);
         deactivate();
     }
 
     public void initialize(final int cursorStart, final int cursorEnd, final String string,
-            final Locale locale, final String separators) {
+            final Locale locale, final int[] sortedSeparators) {
         mCursorStartBefore = cursorStart;
         mStringBefore = string;
         mCursorStartAfter = cursorStart;
         mCursorEndAfter = cursorEnd;
         mStringAfter = string;
-        final int initialMode = getStringMode(mStringBefore, separators);
+        final int initialMode = getStringMode(mStringBefore, sortedSeparators);
         mLocale = locale;
-        mSeparators = separators;
+        mSortedSeparators = sortedSeparators;
         if (CAPS_MODE_ORIGINAL_MIXED_CASE == initialMode) {
             mRotationStyleCurrentIndex = 0;
             mSkipOriginalMixedCaseMode = false;
@@ -131,7 +133,7 @@
                 mStringAfter = mStringBefore.toLowerCase(mLocale);
                 break;
             case CAPS_MODE_FIRST_WORD_UPPER:
-                mStringAfter = StringUtils.capitalizeEachWord(mStringBefore, mSeparators,
+                mStringAfter = StringUtils.capitalizeEachWord(mStringBefore, mSortedSeparators,
                         mLocale);
                 break;
             case CAPS_MODE_ALL_UPPER:
diff --git a/java/src/com/android/inputmethod/latin/utils/StringUtils.java b/java/src/com/android/inputmethod/latin/utils/StringUtils.java
index c5ed393..5920c68 100644
--- a/java/src/com/android/inputmethod/latin/utils/StringUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/StringUtils.java
@@ -22,6 +22,7 @@
 import com.android.inputmethod.latin.Constants;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Locale;
 
 public final class StringUtils {
@@ -183,6 +184,12 @@
         return codePoints;
     }
 
+    public static int[] toSortedCodePointArray(final String string) {
+        final int[] codePoints = toCodePointArray(string);
+        Arrays.sort(codePoints);
+        return codePoints;
+    }
+
     // This method assumes the text is not null. For the empty string, it returns CAPITALIZE_NONE.
     public static int getCapitalizationType(final String text) {
         // If the first char is not uppercase, then the word is either all lower case or
@@ -265,39 +272,39 @@
     }
 
     public static boolean isIdenticalAfterCapitalizeEachWord(final String text,
-            final String separators) {
-        boolean needCapsNext = true;
+            final int[] sortedSeparators) {
+        boolean needsCapsNext = true;
         final int len = text.length();
         for (int i = 0; i < len; i = text.offsetByCodePoints(i, 1)) {
             final int codePoint = text.codePointAt(i);
             if (Character.isLetter(codePoint)) {
-                if ((needCapsNext && !Character.isUpperCase(codePoint))
-                        || (!needCapsNext && !Character.isLowerCase(codePoint))) {
+                if ((needsCapsNext && !Character.isUpperCase(codePoint))
+                        || (!needsCapsNext && !Character.isLowerCase(codePoint))) {
                     return false;
                 }
             }
             // We need a capital letter next if this is a separator.
-            needCapsNext = (-1 != separators.indexOf(codePoint));
+            needsCapsNext = (Arrays.binarySearch(sortedSeparators, codePoint) >= 0);
         }
         return true;
     }
 
     // TODO: like capitalizeFirst*, this does not work perfectly for Dutch because of the IJ digraph
     // which should be capitalized together in *some* cases.
-    public static String capitalizeEachWord(final String text, final String separators,
+    public static String capitalizeEachWord(final String text, final int[] sortedSeparators,
             final Locale locale) {
         final StringBuilder builder = new StringBuilder();
-        boolean needCapsNext = true;
+        boolean needsCapsNext = true;
         final int len = text.length();
         for (int i = 0; i < len; i = text.offsetByCodePoints(i, 1)) {
             final String nextChar = text.substring(i, text.offsetByCodePoints(i, 1));
-            if (needCapsNext) {
+            if (needsCapsNext) {
                 builder.append(nextChar.toUpperCase(locale));
             } else {
                 builder.append(nextChar.toLowerCase(locale));
             }
             // We need a capital letter next if this is a separator.
-            needCapsNext = (-1 != separators.indexOf(nextChar.codePointAt(0)));
+            needsCapsNext = (Arrays.binarySearch(sortedSeparators, nextChar.codePointAt(0)) >= 0);
         }
         return builder.toString();
     }
diff --git a/java/src/com/android/inputmethod/research/ResearchLogger.java b/java/src/com/android/inputmethod/research/ResearchLogger.java
index e7f49a6..11fb3a1 100644
--- a/java/src/com/android/inputmethod/research/ResearchLogger.java
+++ b/java/src/com/android/inputmethod/research/ResearchLogger.java
@@ -59,6 +59,7 @@
 import com.android.inputmethod.latin.SuggestedWords;
 import com.android.inputmethod.latin.define.ProductionFlag;
 import com.android.inputmethod.latin.utils.InputTypeUtils;
+import com.android.inputmethod.latin.utils.StringUtils;
 import com.android.inputmethod.latin.utils.TextRange;
 import com.android.inputmethod.research.MotionEventReader.ReplayData;
 import com.android.inputmethod.research.ui.SplashScreen;
@@ -131,7 +132,8 @@
     public static final String RESEARCH_KEY_OUTPUT_TEXT = ".research.";
 
     // constants related to specific log points
-    private static final String WHITESPACE_SEPARATORS = " \t\n\r";
+    private static final int[] WHITESPACE_SEPARATORS =
+            StringUtils.toSortedCodePointArray(" \t\n\r");
     private static final int MAX_INPUTVIEW_LENGTH_TO_CAPTURE = 8192; // must be >=1
     private static final String PREF_RESEARCH_SAVED_CHANNEL = "pref_research_saved_channel";
 
diff --git a/tests/src/com/android/inputmethod/latin/RichInputConnectionAndTextRangeTests.java b/tests/src/com/android/inputmethod/latin/RichInputConnectionAndTextRangeTests.java
index f19d185..7f07435 100644
--- a/tests/src/com/android/inputmethod/latin/RichInputConnectionAndTextRangeTests.java
+++ b/tests/src/com/android/inputmethod/latin/RichInputConnectionAndTextRangeTests.java
@@ -32,6 +32,7 @@
 
 import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
 import com.android.inputmethod.latin.utils.RunInLocale;
+import com.android.inputmethod.latin.utils.StringUtils;
 import com.android.inputmethod.latin.utils.TextRange;
 
 import java.util.Locale;
@@ -183,6 +184,12 @@
     /**
      * Test logic in getting the word range at the cursor.
      */
+    private static final int[] SPACE = { Constants.CODE_SPACE };
+    static final int[] TAB = { Constants.CODE_TAB };
+    private static final int[] SPACE_TAB = StringUtils.toSortedCodePointArray(" \t");
+    // A character that needs surrogate pair to represent its code point (U+2008A).
+    private static final String SUPPLEMENTARY_CHAR = "\uD840\uDC8A";
+
     public void testGetWordRangeAtCursor() {
         ExtractedText et = new ExtractedText();
         final MockInputMethodService mockInputMethodService = new MockInputMethodService();
@@ -194,48 +201,47 @@
 
         ic.beginBatchEdit();
         // basic case
-        r = ic.getWordRangeAtCursor(" ", 0);
+        r = ic.getWordRangeAtCursor(SPACE, 0);
         assertTrue(TextUtils.equals("word", r.mWord));
 
         // more than one word
-        r = ic.getWordRangeAtCursor(" ", 1);
+        r = ic.getWordRangeAtCursor(SPACE, 1);
         assertTrue(TextUtils.equals("word word", r.mWord));
         ic.endBatchEdit();
 
         // tab character instead of space
         mockInputMethodService.setInputConnection(new MockConnection("one\tword\two", "rd", et));
         ic.beginBatchEdit();
-        r = ic.getWordRangeAtCursor("\t", 1);
+        r = ic.getWordRangeAtCursor(TAB, 1);
         ic.endBatchEdit();
         assertTrue(TextUtils.equals("word\tword", r.mWord));
 
         // only one word doesn't go too far
         mockInputMethodService.setInputConnection(new MockConnection("one\tword\two", "rd", et));
         ic.beginBatchEdit();
-        r = ic.getWordRangeAtCursor("\t", 1);
+        r = ic.getWordRangeAtCursor(TAB, 1);
         ic.endBatchEdit();
         assertTrue(TextUtils.equals("word\tword", r.mWord));
 
         // tab or space
         mockInputMethodService.setInputConnection(new MockConnection("one word\two", "rd", et));
         ic.beginBatchEdit();
-        r = ic.getWordRangeAtCursor(" \t", 1);
+        r = ic.getWordRangeAtCursor(SPACE_TAB, 1);
         ic.endBatchEdit();
         assertTrue(TextUtils.equals("word\tword", r.mWord));
 
         // tab or space multiword
         mockInputMethodService.setInputConnection(new MockConnection("one word\two", "rd", et));
         ic.beginBatchEdit();
-        r = ic.getWordRangeAtCursor(" \t", 2);
+        r = ic.getWordRangeAtCursor(SPACE_TAB, 2);
         ic.endBatchEdit();
         assertTrue(TextUtils.equals("one word\tword", r.mWord));
 
         // splitting on supplementary character
-        final String supplementaryChar = "\uD840\uDC8A";
         mockInputMethodService.setInputConnection(
-                new MockConnection("one word" + supplementaryChar + "wo", "rd", et));
+                new MockConnection("one word" + SUPPLEMENTARY_CHAR + "wo", "rd", et));
         ic.beginBatchEdit();
-        r = ic.getWordRangeAtCursor(supplementaryChar, 0);
+        r = ic.getWordRangeAtCursor(StringUtils.toSortedCodePointArray(SUPPLEMENTARY_CHAR), 0);
         ic.endBatchEdit();
         assertTrue(TextUtils.equals("word", r.mWord));
     }
@@ -265,7 +271,7 @@
         TextRange r;
         SuggestionSpan[] suggestions;
 
-        r = ic.getWordRangeAtCursor(" ", 0);
+        r = ic.getWordRangeAtCursor(SPACE, 0);
         suggestions = r.getSuggestionSpansAtWord();
         assertEquals(suggestions.length, 1);
         MoreAsserts.assertEquals(suggestions[0].getSuggestions(), SUGGESTIONS1);
@@ -277,7 +283,7 @@
         text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS2, 0 /* flags */),
                 10 /* start */, 16 /* end */, 0 /* flags */);
         mockInputMethodService.setInputConnection(new MockConnection(text, cursorPos));
-        r = ic.getWordRangeAtCursor(" ", 0);
+        r = ic.getWordRangeAtCursor(SPACE, 0);
         suggestions = r.getSuggestionSpansAtWord();
         assertEquals(suggestions.length, 2);
         MoreAsserts.assertEquals(suggestions[0].getSuggestions(), SUGGESTIONS1);
@@ -290,7 +296,7 @@
         text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS2, 0 /* flags */),
                 5 /* start */, 16 /* end */, 0 /* flags */);
         mockInputMethodService.setInputConnection(new MockConnection(text, cursorPos));
-        r = ic.getWordRangeAtCursor(" ", 0);
+        r = ic.getWordRangeAtCursor(SPACE, 0);
         suggestions = r.getSuggestionSpansAtWord();
         assertEquals(suggestions.length, 1);
         MoreAsserts.assertEquals(suggestions[0].getSuggestions(), SUGGESTIONS1);
@@ -302,7 +308,7 @@
         text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS2, 0 /* flags */),
                 10 /* start */, 20 /* end */, 0 /* flags */);
         mockInputMethodService.setInputConnection(new MockConnection(text, cursorPos));
-        r = ic.getWordRangeAtCursor(" ", 0);
+        r = ic.getWordRangeAtCursor(SPACE, 0);
         suggestions = r.getSuggestionSpansAtWord();
         assertEquals(suggestions.length, 1);
         MoreAsserts.assertEquals(suggestions[0].getSuggestions(), SUGGESTIONS1);
@@ -314,7 +320,7 @@
         text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS2, 0 /* flags */),
                 5 /* start */, 20 /* end */, 0 /* flags */);
         mockInputMethodService.setInputConnection(new MockConnection(text, cursorPos));
-        r = ic.getWordRangeAtCursor(" ", 0);
+        r = ic.getWordRangeAtCursor(SPACE, 0);
         suggestions = r.getSuggestionSpansAtWord();
         assertEquals(suggestions.length, 1);
         MoreAsserts.assertEquals(suggestions[0].getSuggestions(), SUGGESTIONS1);
@@ -326,7 +332,7 @@
         text.setSpan(new SuggestionSpan(Locale.ENGLISH, SUGGESTIONS2, 0 /* flags */),
                 5 /* start */, 20 /* end */, 0 /* flags */);
         mockInputMethodService.setInputConnection(new MockConnection(text, cursorPos));
-        r = ic.getWordRangeAtCursor(" ", 0);
+        r = ic.getWordRangeAtCursor(SPACE, 0);
         suggestions = r.getSuggestionSpansAtWord();
         assertEquals(suggestions.length, 0);
     }
diff --git a/tests/src/com/android/inputmethod/latin/settings/SpacingAndPunctuationsTests.java b/tests/src/com/android/inputmethod/latin/settings/SpacingAndPunctuationsTests.java
new file mode 100644
index 0000000..424e7ff
--- /dev/null
+++ b/tests/src/com/android/inputmethod/latin/settings/SpacingAndPunctuationsTests.java
@@ -0,0 +1,401 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin.settings;
+
+import android.content.res.Resources;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.inputmethod.latin.SuggestedWords;
+import com.android.inputmethod.latin.utils.RunInLocale;
+
+import junit.framework.AssertionFailedError;
+
+import java.util.Locale;
+
+@SmallTest
+public class SpacingAndPunctuationsTests extends AndroidTestCase {
+    private static final int ARMENIAN_FULL_STOP = '\u0589';
+    private static final int ARMENIAN_COMMA = '\u055D';
+
+    private SpacingAndPunctuations ENGLISH;
+    private SpacingAndPunctuations FRENCH;
+    private SpacingAndPunctuations GERMAN;
+    private SpacingAndPunctuations ARMENIAN;
+    private SpacingAndPunctuations THAI;
+    private SpacingAndPunctuations KHMER;
+    private SpacingAndPunctuations LAO;
+    private SpacingAndPunctuations ARABIC;
+    private SpacingAndPunctuations PERSIAN;
+    private SpacingAndPunctuations HEBREW;
+
+    private SpacingAndPunctuations UNITED_STATES;
+    private SpacingAndPunctuations UNITED_KINGDOM;
+    private SpacingAndPunctuations CANADA_FRENCH;
+    private SpacingAndPunctuations SWISS_GERMAN;
+    private SpacingAndPunctuations INDIA_ENGLISH;
+    private SpacingAndPunctuations ARMENIA_ARMENIAN;
+    private SpacingAndPunctuations CAMBODIA_KHMER;
+    private SpacingAndPunctuations LAOS_LAO;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        // Language only
+        ENGLISH = getSpacingAndPunctuations(Locale.ENGLISH);
+        FRENCH = getSpacingAndPunctuations(Locale.FRENCH);
+        GERMAN = getSpacingAndPunctuations(Locale.GERMAN);
+        THAI = getSpacingAndPunctuations(new Locale("th"));
+        ARMENIAN = getSpacingAndPunctuations(new Locale("hy"));
+        KHMER = getSpacingAndPunctuations(new Locale("km"));
+        LAO = getSpacingAndPunctuations(new Locale("lo"));
+        ARABIC = getSpacingAndPunctuations(new Locale("ar"));
+        PERSIAN = getSpacingAndPunctuations(new Locale("fa"));
+        HEBREW = getSpacingAndPunctuations(new Locale("iw"));
+
+        // Language and Country
+        UNITED_STATES = getSpacingAndPunctuations(Locale.US);
+        UNITED_KINGDOM = getSpacingAndPunctuations(Locale.UK);
+        CANADA_FRENCH = getSpacingAndPunctuations(Locale.CANADA_FRENCH);
+        SWISS_GERMAN = getSpacingAndPunctuations(new Locale("de", "CH"));
+        INDIA_ENGLISH = getSpacingAndPunctuations(new Locale("en", "IN"));
+        ARMENIA_ARMENIAN = getSpacingAndPunctuations(new Locale("hy", "AM"));
+        CAMBODIA_KHMER = getSpacingAndPunctuations(new Locale("km", "KH"));
+        LAOS_LAO = getSpacingAndPunctuations(new Locale("lo", "LA"));
+    }
+
+    private SpacingAndPunctuations getSpacingAndPunctuations(final Locale locale) {
+        final RunInLocale<SpacingAndPunctuations> job = new RunInLocale<SpacingAndPunctuations>() {
+            @Override
+            protected SpacingAndPunctuations job(Resources res) {
+                return new SpacingAndPunctuations(res);
+            }
+        };
+        return job.runInLocale(getContext().getResources(), locale);
+    }
+
+    private static void testingStandardWordSeparator(final SpacingAndPunctuations sp) {
+        assertTrue("Tab",         sp.isWordSeparator('\t'));
+        assertTrue("Newline",     sp.isWordSeparator('\n'));
+        assertTrue("Space",       sp.isWordSeparator(' '));
+        assertTrue("Exclamation", sp.isWordSeparator('!'));
+        assertTrue("Quotation",   sp.isWordSeparator('"'));
+        assertFalse("Number",     sp.isWordSeparator('#'));
+        assertFalse("Dollar",     sp.isWordSeparator('$'));
+        assertFalse("Percent",    sp.isWordSeparator('%'));
+        assertTrue("Ampersand",   sp.isWordSeparator('&'));
+        assertFalse("Apostrophe", sp.isWordSeparator('\''));
+        assertTrue("L Paren",     sp.isWordSeparator('('));
+        assertTrue("R Paren",     sp.isWordSeparator(')'));
+        assertTrue("Asterisk",    sp.isWordSeparator('*'));
+        assertTrue("Plus",        sp.isWordSeparator('+'));
+        assertTrue("Comma",       sp.isWordSeparator(','));
+        assertFalse("Minus",      sp.isWordSeparator('-'));
+        assertTrue("Period",      sp.isWordSeparator('.'));
+        assertTrue("Slash",       sp.isWordSeparator('/'));
+        assertTrue("Colon",       sp.isWordSeparator(':'));
+        assertTrue("Semicolon",   sp.isWordSeparator(';'));
+        assertTrue("L Angle",     sp.isWordSeparator('<'));
+        assertTrue("Equal",       sp.isWordSeparator('='));
+        assertTrue("R Angle",     sp.isWordSeparator('>'));
+        assertTrue("Question",    sp.isWordSeparator('?'));
+        assertFalse("Atmark",     sp.isWordSeparator('@'));
+        assertTrue("L S Bracket", sp.isWordSeparator('['));
+        assertFalse("B Slash",    sp.isWordSeparator('\\'));
+        assertTrue("R S Bracket", sp.isWordSeparator(']'));
+        assertFalse("Circumflex", sp.isWordSeparator('^'));
+        assertTrue("Underscore",  sp.isWordSeparator('_'));
+        assertFalse("Grave",      sp.isWordSeparator('`'));
+        assertTrue("L C Brace",   sp.isWordSeparator('{'));
+        assertTrue("V Line",      sp.isWordSeparator('|'));
+        assertTrue("R C Brace",   sp.isWordSeparator('}'));
+        assertFalse("Tilde",      sp.isWordSeparator('~'));
+    }
+
+    public void testWordSeparator() {
+        testingStandardWordSeparator(ENGLISH);
+        testingStandardWordSeparator(FRENCH);
+        testingStandardWordSeparator(CANADA_FRENCH);
+        testingStandardWordSeparator(ARMENIA_ARMENIAN);
+        assertTrue(ARMENIA_ARMENIAN.isWordSeparator(ARMENIAN_FULL_STOP));
+        assertTrue(ARMENIA_ARMENIAN.isWordSeparator(ARMENIAN_COMMA));
+        // TODO: We should fix these.
+        testingStandardWordSeparator(ARMENIAN);
+        assertFalse(ARMENIAN.isWordSeparator(ARMENIAN_FULL_STOP));
+        assertFalse(ARMENIAN.isWordSeparator(ARMENIAN_COMMA));
+    }
+
+    private static void testingStandardWordConnector(final SpacingAndPunctuations sp) {
+        assertFalse("Tab",         sp.isWordConnector('\t'));
+        assertFalse("Newline",     sp.isWordConnector('\n'));
+        assertFalse("Space",       sp.isWordConnector(' '));
+        assertFalse("Exclamation", sp.isWordConnector('!'));
+        assertFalse("Quotation",   sp.isWordConnector('"'));
+        assertFalse("Number",      sp.isWordConnector('#'));
+        assertFalse("Dollar",      sp.isWordConnector('$'));
+        assertFalse("Percent",     sp.isWordConnector('%'));
+        assertFalse("Ampersand",   sp.isWordConnector('&'));
+        assertTrue("Apostrophe",   sp.isWordConnector('\''));
+        assertFalse("L Paren",     sp.isWordConnector('('));
+        assertFalse("R Paren",     sp.isWordConnector(')'));
+        assertFalse("Asterisk",    sp.isWordConnector('*'));
+        assertFalse("Plus",        sp.isWordConnector('+'));
+        assertFalse("Comma",       sp.isWordConnector(','));
+        assertTrue("Minus",        sp.isWordConnector('-'));
+        assertFalse("Period",      sp.isWordConnector('.'));
+        assertFalse("Slash",       sp.isWordConnector('/'));
+        assertFalse("Colon",       sp.isWordConnector(':'));
+        assertFalse("Semicolon",   sp.isWordConnector(';'));
+        assertFalse("L Angle",     sp.isWordConnector('<'));
+        assertFalse("Equal",       sp.isWordConnector('='));
+        assertFalse("R Angle",     sp.isWordConnector('>'));
+        assertFalse("Question",    sp.isWordConnector('?'));
+        assertFalse("Atmark",      sp.isWordConnector('@'));
+        assertFalse("L S Bracket", sp.isWordConnector('['));
+        assertFalse("B Slash",     sp.isWordConnector('\\'));
+        assertFalse("R S Bracket", sp.isWordConnector(']'));
+        assertFalse("Circumflex",  sp.isWordConnector('^'));
+        assertFalse("Underscore",  sp.isWordConnector('_'));
+        assertFalse("Grave",       sp.isWordConnector('`'));
+        assertFalse("L C Brace",   sp.isWordConnector('{'));
+        assertFalse("V Line",      sp.isWordConnector('|'));
+        assertFalse("R C Brace",   sp.isWordConnector('}'));
+        assertFalse("Tilde",       sp.isWordConnector('~'));
+
+    }
+
+    public void testWordConnector() {
+        testingStandardWordConnector(ENGLISH);
+        testingStandardWordConnector(FRENCH);
+        testingStandardWordConnector(CANADA_FRENCH);
+        testingStandardWordConnector(ARMENIA_ARMENIAN);
+    }
+
+    private static void testingCommonPrecededBySpace(final SpacingAndPunctuations sp) {
+        assertFalse("Tab",         sp.isUsuallyPrecededBySpace('\t'));
+        assertFalse("Newline",     sp.isUsuallyPrecededBySpace('\n'));
+        assertFalse("Space",       sp.isUsuallyPrecededBySpace(' '));
+        //assertFalse("Exclamation", sp.isUsuallyPrecededBySpace('!'));
+        assertFalse("Quotation",   sp.isUsuallyPrecededBySpace('"'));
+        assertFalse("Number",      sp.isUsuallyPrecededBySpace('#'));
+        assertFalse("Dollar",      sp.isUsuallyPrecededBySpace('$'));
+        assertFalse("Percent",     sp.isUsuallyPrecededBySpace('%'));
+        assertTrue("Ampersand",    sp.isUsuallyPrecededBySpace('&'));
+        assertFalse("Apostrophe",  sp.isUsuallyPrecededBySpace('\''));
+        assertTrue("L Paren",      sp.isUsuallyPrecededBySpace('('));
+        assertFalse("R Paren",     sp.isUsuallyPrecededBySpace(')'));
+        assertFalse("Asterisk",    sp.isUsuallyPrecededBySpace('*'));
+        assertFalse("Plus",        sp.isUsuallyPrecededBySpace('+'));
+        assertFalse("Comma",       sp.isUsuallyPrecededBySpace(','));
+        assertFalse("Minus",       sp.isUsuallyPrecededBySpace('-'));
+        assertFalse("Period",      sp.isUsuallyPrecededBySpace('.'));
+        assertFalse("Slash",       sp.isUsuallyPrecededBySpace('/'));
+        //assertFalse("Colon",       sp.isUsuallyPrecededBySpace(':'));
+        //assertFalse("Semicolon",   sp.isUsuallyPrecededBySpace(';'));
+        assertFalse("L Angle",     sp.isUsuallyPrecededBySpace('<'));
+        assertFalse("Equal",       sp.isUsuallyPrecededBySpace('='));
+        assertFalse("R Angle",     sp.isUsuallyPrecededBySpace('>'));
+        //assertFalse("Question",    sp.isUsuallyPrecededBySpace('?'));
+        assertFalse("Atmark",      sp.isUsuallyPrecededBySpace('@'));
+        assertTrue("L S Bracket",  sp.isUsuallyPrecededBySpace('['));
+        assertFalse("B Slash",     sp.isUsuallyPrecededBySpace('\\'));
+        assertFalse("R S Bracket", sp.isUsuallyPrecededBySpace(']'));
+        assertFalse("Circumflex",  sp.isUsuallyPrecededBySpace('^'));
+        assertFalse("Underscore",  sp.isUsuallyPrecededBySpace('_'));
+        assertFalse("Grave",       sp.isUsuallyPrecededBySpace('`'));
+        assertTrue("L C Brace",    sp.isUsuallyPrecededBySpace('{'));
+        assertFalse("V Line",      sp.isUsuallyPrecededBySpace('|'));
+        assertFalse("R C Brace",   sp.isUsuallyPrecededBySpace('}'));
+        assertFalse("Tilde",       sp.isUsuallyPrecededBySpace('~'));
+    }
+
+    private static void testingStandardPrecededBySpace(final SpacingAndPunctuations sp) {
+        testingCommonPrecededBySpace(sp);
+        assertFalse("Exclamation", sp.isUsuallyPrecededBySpace('!'));
+        assertFalse("Colon",       sp.isUsuallyPrecededBySpace(':'));
+        assertFalse("Semicolon",   sp.isUsuallyPrecededBySpace(';'));
+        assertFalse("Question",    sp.isUsuallyPrecededBySpace('?'));
+    }
+
+    public void testIsUsuallyPrecededBySpace() {
+        testingStandardPrecededBySpace(ENGLISH);
+        testingCommonPrecededBySpace(FRENCH);
+        assertTrue("Exclamation", FRENCH.isUsuallyPrecededBySpace('!'));
+        assertTrue("Colon",       FRENCH.isUsuallyPrecededBySpace(':'));
+        assertTrue("Semicolon",   FRENCH.isUsuallyPrecededBySpace(';'));
+        assertTrue("Question",    FRENCH.isUsuallyPrecededBySpace('?'));
+        testingCommonPrecededBySpace(CANADA_FRENCH);
+        assertFalse("Exclamation", CANADA_FRENCH.isUsuallyPrecededBySpace('!'));
+        assertTrue("Colon",        CANADA_FRENCH.isUsuallyPrecededBySpace(':'));
+        assertFalse("Semicolon",   CANADA_FRENCH.isUsuallyPrecededBySpace(';'));
+        assertFalse("Question",    CANADA_FRENCH.isUsuallyPrecededBySpace('?'));
+        testingStandardPrecededBySpace(ARMENIA_ARMENIAN);
+    }
+
+    private static void testingStandardFollowedBySpace(final SpacingAndPunctuations sp) {
+        assertFalse("Tab",         sp.isUsuallyFollowedBySpace('\t'));
+        assertFalse("Newline",     sp.isUsuallyFollowedBySpace('\n'));
+        assertFalse("Space",       sp.isUsuallyFollowedBySpace(' '));
+        assertTrue("Exclamation",  sp.isUsuallyFollowedBySpace('!'));
+        assertFalse("Quotation",   sp.isUsuallyFollowedBySpace('"'));
+        assertFalse("Number",      sp.isUsuallyFollowedBySpace('#'));
+        assertFalse("Dollar",      sp.isUsuallyFollowedBySpace('$'));
+        assertFalse("Percent",     sp.isUsuallyFollowedBySpace('%'));
+        assertTrue("Ampersand",    sp.isUsuallyFollowedBySpace('&'));
+        assertFalse("Apostrophe",  sp.isUsuallyFollowedBySpace('\''));
+        assertFalse("L Paren",     sp.isUsuallyFollowedBySpace('('));
+        assertTrue("R Paren",      sp.isUsuallyFollowedBySpace(')'));
+        assertFalse("Asterisk",    sp.isUsuallyFollowedBySpace('*'));
+        assertFalse("Plus",        sp.isUsuallyFollowedBySpace('+'));
+        assertTrue("Comma",        sp.isUsuallyFollowedBySpace(','));
+        assertFalse("Minus",       sp.isUsuallyFollowedBySpace('-'));
+        assertTrue("Period",       sp.isUsuallyFollowedBySpace('.'));
+        assertFalse("Slash",       sp.isUsuallyFollowedBySpace('/'));
+        assertTrue("Colon",        sp.isUsuallyFollowedBySpace(':'));
+        assertTrue("Semicolon",    sp.isUsuallyFollowedBySpace(';'));
+        assertFalse("L Angle",     sp.isUsuallyFollowedBySpace('<'));
+        assertFalse("Equal",       sp.isUsuallyFollowedBySpace('='));
+        assertFalse("R Angle",     sp.isUsuallyFollowedBySpace('>'));
+        assertTrue("Question",     sp.isUsuallyFollowedBySpace('?'));
+        assertFalse("Atmark",      sp.isUsuallyFollowedBySpace('@'));
+        assertFalse("L S Bracket", sp.isUsuallyFollowedBySpace('['));
+        assertFalse("B Slash",     sp.isUsuallyFollowedBySpace('\\'));
+        assertTrue("R S Bracket",  sp.isUsuallyFollowedBySpace(']'));
+        assertFalse("Circumflex",  sp.isUsuallyFollowedBySpace('^'));
+        assertFalse("Underscore",  sp.isUsuallyFollowedBySpace('_'));
+        assertFalse("Grave",       sp.isUsuallyFollowedBySpace('`'));
+        assertFalse("L C Brace",   sp.isUsuallyFollowedBySpace('{'));
+        assertFalse("V Line",      sp.isUsuallyFollowedBySpace('|'));
+        assertTrue("R C Brace",    sp.isUsuallyFollowedBySpace('}'));
+        assertFalse("Tilde",       sp.isUsuallyFollowedBySpace('~'));
+    }
+
+    public void testIsUsuallyFollowedBySpace() {
+        testingStandardFollowedBySpace(ENGLISH);
+        testingStandardFollowedBySpace(FRENCH);
+        testingStandardFollowedBySpace(CANADA_FRENCH);
+        testingStandardFollowedBySpace(ARMENIA_ARMENIAN);
+        assertTrue(ARMENIA_ARMENIAN.isUsuallyFollowedBySpace(ARMENIAN_FULL_STOP));
+        assertTrue(ARMENIA_ARMENIAN.isUsuallyFollowedBySpace(ARMENIAN_COMMA));
+    }
+
+    private static void testingStandardSentenceSeparator(final SpacingAndPunctuations sp) {
+        assertFalse("Tab",         sp.isUsuallyFollowedBySpace('\t'));
+        assertFalse("Newline",     sp.isUsuallyFollowedBySpace('\n'));
+        assertFalse("Space",       sp.isUsuallyFollowedBySpace(' '));
+        assertFalse("Exclamation", sp.isUsuallyFollowedBySpace('!'));
+        assertFalse("Quotation",   sp.isUsuallyFollowedBySpace('"'));
+        assertFalse("Number",      sp.isUsuallyFollowedBySpace('#'));
+        assertFalse("Dollar",      sp.isUsuallyFollowedBySpace('$'));
+        assertFalse("Percent",     sp.isUsuallyFollowedBySpace('%'));
+        assertFalse("Ampersand",   sp.isUsuallyFollowedBySpace('&'));
+        assertFalse("Apostrophe",  sp.isUsuallyFollowedBySpace('\''));
+        assertFalse("L Paren",     sp.isUsuallyFollowedBySpace('('));
+        assertFalse("R Paren",     sp.isUsuallyFollowedBySpace(')'));
+        assertFalse("Asterisk",    sp.isUsuallyFollowedBySpace('*'));
+        assertFalse("Plus",        sp.isUsuallyFollowedBySpace('+'));
+        assertFalse("Comma",       sp.isUsuallyFollowedBySpace(','));
+        assertFalse("Minus",       sp.isUsuallyFollowedBySpace('-'));
+        assertTrue("Period",       sp.isUsuallyFollowedBySpace('.'));
+        assertFalse("Slash",       sp.isUsuallyFollowedBySpace('/'));
+        assertFalse("Colon",       sp.isUsuallyFollowedBySpace(':'));
+        assertFalse("Semicolon",   sp.isUsuallyFollowedBySpace(';'));
+        assertFalse("L Angle",     sp.isUsuallyFollowedBySpace('<'));
+        assertFalse("Equal",       sp.isUsuallyFollowedBySpace('='));
+        assertFalse("R Angle",     sp.isUsuallyFollowedBySpace('>'));
+        assertFalse("Question",    sp.isUsuallyFollowedBySpace('?'));
+        assertFalse("Atmark",      sp.isUsuallyFollowedBySpace('@'));
+        assertFalse("L S Bracket", sp.isUsuallyFollowedBySpace('['));
+        assertFalse("B Slash",     sp.isUsuallyFollowedBySpace('\\'));
+        assertFalse("R S Bracket", sp.isUsuallyFollowedBySpace(']'));
+        assertFalse("Circumflex",  sp.isUsuallyFollowedBySpace('^'));
+        assertFalse("Underscore",  sp.isUsuallyFollowedBySpace('_'));
+        assertFalse("Grave",       sp.isUsuallyFollowedBySpace('`'));
+        assertFalse("L C Brace",   sp.isUsuallyFollowedBySpace('{'));
+        assertFalse("V Line",      sp.isUsuallyFollowedBySpace('|'));
+        assertFalse("R C Brace",   sp.isUsuallyFollowedBySpace('}'));
+        assertFalse("Tilde",       sp.isUsuallyFollowedBySpace('~'));
+    }
+
+    public void isSentenceSeparator() {
+        testingStandardSentenceSeparator(ENGLISH);
+        try {
+            testingStandardSentenceSeparator(ARMENIA_ARMENIAN);
+            fail("Armenian Sentence Separator");
+        } catch (final AssertionFailedError e) {
+            assertEquals("Period", e.getMessage());
+        }
+        assertTrue(ARMENIA_ARMENIAN.isSentenceSeparator(ARMENIAN_FULL_STOP));
+        assertFalse(ARMENIA_ARMENIAN.isSentenceSeparator(ARMENIAN_COMMA));
+    }
+
+    public void testLanguageHasSpace() {
+        assertTrue(ENGLISH.mCurrentLanguageHasSpaces);
+        assertTrue(FRENCH.mCurrentLanguageHasSpaces);
+        assertTrue(GERMAN.mCurrentLanguageHasSpaces);
+        assertFalse(THAI.mCurrentLanguageHasSpaces);
+        assertFalse(CAMBODIA_KHMER.mCurrentLanguageHasSpaces);
+        assertFalse(LAOS_LAO.mCurrentLanguageHasSpaces);
+        // TODO: We should fix these.
+        assertTrue(KHMER.mCurrentLanguageHasSpaces);
+        assertTrue(LAO.mCurrentLanguageHasSpaces);
+    }
+
+    public void testUsesAmericanTypography() {
+        assertTrue(ENGLISH.mUsesAmericanTypography);
+        assertTrue(UNITED_STATES.mUsesAmericanTypography);
+        assertTrue(UNITED_KINGDOM.mUsesAmericanTypography);
+        assertTrue(INDIA_ENGLISH.mUsesAmericanTypography);
+        assertFalse(FRENCH.mUsesAmericanTypography);
+        assertFalse(GERMAN.mUsesAmericanTypography);
+        assertFalse(SWISS_GERMAN.mUsesAmericanTypography);
+    }
+
+    public void testUsesGermanRules() {
+        assertFalse(ENGLISH.mUsesGermanRules);
+        assertFalse(FRENCH.mUsesGermanRules);
+        assertTrue(GERMAN.mUsesGermanRules);
+        assertTrue(SWISS_GERMAN.mUsesGermanRules);
+    }
+
+    private static void testingStandardPunctuationSuggestions(final SpacingAndPunctuations sp) {
+        final SuggestedWords suggestedWords = sp.mSuggestPuncList;
+        assertFalse("typedWordValid", suggestedWords.mTypedWordValid);
+        assertFalse("willAutoCorrect", suggestedWords.mWillAutoCorrect);
+        assertTrue("isPunctuationSuggestions", suggestedWords.mIsPunctuationSuggestions);
+        assertFalse("isObsoleteSuggestions", suggestedWords.mIsObsoleteSuggestions);
+        assertFalse("isPrediction", suggestedWords.mIsPrediction);
+        final String[] punctuations = {
+            "!", "?", ",", ":", ";", "\"", "(", ")", "'", "-", "/", "@", "_"
+        };
+        assertEquals("size", punctuations.length, suggestedWords.size());
+        for (int index = 0; index < punctuations.length; index++) {
+            assertEquals("punctuation at " + index,
+                    punctuations[index], suggestedWords.getWord(index));
+        }
+    }
+    public void testPunctuationSuggestions() {
+        testingStandardPunctuationSuggestions(ENGLISH);
+        testingStandardPunctuationSuggestions(FRENCH);
+        testingStandardPunctuationSuggestions(GERMAN);
+        // TODO: Should fix these RTL languages
+        testingStandardPunctuationSuggestions(ARABIC);
+        testingStandardPunctuationSuggestions(PERSIAN);
+        testingStandardPunctuationSuggestions(HEBREW);
+    }
+}
diff --git a/tests/src/com/android/inputmethod/latin/utils/RecapitalizeStatusTests.java b/tests/src/com/android/inputmethod/latin/utils/RecapitalizeStatusTests.java
index a520412..ada80c3 100644
--- a/tests/src/com/android/inputmethod/latin/utils/RecapitalizeStatusTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/RecapitalizeStatusTests.java
@@ -19,31 +19,35 @@
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 
+import com.android.inputmethod.latin.Constants;
+
 import java.util.Locale;
 
 @SmallTest
 public class RecapitalizeStatusTests extends AndroidTestCase {
+    private static final int[] SPACE = { Constants.CODE_SPACE };
+
     public void testTrim() {
         final RecapitalizeStatus status = new RecapitalizeStatus();
-        status.initialize(30, 40, "abcdefghij", Locale.ENGLISH, " ");
+        status.initialize(30, 40, "abcdefghij", Locale.ENGLISH, SPACE);
         status.trim();
         assertEquals("abcdefghij", status.getRecapitalizedString());
         assertEquals(30, status.getNewCursorStart());
         assertEquals(40, status.getNewCursorEnd());
 
-        status.initialize(30, 44, "    abcdefghij", Locale.ENGLISH, " ");
+        status.initialize(30, 44, "    abcdefghij", Locale.ENGLISH, SPACE);
         status.trim();
         assertEquals("abcdefghij", status.getRecapitalizedString());
         assertEquals(34, status.getNewCursorStart());
         assertEquals(44, status.getNewCursorEnd());
 
-        status.initialize(30, 40, "abcdefgh  ", Locale.ENGLISH, " ");
+        status.initialize(30, 40, "abcdefgh  ", Locale.ENGLISH, SPACE);
         status.trim();
         assertEquals("abcdefgh", status.getRecapitalizedString());
         assertEquals(30, status.getNewCursorStart());
         assertEquals(38, status.getNewCursorEnd());
 
-        status.initialize(30, 45, "   abcdefghij  ", Locale.ENGLISH, " ");
+        status.initialize(30, 45, "   abcdefghij  ", Locale.ENGLISH, SPACE);
         status.trim();
         assertEquals("abcdefghij", status.getRecapitalizedString());
         assertEquals(33, status.getNewCursorStart());
@@ -52,7 +56,7 @@
 
     public void testRotate() {
         final RecapitalizeStatus status = new RecapitalizeStatus();
-        status.initialize(29, 40, "abcd efghij", Locale.ENGLISH, " ");
+        status.initialize(29, 40, "abcd efghij", Locale.ENGLISH, SPACE);
         status.rotate();
         assertEquals("Abcd Efghij", status.getRecapitalizedString());
         assertEquals(29, status.getNewCursorStart());
@@ -64,7 +68,7 @@
         status.rotate();
         assertEquals("Abcd Efghij", status.getRecapitalizedString());
 
-        status.initialize(29, 40, "Abcd Efghij", Locale.ENGLISH, " ");
+        status.initialize(29, 40, "Abcd Efghij", Locale.ENGLISH, SPACE);
         status.rotate();
         assertEquals("ABCD EFGHIJ", status.getRecapitalizedString());
         assertEquals(29, status.getNewCursorStart());
@@ -76,7 +80,7 @@
         status.rotate();
         assertEquals("ABCD EFGHIJ", status.getRecapitalizedString());
 
-        status.initialize(29, 40, "ABCD EFGHIJ", Locale.ENGLISH, " ");
+        status.initialize(29, 40, "ABCD EFGHIJ", Locale.ENGLISH, SPACE);
         status.rotate();
         assertEquals("abcd efghij", status.getRecapitalizedString());
         assertEquals(29, status.getNewCursorStart());
@@ -88,7 +92,7 @@
         status.rotate();
         assertEquals("abcd efghij", status.getRecapitalizedString());
 
-        status.initialize(29, 39, "AbCDefghij", Locale.ENGLISH, " ");
+        status.initialize(29, 39, "AbCDefghij", Locale.ENGLISH, SPACE);
         status.rotate();
         assertEquals("abcdefghij", status.getRecapitalizedString());
         assertEquals(29, status.getNewCursorStart());
@@ -102,7 +106,7 @@
         status.rotate();
         assertEquals("abcdefghij", status.getRecapitalizedString());
 
-        status.initialize(29, 40, "Abcd efghij", Locale.ENGLISH, " ");
+        status.initialize(29, 40, "Abcd efghij", Locale.ENGLISH, SPACE);
         status.rotate();
         assertEquals("abcd efghij", status.getRecapitalizedString());
         assertEquals(29, status.getNewCursorStart());
@@ -116,7 +120,8 @@
         status.rotate();
         assertEquals("abcd efghij", status.getRecapitalizedString());
 
-        status.initialize(30, 34, "grüß", Locale.GERMAN, " "); status.rotate();
+        status.initialize(30, 34, "grüß", Locale.GERMAN, SPACE);
+        status.rotate();
         assertEquals("Grüß", status.getRecapitalizedString());
         assertEquals(30, status.getNewCursorStart());
         assertEquals(34, status.getNewCursorEnd());
@@ -133,7 +138,8 @@
         assertEquals(30, status.getNewCursorStart());
         assertEquals(34, status.getNewCursorEnd());
 
-        status.initialize(30, 33, "œuf", Locale.FRENCH, " "); status.rotate();
+        status.initialize(30, 33, "œuf", Locale.FRENCH, SPACE);
+        status.rotate();
         assertEquals("Œuf", status.getRecapitalizedString());
         assertEquals(30, status.getNewCursorStart());
         assertEquals(33, status.getNewCursorEnd());
@@ -150,7 +156,8 @@
         assertEquals(30, status.getNewCursorStart());
         assertEquals(33, status.getNewCursorEnd());
 
-        status.initialize(30, 33, "œUf", Locale.FRENCH, " "); status.rotate();
+        status.initialize(30, 33, "œUf", Locale.FRENCH, SPACE);
+        status.rotate();
         assertEquals("œuf", status.getRecapitalizedString());
         assertEquals(30, status.getNewCursorStart());
         assertEquals(33, status.getNewCursorEnd());
@@ -171,7 +178,8 @@
         assertEquals(30, status.getNewCursorStart());
         assertEquals(33, status.getNewCursorEnd());
 
-        status.initialize(30, 35, "école", Locale.FRENCH, " "); status.rotate();
+        status.initialize(30, 35, "école", Locale.FRENCH, SPACE);
+        status.rotate();
         assertEquals("École", status.getRecapitalizedString());
         assertEquals(30, status.getNewCursorStart());
         assertEquals(35, status.getNewCursorEnd());
diff --git a/tests/src/com/android/inputmethod/latin/utils/StringAndJsonUtilsTests.java b/tests/src/com/android/inputmethod/latin/utils/StringAndJsonUtilsTests.java
index 7196612..e55c32b 100644
--- a/tests/src/com/android/inputmethod/latin/utils/StringAndJsonUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/utils/StringAndJsonUtilsTests.java
@@ -19,6 +19,8 @@
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 
+import com.android.inputmethod.latin.Constants;
+
 import java.util.Arrays;
 import java.util.List;
 import java.util.Locale;
@@ -206,42 +208,47 @@
         assertTrue(StringUtils.isIdenticalAfterDowncase(""));
     }
 
-    private static void checkCapitalize(final String src, final String dst, final String separators,
-            final Locale locale) {
-        assertEquals(dst, StringUtils.capitalizeEachWord(src, separators, locale));
+    private static void checkCapitalize(final String src, final String dst,
+            final int[] sortedSeparators, final Locale locale) {
+        assertEquals(dst, StringUtils.capitalizeEachWord(src, sortedSeparators, locale));
         assert(src.equals(dst)
-                == StringUtils.isIdenticalAfterCapitalizeEachWord(src, separators));
+                == StringUtils.isIdenticalAfterCapitalizeEachWord(src, sortedSeparators));
     }
 
+    private static final int[] SPACE = { Constants.CODE_SPACE };
+    private static final int[] SPACE_PERIOD = StringUtils.toSortedCodePointArray(" .");
+    private static final int[] SENTENCE_SEPARATORS =
+            StringUtils.toSortedCodePointArray(" \n.!?*()&");
+    private static final int[] WORD_SEPARATORS = StringUtils.toSortedCodePointArray(" \n.!?*,();&");
+
     public void testCapitalizeEachWord() {
-        checkCapitalize("", "", " ", Locale.ENGLISH);
-        checkCapitalize("test", "Test", " ", Locale.ENGLISH);
-        checkCapitalize("    test", "    Test", " ", Locale.ENGLISH);
-        checkCapitalize("Test", "Test", " ", Locale.ENGLISH);
-        checkCapitalize("    Test", "    Test", " ", Locale.ENGLISH);
-        checkCapitalize(".Test", ".test", " ", Locale.ENGLISH);
-        checkCapitalize(".Test", ".Test", " .", Locale.ENGLISH);
-        checkCapitalize(".Test", ".Test", ". ", Locale.ENGLISH);
-        checkCapitalize("test and retest", "Test And Retest", " .", Locale.ENGLISH);
-        checkCapitalize("Test and retest", "Test And Retest", " .", Locale.ENGLISH);
-        checkCapitalize("Test And Retest", "Test And Retest", " .", Locale.ENGLISH);
-        checkCapitalize("Test And.Retest  ", "Test And.Retest  ", " .", Locale.ENGLISH);
-        checkCapitalize("Test And.retest  ", "Test And.Retest  ", " .", Locale.ENGLISH);
-        checkCapitalize("Test And.retest  ", "Test And.retest  ", " ", Locale.ENGLISH);
-        checkCapitalize("Test And.Retest  ", "Test And.retest  ", " ", Locale.ENGLISH);
-        checkCapitalize("test and ietest", "Test And İetest", " .", new Locale("tr"));
-        checkCapitalize("test and ietest", "Test And Ietest", " .", Locale.ENGLISH);
-        checkCapitalize("Test&Retest", "Test&Retest", " \n.!?*()&", Locale.ENGLISH);
-        checkCapitalize("Test&retest", "Test&Retest", " \n.!?*()&", Locale.ENGLISH);
-        checkCapitalize("test&Retest", "Test&Retest", " \n.!?*()&", Locale.ENGLISH);
+        checkCapitalize("", "", SPACE, Locale.ENGLISH);
+        checkCapitalize("test", "Test", SPACE, Locale.ENGLISH);
+        checkCapitalize("    test", "    Test", SPACE, Locale.ENGLISH);
+        checkCapitalize("Test", "Test", SPACE, Locale.ENGLISH);
+        checkCapitalize("    Test", "    Test", SPACE, Locale.ENGLISH);
+        checkCapitalize(".Test", ".test", SPACE, Locale.ENGLISH);
+        checkCapitalize(".Test", ".Test", SPACE_PERIOD, Locale.ENGLISH);
+        checkCapitalize("test and retest", "Test And Retest", SPACE_PERIOD, Locale.ENGLISH);
+        checkCapitalize("Test and retest", "Test And Retest", SPACE_PERIOD, Locale.ENGLISH);
+        checkCapitalize("Test And Retest", "Test And Retest", SPACE_PERIOD, Locale.ENGLISH);
+        checkCapitalize("Test And.Retest  ", "Test And.Retest  ", SPACE_PERIOD, Locale.ENGLISH);
+        checkCapitalize("Test And.retest  ", "Test And.Retest  ", SPACE_PERIOD, Locale.ENGLISH);
+        checkCapitalize("Test And.retest  ", "Test And.retest  ", SPACE, Locale.ENGLISH);
+        checkCapitalize("Test And.Retest  ", "Test And.retest  ", SPACE, Locale.ENGLISH);
+        checkCapitalize("test and ietest", "Test And İetest", SPACE_PERIOD, new Locale("tr"));
+        checkCapitalize("test and ietest", "Test And Ietest", SPACE_PERIOD, Locale.ENGLISH);
+        checkCapitalize("Test&Retest", "Test&Retest", SENTENCE_SEPARATORS, Locale.ENGLISH);
+        checkCapitalize("Test&retest", "Test&Retest", SENTENCE_SEPARATORS, Locale.ENGLISH);
+        checkCapitalize("test&Retest", "Test&Retest", SENTENCE_SEPARATORS, Locale.ENGLISH);
         checkCapitalize("rest\nrecreation! And in the end...",
-                "Rest\nRecreation! And In The End...", " \n.!?*,();&", Locale.ENGLISH);
+                "Rest\nRecreation! And In The End...", WORD_SEPARATORS, Locale.ENGLISH);
         checkCapitalize("lorem ipsum dolor sit amet", "Lorem Ipsum Dolor Sit Amet",
-                " \n.,!?*()&;", Locale.ENGLISH);
+                WORD_SEPARATORS, Locale.ENGLISH);
         checkCapitalize("Lorem!Ipsum (Dolor) Sit * Amet", "Lorem!Ipsum (Dolor) Sit * Amet",
-                " \n,.;!?*()&", Locale.ENGLISH);
+                WORD_SEPARATORS, Locale.ENGLISH);
         checkCapitalize("Lorem!Ipsum (dolor) Sit * Amet", "Lorem!Ipsum (Dolor) Sit * Amet",
-                " \n,.;!?*()&", Locale.ENGLISH);
+                WORD_SEPARATORS, Locale.ENGLISH);
     }
 
     public void testLooksLikeURL() {