Merge "Correctly add double quote to the space strippers" into jb-mr1.1-dev
diff --git a/java/res/xml/method.xml b/java/res/xml/method.xml
index 3d360a8..0387071 100644
--- a/java/res/xml/method.xml
+++ b/java/res/xml/method.xml
@@ -36,6 +36,7 @@
     en_GB: English Great Britain/qwerty
     eo: Esperanto/spanish
     es: Spanish/spanish
+    es_US: Spanish United States/spanish
     et: Estonian/nordic
     fa: Persian/arabic
     fi: Finnish/nordic
@@ -184,6 +185,13 @@
     />
     <subtype android:icon="@drawable/ic_subtype_keyboard"
             android:label="@string/subtype_generic"
+            android:subtypeId="-2066550842"
+            android:imeSubtypeLocale="es_US"
+            android:imeSubtypeMode="keyboard"
+            android:imeSubtypeExtraValue="KeyboardLayoutSet=spanish,AsciiCapable"
+    />
+    <subtype android:icon="@drawable/ic_subtype_keyboard"
+            android:label="@string/subtype_generic"
             android:subtypeId="-332580523"
             android:imeSubtypeLocale="et"
             android:imeSubtypeMode="keyboard"
diff --git a/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java b/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java
index d126077..9394518 100644
--- a/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java
+++ b/java/src/com/android/inputmethod/latin/AdditionalSubtypeSettings.java
@@ -85,6 +85,9 @@
     }
 
     static final class SubtypeLocaleAdapter extends ArrayAdapter<SubtypeLocaleItem> {
+        private static final String TAG = SubtypeLocaleAdapter.class.getSimpleName();
+        private static final boolean DEBUG_SUBTYPE_ID = false;
+
         public SubtypeLocaleAdapter(final Context context) {
             super(context, android.R.layout.simple_spinner_item);
             setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
@@ -94,6 +97,11 @@
             final int count = imi.getSubtypeCount();
             for (int i = 0; i < count; i++) {
                 final InputMethodSubtype subtype = imi.getSubtypeAt(i);
+                if (DEBUG_SUBTYPE_ID) {
+                    android.util.Log.d(TAG, String.format("%-6s 0x%08x %11d %s",
+                            subtype.getLocale(), subtype.hashCode(), subtype.hashCode(),
+                            SubtypeLocale.getSubtypeDisplayName(subtype, context.getResources())));
+                }
                 if (subtype.containsExtraValueKey(ASCII_CAPABLE)) {
                     items.add(createItem(context, subtype.getLocale()));
                 }
diff --git a/java/src/com/android/inputmethod/latin/InputAttributes.java b/java/src/com/android/inputmethod/latin/InputAttributes.java
index 2f7608a..422fc72 100644
--- a/java/src/com/android/inputmethod/latin/InputAttributes.java
+++ b/java/src/com/android/inputmethod/latin/InputAttributes.java
@@ -29,6 +29,7 @@
     final public boolean mInputTypeNoAutoCorrect;
     final public boolean mIsSettingsSuggestionStripOn;
     final public boolean mApplicationSpecifiedCompletionOn;
+    final public boolean mShouldInsertSpacesAutomatically;
     final private int mInputType;
 
     public InputAttributes(final EditorInfo editorInfo, final boolean isFullscreenMode) {
@@ -54,6 +55,7 @@
             mIsSettingsSuggestionStripOn = false;
             mInputTypeNoAutoCorrect = false;
             mApplicationSpecifiedCompletionOn = false;
+            mShouldInsertSpacesAutomatically = false;
         } else {
             final int variation = inputType & InputType.TYPE_MASK_VARIATION;
             final boolean flagNoSuggestions =
@@ -65,6 +67,7 @@
             final boolean flagAutoComplete =
                     0 != (inputType & InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE);
 
+            // TODO: Have a helper method in InputTypeUtils
             // Make sure that passwords are not displayed in {@link SuggestionStripView}.
             if (InputTypeUtils.isPasswordInputType(inputType)
                     || InputTypeUtils.isVisiblePasswordInputType(inputType)
@@ -78,6 +81,8 @@
                 mIsSettingsSuggestionStripOn = true;
             }
 
+            mShouldInsertSpacesAutomatically = InputTypeUtils.isAutoSpaceFriendlyType(inputType);
+
             // If it's a browser edit field and auto correct is not ON explicitly, then
             // disable auto correction, but keep suggestions on.
             // If NO_SUGGESTIONS is set, don't do prediction.
diff --git a/java/src/com/android/inputmethod/latin/InputTypeUtils.java b/java/src/com/android/inputmethod/latin/InputTypeUtils.java
index 500866a..9a4503b 100644
--- a/java/src/com/android/inputmethod/latin/InputTypeUtils.java
+++ b/java/src/com/android/inputmethod/latin/InputTypeUtils.java
@@ -29,31 +29,37 @@
             TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_PASSWORD;
     private static final int TEXT_VISIBLE_PASSWORD_INPUT_TYPE =
             TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_VISIBLE_PASSWORD;
+    private static final int[] SUPPRESSING_AUTO_SPACES_FIELD_VARIATION = {
+        InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS,
+        InputType.TYPE_TEXT_VARIATION_PASSWORD,
+        InputType.TYPE_TEXT_VARIATION_URI,
+        InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD,
+        InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD };
 
     private InputTypeUtils() {
         // This utility class is not publicly instantiable.
     }
 
-    private static boolean isWebEditTextInputType(int inputType) {
+    private static boolean isWebEditTextInputType(final int inputType) {
         return inputType == (TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_WEB_EDIT_TEXT);
     }
 
-    private static boolean isWebPasswordInputType(int inputType) {
+    private static boolean isWebPasswordInputType(final int inputType) {
         return WEB_TEXT_PASSWORD_INPUT_TYPE != 0
                 && inputType == WEB_TEXT_PASSWORD_INPUT_TYPE;
     }
 
-    private static boolean isWebEmailAddressInputType(int inputType) {
+    private static boolean isWebEmailAddressInputType(final int inputType) {
         return WEB_TEXT_EMAIL_ADDRESS_INPUT_TYPE != 0
                 && inputType == WEB_TEXT_EMAIL_ADDRESS_INPUT_TYPE;
     }
 
-    private static boolean isNumberPasswordInputType(int inputType) {
+    private static boolean isNumberPasswordInputType(final int inputType) {
         return NUMBER_PASSWORD_INPUT_TYPE != 0
                 && inputType == NUMBER_PASSWORD_INPUT_TYPE;
     }
 
-    private static boolean isTextPasswordInputType(int inputType) {
+    private static boolean isTextPasswordInputType(final int inputType) {
         return inputType == TEXT_PASSWORD_INPUT_TYPE;
     }
 
@@ -61,12 +67,12 @@
         return variation == TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS;
     }
 
-    public static boolean isEmailVariation(int variation) {
+    public static boolean isEmailVariation(final int variation) {
         return variation == TYPE_TEXT_VARIATION_EMAIL_ADDRESS
                 || isWebEmailAddressVariation(variation);
     }
 
-    public static boolean isWebInputType(int inputType) {
+    public static boolean isWebInputType(final int inputType) {
         final int maskedInputType =
                 inputType & (TYPE_MASK_CLASS | TYPE_MASK_VARIATION);
         return isWebEditTextInputType(maskedInputType) || isWebPasswordInputType(maskedInputType)
@@ -74,7 +80,7 @@
     }
 
     // Please refer to TextView.isPasswordInputType
-    public static boolean isPasswordInputType(int inputType) {
+    public static boolean isPasswordInputType(final int inputType) {
         final int maskedInputType =
                 inputType & (TYPE_MASK_CLASS | TYPE_MASK_VARIATION);
         return isTextPasswordInputType(maskedInputType) || isWebPasswordInputType(maskedInputType)
@@ -82,9 +88,18 @@
     }
 
     // Please refer to TextView.isVisiblePasswordInputType
-    public static boolean isVisiblePasswordInputType(int inputType) {
+    public static boolean isVisiblePasswordInputType(final int inputType) {
         final int maskedInputType =
                 inputType & (TYPE_MASK_CLASS | TYPE_MASK_VARIATION);
         return maskedInputType == TEXT_VISIBLE_PASSWORD_INPUT_TYPE;
     }
+
+    public static boolean isAutoSpaceFriendlyType(final int inputType) {
+        if (TYPE_CLASS_TEXT != (TYPE_MASK_CLASS & inputType)) return false;
+        final int variation = TYPE_MASK_VARIATION & inputType;
+        for (final int fieldVariation : SUPPRESSING_AUTO_SPACES_FIELD_VARIATION) {
+            if (variation == fieldVariation) return false;
+        }
+        return true;
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index ddfc273..f416396 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -2257,7 +2257,9 @@
 
     // This essentially inserts a space, and that's it.
     public void promotePhantomSpace() {
-        sendKeyCodePoint(Keyboard.CODE_SPACE);
+        if (mCurrentSettings.shouldInsertSpacesAutomatically()) {
+            sendKeyCodePoint(Keyboard.CODE_SPACE);
+        }
     }
 
     // Used by the RingCharBuffer
diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java
index 2a778aa..2f49fe9 100644
--- a/java/src/com/android/inputmethod/latin/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/SettingsValues.java
@@ -271,6 +271,10 @@
         return mPhantomSpacePromotingSymbols.contains(String.valueOf((char)code));
     }
 
+    public boolean shouldInsertSpacesAutomatically() {
+        return mInputAttributes.mShouldInsertSpacesAutomatically;
+    }
+
     private static boolean isAutoCorrectEnabled(final Resources res,
             final String currentAutoCorrectionSetting) {
         final String autoCorrectionOff = res.getString(
diff --git a/native/jni/src/defines.h b/native/jni/src/defines.h
index ea0f0ef..e06ee42 100644
--- a/native/jni/src/defines.h
+++ b/native/jni/src/defines.h
@@ -250,6 +250,12 @@
 #ifndef S_INT_MAX
 #define S_INT_MAX 2147483647 // ((1 << 31) - 1)
 #endif
+#ifndef S_INT_MIN
+// The literal constant -2147483648 does not work in C prior C90, because
+// the compiler tries to fit the positive number into an int and then negate it.
+// GCC warns about this.
+#define S_INT_MIN (-2147483647 - 1) // -(1 << 31)
+#endif
 
 // Define this to use mmap() for dictionary loading.  Undefine to use malloc() instead of mmap().
 // We measured and compared performance of both, and found mmap() is fairly good in terms of