Merge "Fix a bug where ampersands in XML would not work"
diff --git a/java/res/layout/vibration_settings_dialog.xml b/java/res/layout/vibration_settings_dialog.xml
new file mode 100644
index 0000000..981ba9b
--- /dev/null
+++ b/java/res/layout/vibration_settings_dialog.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, 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.
+*/
+-->
+
+<LinearLayout
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_margin="10dip">
+    <LinearLayout
+        android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:gravity="center_horizontal"
+        android:layout_margin="10dip">
+        <TextView android:id="@+id/vibration_value"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textSize="20dip"/>
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/settings_ms"
+            android:textSize="20dip"/>
+    </LinearLayout>
+    <SeekBar
+        android:id="@+id/vibration_settings"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:max="250"
+        android:layout_margin="10dip"/>
+</LinearLayout>
diff --git a/java/res/values/donottranslate.xml b/java/res/values/donottranslate.xml
index 75e22dd..aefaec9 100644
--- a/java/res/values/donottranslate.xml
+++ b/java/res/values/donottranslate.xml
@@ -165,4 +165,5 @@
     <!-- dictionary pack package name /settings activity (for shared prefs and settings) -->
     <string name="dictionary_pack_package_name">com.google.android.inputmethod.latin.dictionarypack</string>
     <string name="dictionary_pack_settings_activity">com.google.android.inputmethod.latin.dictionarypack.DictionarySettingsActivity</string>
+    <string name="settings_ms">ms</string>
 </resources>
diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml
index 2f591fd..a1c1a9f 100644
--- a/java/res/values/strings.xml
+++ b/java/res/values/strings.xml
@@ -343,4 +343,6 @@
 
     <!-- Title of an option for usability study mode -->
     <string name="prefs_usability_study_mode">Usability study mode</string>
+    <!-- Title of the settings for vibration duration -->
+    <string name="prefs_vibration_duration_settings">Vibration duration settings</string>
 </resources>
diff --git a/java/res/xml/prefs.xml b/java/res/xml/prefs.xml
index 24de95f..312af28 100644
--- a/java/res/xml/prefs.xml
+++ b/java/res/xml/prefs.xml
@@ -125,6 +125,9 @@
                 android:summary="@string/enable_span_insert_summary"
                 android:persistent="true"
                 android:defaultValue="true" />
+            <PreferenceScreen
+                android:key="pref_vibration_duration_settings"
+                android:title="@string/prefs_vibration_duration_settings"/>
             <!-- TODO: evaluate results and revive this option. The code
                 already supports it. -->
             <!-- <CheckBoxPreference -->
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java
index b1cc7ca..1e2ea55 100644
--- a/java/src/com/android/inputmethod/keyboard/Key.java
+++ b/java/src/com/android/inputmethod/keyboard/Key.java
@@ -19,6 +19,7 @@
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
+import android.graphics.Rect;
 import android.graphics.Typeface;
 import android.graphics.drawable.Drawable;
 import android.text.TextUtils;
@@ -86,6 +87,9 @@
     public final int mX;
     /** Y coordinate of the key in the keyboard layout */
     public final int mY;
+    /** Hit bounding box of the key */
+    public final Rect mHitBox = new Rect();
+
     /** Text to output when pressed. This can be multiple characters, like ".com" */
     public final CharSequence mOutputText;
     /** More keys */
@@ -93,14 +97,6 @@
     /** More keys maximum column number */
     public final int mMaxMoreKeysColumn;
 
-    /**
-     * Flags that specify the anchoring to edges of the keyboard for detecting touch events
-     * that are just out of the boundary of the key. This is a bit mask of
-     * {@link Keyboard#EDGE_LEFT}, {@link Keyboard#EDGE_RIGHT},
-     * {@link Keyboard#EDGE_TOP} and {@link Keyboard#EDGE_BOTTOM}.
-     */
-    private int mEdgeFlags;
-
     /** Background type that represents different key background visual than normal one. */
     public final int mBackgroundType;
     public static final int BACKGROUND_TYPE_NORMAL = 0;
@@ -167,23 +163,22 @@
      * This constructor is being used only for key in more keys keyboard.
      */
     public Key(Resources res, KeyboardParams params, String moreKeySpec,
-            int x, int y, int width, int height, int edgeFlags) {
+            int x, int y, int width, int height) {
         this(params, MoreKeySpecParser.getLabel(moreKeySpec), null, getIcon(params, moreKeySpec),
                 getCode(res, params, moreKeySpec), MoreKeySpecParser.getOutputText(moreKeySpec),
-                x, y, width, height, edgeFlags);
+                x, y, width, height);
     }
 
     /**
      * This constructor is being used only for key in popup suggestions pane.
      */
     public Key(KeyboardParams params, CharSequence label, CharSequence hintLabel, Drawable icon,
-            int code, CharSequence outputText, int x, int y, int width, int height, int edgeFlags) {
+            int code, CharSequence outputText, int x, int y, int width, int height) {
         mHeight = height - params.mVerticalGap;
         mHorizontalGap = params.mHorizontalGap;
         mVerticalGap = params.mVerticalGap;
         mVisualInsetsLeft = mVisualInsetsRight = 0;
         mWidth = width - mHorizontalGap;
-        mEdgeFlags = edgeFlags;
         mHintLabel = hintLabel;
         mLabelOption = 0;
         mBackgroundType = BACKGROUND_TYPE_NORMAL;
@@ -197,6 +192,7 @@
         // Horizontal gap is divided equally to both sides of the key.
         mX = x + mHorizontalGap / 2;
         mY = y;
+        mHitBox.set(x, y, x + width + 1, y + height);
     }
 
     /**
@@ -212,8 +208,9 @@
     public Key(Resources res, KeyboardParams params, KeyboardBuilder.Row row,
             XmlResourceParser parser, KeyStyles keyStyles) {
         final float horizontalGap = isSpacer() ? 0 : params.mHorizontalGap;
+        final int keyHeight = row.mRowHeight;
         mVerticalGap = params.mVerticalGap;
-        mHeight = row.mRowHeight - mVerticalGap;
+        mHeight = keyHeight - mVerticalGap;
 
         final TypedArray keyAttr = res.obtainAttributes(Xml.asAttributeSet(parser),
                 R.styleable.Keyboard_Key);
@@ -230,12 +227,14 @@
 
         final float keyXPos = row.getKeyX(keyAttr);
         final float keyWidth = row.getKeyWidth(keyAttr, keyXPos);
+        final int keyYPos = row.getKeyY();
 
         // Horizontal gap is divided equally to both sides of the key.
         mX = (int) (keyXPos + horizontalGap / 2);
-        mY = row.getKeyY();
+        mY = keyYPos;
         mWidth = (int) (keyWidth - horizontalGap);
         mHorizontalGap = (int) horizontalGap;
+        mHitBox.set((int)keyXPos, keyYPos, (int)(keyXPos + keyWidth) + 1, keyYPos + keyHeight);
         // Update row to have current x coordinate.
         row.setXPos(keyXPos + keyWidth);
 
@@ -256,7 +255,6 @@
                 R.styleable.Keyboard_Key_backgroundType, BACKGROUND_TYPE_NORMAL);
         mRepeatable = style.getBoolean(keyAttr, R.styleable.Keyboard_Key_isRepeatable, false);
         mEnabled = style.getBoolean(keyAttr, R.styleable.Keyboard_Key_enabled, true);
-        mEdgeFlags = 0;
 
         final KeyboardIconsSet iconsSet = params.mIconsSet;
         mVisualInsetsLeft = (int) KeyboardBuilder.getDimensionOrFraction(keyAttr,
@@ -294,8 +292,20 @@
         keyAttr.recycle();
     }
 
-    public void addEdgeFlags(int flags) {
-        mEdgeFlags |= flags;
+    public void markAsLeftEdge(KeyboardParams params) {
+        mHitBox.left = params.mHorizontalEdgesPadding;
+    }
+
+    public void markAsRightEdge(KeyboardParams params) {
+        mHitBox.right = params.mOccupiedWidth - params.mHorizontalEdgesPadding;
+    }
+
+    public void markAsTopEdge(KeyboardParams params) {
+        mHitBox.top = params.mTopPadding;
+    }
+
+    public void markAsBottomEdge(KeyboardParams params) {
+        mHitBox.bottom = params.mOccupiedHeight + params.mBottomPadding;
     }
 
     public boolean isSticky() {
@@ -427,23 +437,10 @@
      * @param y the y-coordinate of the point
      * @return whether or not the point falls on the key. If the key is attached to an edge, it will
      * assume that all points between the key and the edge are considered to be on the key.
+     * @see {@link #markAsLeftEdge(KeyboardParams)} etc.
      */
     public boolean isOnKey(int x, int y) {
-        final int left = mX - mHorizontalGap / 2;
-        final int right = left + mWidth + mHorizontalGap;
-        final int top = mY;
-        final int bottom = top + mHeight + mVerticalGap;
-        final int flags = mEdgeFlags;
-        if (flags == 0) {
-            return x >= left && x <= right && y >= top && y <= bottom;
-        }
-        final boolean leftEdge = (flags & Keyboard.EDGE_LEFT) != 0;
-        final boolean rightEdge = (flags & Keyboard.EDGE_RIGHT) != 0;
-        final boolean topEdge = (flags & Keyboard.EDGE_TOP) != 0;
-        final boolean bottomEdge = (flags & Keyboard.EDGE_BOTTOM) != 0;
-        // In order to mitigate rounding errors, we use (left <= x <= right) here.
-        return (x >= left || leftEdge) && (x <= right || rightEdge)
-                && (y >= top || topEdge) && (y <= bottom || bottomEdge);
+        return mHitBox.contains(x, y);
     }
 
     /**
@@ -547,7 +544,7 @@
          * This constructor is being used only for divider in more keys keyboard.
          */
         public Spacer(KeyboardParams params, Drawable icon, int x, int y, int width, int height) {
-            super(params, null, null, icon, Keyboard.CODE_DUMMY, null, x, y, width, height, 0);
+            super(params, null, null, icon, Keyboard.CODE_DUMMY, null, x, y, width, height);
         }
 
         @Override
diff --git a/java/src/com/android/inputmethod/keyboard/Keyboard.java b/java/src/com/android/inputmethod/keyboard/Keyboard.java
index d8f8bef..045f0d7 100644
--- a/java/src/com/android/inputmethod/keyboard/Keyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/Keyboard.java
@@ -47,11 +47,6 @@
  * </pre>
  */
 public class Keyboard {
-    public static final int EDGE_LEFT = 0x01;
-    public static final int EDGE_RIGHT = 0x02;
-    public static final int EDGE_TOP = 0x04;
-    public static final int EDGE_BOTTOM = 0x08;
-
     /** Some common keys code.  These should be aligned with values/keycodes.xml */
     public static final int CODE_ENTER = '\n';
     public static final int CODE_TAB = '\t';
diff --git a/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java b/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java
index c904394..d4b35a5 100644
--- a/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java
@@ -193,13 +193,11 @@
                 return (mNumRows - 1 - row) * mDefaultRowHeight + mTopPadding;
             }
 
-            public int getRowFlags(int row) {
-                int rowFlags = 0;
+            public void markAsEdgeKey(Key key, int row) {
                 if (row == 0)
-                    rowFlags |= Keyboard.EDGE_TOP;
+                    key.markAsTopEdge(this);
                 if (isTopRow(row))
-                    rowFlags |= Keyboard.EDGE_BOTTOM;
-                return rowFlags;
+                    key.markAsBottomEdge(this);
             }
 
             private boolean isTopRow(int rowCount) {
@@ -254,8 +252,8 @@
                 final String moreKeySpec = mMoreKeys[n].toString();
                 final int row = n / params.mNumColumns;
                 final Key key = new Key(mResources, params, moreKeySpec, params.getX(n, row),
-                        params.getY(row), params.mDefaultKeyWidth, params.mDefaultRowHeight,
-                        params.getRowFlags(row));
+                        params.getY(row), params.mDefaultKeyWidth, params.mDefaultRowHeight);
+                params.markAsEdgeKey(key, row);
                 params.onAddKey(key);
             }
             return new MiniKeyboard(params);
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
index 48f683a..187a1ad 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardBuilder.java
@@ -753,7 +753,7 @@
         if (mCurrentRow == null)
             throw new InflateException("orphant end row tag");
         if (mRightEdgeKey != null) {
-            mRightEdgeKey.addEdgeFlags(Keyboard.EDGE_RIGHT);
+            mRightEdgeKey.markAsRightEdge(mParams);
             mRightEdgeKey = null;
         }
         addEdgeSpace(mParams.mHorizontalEdgesPadding, row);
@@ -765,11 +765,11 @@
     private void endKey(Key key) {
         mParams.onAddKey(key);
         if (mLeftEdge) {
-            key.addEdgeFlags(Keyboard.EDGE_LEFT);
+            key.markAsLeftEdge(mParams);
             mLeftEdge = false;
         }
         if (mTopEdge) {
-            key.addEdgeFlags(Keyboard.EDGE_TOP);
+            key.markAsTopEdge(mParams);
         }
         mRightEdgeKey = key;
     }
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 32649d5..48a1f8b 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -2099,16 +2099,7 @@
     }
 
     private void updateKeypressVibrationDuration() {
-        final String[] durationPerHardwareList = mResources.getStringArray(
-                R.array.keypress_vibration_durations);
-        final String hardwarePrefix = Build.HARDWARE + ",";
-        for (final String element : durationPerHardwareList) {
-            if (element.startsWith(hardwarePrefix)) {
-                mKeypressVibrationDuration =
-                        Long.parseLong(element.substring(element.lastIndexOf(',') + 1));
-                break;
-            }
-        }
+        mKeypressVibrationDuration = Utils.getCurrentVibrationDuration(mPrefs, mResources);
     }
 
     private void playKeyClick(int primaryCode) {
diff --git a/java/src/com/android/inputmethod/latin/MoreSuggestions.java b/java/src/com/android/inputmethod/latin/MoreSuggestions.java
index 1afa072..9a59ef2 100644
--- a/java/src/com/android/inputmethod/latin/MoreSuggestions.java
+++ b/java/src/com/android/inputmethod/latin/MoreSuggestions.java
@@ -153,23 +153,19 @@
                 return (mOccupiedWidth - mDividerWidth * (numColumnInRow - 1)) / numColumnInRow;
             }
 
-            public int getFlags(int pos) {
-                int rowFlags = 0;
-
+            public void markAsEdgeKey(Key key, int pos) {
                 final int row = mRowNumbers[pos];
                 if (row == 0)
-                    rowFlags |= Keyboard.EDGE_BOTTOM;
+                    key.markAsBottomEdge(this);
                 if (row == mNumRows - 1)
-                    rowFlags |= Keyboard.EDGE_TOP;
+                    key.markAsTopEdge(this);
 
                 final int numColumnInRow = mNumColumnsInRow[row];
                 final int column = getColumnNumber(pos);
                 if (column == 0)
-                    rowFlags |= Keyboard.EDGE_LEFT;
+                    key.markAsLeftEdge(this);
                 if (column == numColumnInRow - 1)
-                    rowFlags |= Keyboard.EDGE_RIGHT;
-
-                return rowFlags;
+                    key.markAsRightEdge(this);
             }
         }
 
@@ -214,7 +210,8 @@
                 final int index = pos + SUGGESTION_CODE_BASE;
                 final Key key = new Key(
                         params, word, info, null, index, null, x, y, width,
-                        params.mDefaultRowHeight, params.getFlags(pos));
+                        params.mDefaultRowHeight);
+                params.markAsEdgeKey(key, pos);
                 params.onAddKey(key);
                 final int columnNumber = params.getColumnNumber(pos);
                 final int numColumnInRow = params.getNumColumnInRow(pos);
diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java
index d706cd0..a2e8966 100644
--- a/java/src/com/android/inputmethod/latin/Settings.java
+++ b/java/src/com/android/inputmethod/latin/Settings.java
@@ -36,7 +36,10 @@
 import android.text.TextUtils;
 import android.text.method.LinkMovementMethod;
 import android.util.Log;
+import android.view.View;
 import android.view.inputmethod.EditorInfo;
+import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
 import android.widget.TextView;
 
 import com.android.inputmethod.compat.CompatUtils;
@@ -89,6 +92,9 @@
 
     public static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode";
 
+    public static final String PREF_VIBRATION_DURATION_SETTINGS =
+            "pref_vibration_duration_settings";
+
     // Dialog ids
     private static final int VOICE_INPUT_CONFIRM_DIALOG = 0;
 
@@ -335,6 +341,7 @@
     private boolean mVoiceOn;
 
     private AlertDialog mDialog;
+    private TextView mVibrationSettingsTextView;
 
     private boolean mOkClicked = false;
     private String mVoiceModeOff;
@@ -475,6 +482,19 @@
                 miscSettings.removePreference(pref);
             }
         }
+
+        final PreferenceScreen vibrationSettingsPref =
+                (PreferenceScreen) findPreference(PREF_VIBRATION_DURATION_SETTINGS);
+        if (vibrationSettingsPref != null) {
+            vibrationSettingsPref.setOnPreferenceClickListener(
+                    new OnPreferenceClickListener() {
+                        @Override
+                        public boolean onPreferenceClick(Preference arg0) {
+                            showVibrationSettingsDialog();
+                            return true;
+                        }
+                    });
+        }
     }
 
     @SuppressWarnings("unused")
@@ -621,4 +641,51 @@
             mVoicePreference.setValue(mVoiceModeOff);
         }
     }
-}
+
+    private void showVibrationSettingsDialog() {
+        final SharedPreferences sp = getPreferenceManager().getSharedPreferences();
+        final Activity context = getActivityInternal();
+        final AlertDialog.Builder builder = new AlertDialog.Builder(context);
+        builder.setTitle(R.string.prefs_vibration_duration_settings);
+        builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+            @Override
+            public void onClick(DialogInterface dialog, int whichButton) {
+                final int ms = Integer.valueOf(mVibrationSettingsTextView.getText().toString());
+                sp.edit().putInt(Settings.PREF_VIBRATION_DURATION_SETTINGS, ms).apply();
+            }
+        });
+        builder.setNegativeButton(android.R.string.cancel,  new DialogInterface.OnClickListener() {
+            @Override
+            public void onClick(DialogInterface dialog, int whichButton) {
+                dialog.dismiss();
+            }
+        });
+        final View v = context.getLayoutInflater().inflate(
+                R.layout.vibration_settings_dialog, null);
+        final int currentMs = Utils.getCurrentVibrationDuration(
+                getPreferenceManager().getSharedPreferences(), getResources());
+        mVibrationSettingsTextView = (TextView)v.findViewById(R.id.vibration_value);
+        final SeekBar sb = (SeekBar)v.findViewById(R.id.vibration_settings);
+        sb.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
+            @Override
+            public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {
+                final int tempMs = arg1;
+                mVibrationSettingsTextView.setText(String.valueOf(tempMs));
+            }
+
+            @Override
+            public void onStartTrackingTouch(SeekBar arg0) {
+            }
+
+            @Override
+            public void onStopTrackingTouch(SeekBar arg0) {
+                final int tempMs = arg0.getProgress();
+                VibratorCompatWrapper.getInstance(context).vibrate(tempMs);
+            }
+        });
+        sb.setProgress(currentMs);
+        mVibrationSettingsTextView.setText(String.valueOf(currentMs));
+        builder.setView(v);
+        builder.create().show();
+    }
+}
\ No newline at end of file
diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java
index c35273e..7712765 100644
--- a/java/src/com/android/inputmethod/latin/Utils.java
+++ b/java/src/com/android/inputmethod/latin/Utils.java
@@ -17,9 +17,11 @@
 package com.android.inputmethod.latin;
 
 import android.content.Context;
+import android.content.SharedPreferences;
 import android.content.res.Resources;
 import android.inputmethodservice.InputMethodService;
 import android.os.AsyncTask;
+import android.os.Build;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Process;
@@ -772,4 +774,20 @@
         // - It also does not work with unicode surrogate code points.
         return s.toUpperCase(locale).charAt(0) + s.substring(1);
     }
+
+    public static int getCurrentVibrationDuration(SharedPreferences sp, Resources res) {
+        final int ms = sp.getInt(Settings.PREF_VIBRATION_DURATION_SETTINGS, -1);
+        if (ms >= 0) {
+            return ms;
+        }
+        final String[] durationPerHardwareList = res.getStringArray(
+                R.array.keypress_vibration_durations);
+        final String hardwarePrefix = Build.HARDWARE + ",";
+        for (final String element : durationPerHardwareList) {
+            if (element.startsWith(hardwarePrefix)) {
+                return (int)Long.parseLong(element.substring(element.lastIndexOf(',') + 1));
+            }
+        }
+        return -1;
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
index 77fbe3e..2546df0 100644
--- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
+++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java
@@ -85,10 +85,10 @@
     private static class SuggestionsGatherer implements WordCallback {
         public static class Result {
             public final String[] mSuggestions;
-            public final boolean mLooksLikeTypo;
-            public Result(final String[] gatheredSuggestions, final boolean looksLikeTypo) {
+            public final boolean mHasLikelySuggestions;
+            public Result(final String[] gatheredSuggestions, final boolean hasLikelySuggestions) {
                 mSuggestions = gatheredSuggestions;
-                mLooksLikeTypo = looksLikeTypo;
+                mHasLikelySuggestions = hasLikelySuggestions;
             }
         }
 
@@ -149,19 +149,19 @@
         public Result getResults(final CharSequence originalText, final double threshold,
                 final int capitalizeType, final Locale locale) {
             final String[] gatheredSuggestions;
-            final boolean looksLikeTypo;
+            final boolean hasLikelySuggestions;
             if (0 == mLength) {
                 // Either we found no suggestions, or we found some BUT the max length was 0.
                 // If we found some mBestSuggestion will not be null. If it is null, then
                 // we found none, regardless of the max length.
                 if (null == mBestSuggestion) {
                     gatheredSuggestions = null;
-                    looksLikeTypo = false;
+                    hasLikelySuggestions = false;
                 } else {
                     gatheredSuggestions = EMPTY_STRING_ARRAY;
                     final double normalizedScore =
                             Utils.calcNormalizedScore(originalText, mBestSuggestion, mBestScore);
-                    looksLikeTypo = (normalizedScore > threshold);
+                    hasLikelySuggestions = (normalizedScore > threshold);
                 }
             } else {
                 if (DBG) {
@@ -195,14 +195,14 @@
                 final CharSequence bestSuggestion = mSuggestions.get(0);
                 final double normalizedScore =
                         Utils.calcNormalizedScore(originalText, bestSuggestion, bestScore);
-                looksLikeTypo = (normalizedScore > threshold);
+                hasLikelySuggestions = (normalizedScore > threshold);
                 if (DBG) {
                     Log.i(TAG, "Best suggestion : " + bestSuggestion + ", score " + bestScore);
                     Log.i(TAG, "Normalized score = " + normalizedScore + " (threshold " + threshold
-                            + ") => looksLikeTypo = " + looksLikeTypo);
+                            + ") => hasLikelySuggestions = " + hasLikelySuggestions);
                 }
             }
-            return new Result(gatheredSuggestions, looksLikeTypo);
+            return new Result(gatheredSuggestions, hasLikelySuggestions);
         }
     }
 
@@ -349,6 +349,7 @@
                     }
                 }
 
+                // TODO: Don't gather suggestions if the limit is <= 0 unless necessary
                 final SuggestionsGatherer suggestionsGatherer =
                         new SuggestionsGatherer(suggestionsLimit);
                 final WordComposer composer = new WordComposer();
@@ -397,17 +398,18 @@
                 if (DBG) {
                     Log.i(TAG, "Spell checking results for " + text + " with suggestion limit "
                             + suggestionsLimit);
-                    Log.i(TAG, "IsInDict = " + result.mLooksLikeTypo);
-                    Log.i(TAG, "LooksLikeTypo = " + result.mLooksLikeTypo);
+                    Log.i(TAG, "IsInDict = " + isInDict);
+                    Log.i(TAG, "LooksLikeTypo = " + (!isInDict));
+                    Log.i(TAG, "HasLikelySuggestions = " + result.mHasLikelySuggestions);
                     for (String suggestion : result.mSuggestions) {
                         Log.i(TAG, suggestion);
                     }
                 }
 
+                // TODO: actually use result.mHasLikelySuggestions
                 final int flags =
-                        (isInDict ? SuggestionsInfo.RESULT_ATTR_IN_THE_DICTIONARY : 0)
-                                | (result.mLooksLikeTypo
-                                        ? SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO : 0);
+                        (isInDict ? SuggestionsInfo.RESULT_ATTR_IN_THE_DICTIONARY
+                                : SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO);
                 return new SuggestionsInfo(flags, result.mSuggestions);
             } catch (RuntimeException e) {
                 // Don't kill the keyboard if there is a bug in the spell checker