Less aggressive CAPS mode prediction.

Don't auto-correct if the typed word has more than one uppercase letter.
Also, delay applying shift state to the keyboard so that fast backspaces are not interrupted by the
time taken to render the shifted/unshifted keyboard.
Show ellipsis on the ?123 key
diff --git a/res/xml-de/kbd_qwerty.xml b/res/xml-de/kbd_qwerty.xml
index 763492d..89e53ef 100755
--- a/res/xml-de/kbd_qwerty.xml
+++ b/res/xml-de/kbd_qwerty.xml
@@ -98,7 +98,7 @@
     <Row android:keyboardMode="@+id/mode_normal" android:rowEdgeFlags="bottom">
         <Key android:codes="-2" android:keyLabel="@string/label_symbol_key" 
                 android:popupKeyboard="@xml/kbd_popup_template"
-                android:popupCharacters=""
+                android:popupCharacters="_"
                 android:keyWidth="20%p" android:keyEdgeFlags="left"/>
         <Key android:keyLabel="," android:keyWidth="15%p" />
         <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space" 
@@ -114,7 +114,7 @@
     <Row android:keyboardMode="@+id/mode_url" android:rowEdgeFlags="bottom">
         <Key android:codes="-2" android:keyLabel="@string/label_symbol_key" 
                 android:popupKeyboard="@xml/kbd_popup_template"
-                android:popupCharacters=""
+                android:popupCharacters="_"
                 android:keyWidth="20%p" android:keyEdgeFlags="left"/>
         <Key android:keyLabel=".com" android:keyOutputText=".com"
                 android:popupKeyboard="@xml/popup_domains"
@@ -133,7 +133,7 @@
     <Row android:keyboardMode="@+id/mode_email" android:rowEdgeFlags="bottom">
         <Key android:codes="-2" android:keyLabel="@string/label_symbol_key" 
                 android:popupKeyboard="@xml/kbd_popup_template"
-                android:popupCharacters=""
+                android:popupCharacters="_"
                 android:keyWidth="20%p" android:keyEdgeFlags="left"/>
         <Key android:keyLabel="," android:keyWidth="15%p" />
         <Key android:keyLabel="\@" android:keyWidth="15%p"/>
@@ -150,7 +150,7 @@
     <Row android:keyboardMode="@+id/mode_im" android:rowEdgeFlags="bottom">
         <Key android:codes="-2" android:keyLabel="@string/label_symbol_key" 
                 android:popupKeyboard="@xml/kbd_popup_template"
-                android:popupCharacters=""
+                android:popupCharacters="_"
                 android:keyWidth="20%p" android:keyEdgeFlags="left"/>
         <Key android:keyLabel="," android:keyWidth="15%p"/>
         <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space" 
diff --git a/res/xml/kbd_phone.xml b/res/xml/kbd_phone.xml
index 880d961..d2bcdac 100755
--- a/res/xml/kbd_phone.xml
+++ b/res/xml/kbd_phone.xml
@@ -51,7 +51,7 @@
     <Row android:rowEdgeFlags="bottom">
         <Key android:codes="-2" android:keyIcon="@drawable/sym_keyboard_numalt"
                 android:popupKeyboard="@xml/kbd_popup_template"
-                android:popupCharacters=""
+                android:popupCharacters="_"
                 android:iconPreview="@drawable/sym_keyboard_feedback_numalt"/>
 
         <Key android:codes="48" android:keyIcon="@drawable/sym_keyboard_num0"/>
diff --git a/res/xml/kbd_phone_symbols.xml b/res/xml/kbd_phone_symbols.xml
index 9ce7a1a..107f85c 100755
--- a/res/xml/kbd_phone_symbols.xml
+++ b/res/xml/kbd_phone_symbols.xml
@@ -55,6 +55,8 @@
     
     <Row android:rowEdgeFlags="bottom">
         <Key android:codes="-2" android:keyLabel="@string/label_phone_key" 
+                android:popupKeyboard="@xml/kbd_popup_template"
+                android:popupCharacters="_"
                 android:keyEdgeFlags="left"/>
         <Key android:keyLabel="+"/>
         <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space" 
diff --git a/res/xml/kbd_qwerty.xml b/res/xml/kbd_qwerty.xml
index fb8c574..8d64d3e 100755
--- a/res/xml/kbd_qwerty.xml
+++ b/res/xml/kbd_qwerty.xml
@@ -109,7 +109,7 @@
     <Row android:keyboardMode="@+id/mode_normal" android:rowEdgeFlags="bottom">
         <Key android:codes="-2" android:keyLabel="@string/label_symbol_key" 
                 android:popupKeyboard="@xml/kbd_popup_template"
-                android:popupCharacters=""
+                android:popupCharacters="_"
                 android:keyWidth="20%p" android:keyEdgeFlags="left"/>
         <Key android:keyLabel="," android:keyWidth="15%p" />
         <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space" 
@@ -125,7 +125,7 @@
     <Row android:keyboardMode="@+id/mode_url" android:rowEdgeFlags="bottom">
         <Key android:codes="-2" android:keyLabel="@string/label_symbol_key" 
                 android:popupKeyboard="@xml/kbd_popup_template"
-                android:popupCharacters=""
+                android:popupCharacters="_"
                 android:keyWidth="20%p" android:keyEdgeFlags="left"/>
         <Key android:keyLabel=".com" android:keyOutputText=".com"
                 android:popupKeyboard="@xml/popup_domains"
@@ -144,7 +144,7 @@
     <Row android:keyboardMode="@+id/mode_email" android:rowEdgeFlags="bottom">
         <Key android:codes="-2" android:keyLabel="@string/label_symbol_key" 
                 android:popupKeyboard="@xml/kbd_popup_template"
-                android:popupCharacters=""
+                android:popupCharacters="_"
                 android:keyWidth="20%p" android:keyEdgeFlags="left"/>
         <Key android:keyLabel="," android:keyWidth="15%p" />
         <Key android:keyLabel="\@" android:keyWidth="15%p"/>
@@ -161,7 +161,7 @@
     <Row android:keyboardMode="@+id/mode_im" android:rowEdgeFlags="bottom">
         <Key android:codes="-2" android:keyLabel="@string/label_symbol_key" 
                 android:popupKeyboard="@xml/kbd_popup_template"
-                android:popupCharacters=""
+                android:popupCharacters="_"
                 android:keyWidth="20%p" android:keyEdgeFlags="left"/>
         <Key android:keyLabel="," android:keyWidth="15%p"/>
         <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space" 
@@ -174,4 +174,4 @@
                 android:keyWidth="20%p" android:keyEdgeFlags="right"/>
     </Row>
 </Keyboard>
-    
\ No newline at end of file
+    
diff --git a/res/xml/kbd_symbols.xml b/res/xml/kbd_symbols.xml
index 2a15039..ecdf751 100755
--- a/res/xml/kbd_symbols.xml
+++ b/res/xml/kbd_symbols.xml
@@ -121,7 +121,7 @@
     <Row  android:rowEdgeFlags="bottom">
         <Key android:codes="-2" android:keyLabel="@string/label_alpha_key" 
                 android:popupKeyboard="@xml/kbd_popup_template"
-                android:popupCharacters=""
+                android:popupCharacters="_"
                 android:keyWidth="20%p" android:keyEdgeFlags="left"/>
         <Key android:keyLabel="," android:keyWidth="15%p" 
                 android:popupKeyboard="@xml/kbd_popup_template"
diff --git a/res/xml/kbd_symbols_shift.xml b/res/xml/kbd_symbols_shift.xml
index 6a472a4..fee845e 100755
--- a/res/xml/kbd_symbols_shift.xml
+++ b/res/xml/kbd_symbols_shift.xml
@@ -79,7 +79,7 @@
     <Row android:rowEdgeFlags="bottom">
         <Key android:codes="-2" android:keyLabel="@string/label_alpha_key" android:keyWidth="20%p"
                 android:popupKeyboard="@xml/kbd_popup_template"
-                android:popupCharacters=""
+                android:popupCharacters="_"
                 android:keyEdgeFlags="left"/>
         <Key android:keyLabel="„" android:keyWidth="15%p" />
         <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space" android:keyWidth="30%p" 
diff --git a/src/com/android/inputmethod/latin/LatinIME.java b/src/com/android/inputmethod/latin/LatinIME.java
index eec78a1..3dfdc5f 100644
--- a/src/com/android/inputmethod/latin/LatinIME.java
+++ b/src/com/android/inputmethod/latin/LatinIME.java
@@ -71,6 +71,7 @@
 
     private static final int MSG_UPDATE_SUGGESTIONS = 0;
     private static final int MSG_START_TUTORIAL = 1;
+    private static final int MSG_UPDATE_SHIFT_STATE = 2;
     
     // How many continuous deletes at which to start deleting at a higher speed.
     private static final int DELETE_ACCELERATE_AT = 20;
@@ -153,6 +154,9 @@
                         }
                     }
                     break;
+                case MSG_UPDATE_SHIFT_STATE:
+                    updateShiftKeyState(getCurrentInputEditorInfo());
+                    break;
             }
         }
     };
@@ -321,7 +325,7 @@
         }
         mPredictionOn = mPredictionOn && mCorrectionMode > 0;
         checkTutorial(attribute.privateImeOptions);
-        if (TRACE) Debug.startMethodTracing("latinime");
+        if (TRACE) Debug.startMethodTracing("/data/trace/latinime");
     }
 
     @Override
@@ -622,7 +626,8 @@
         } else {
             deleteChar = true;
         }
-        updateShiftKeyState(getCurrentInputEditorInfo());
+        mHandler.removeMessages(MSG_UPDATE_SHIFT_STATE);
+        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_UPDATE_SHIFT_STATE), 300);
         TextEntryState.backspace();
         if (TextEntryState.getState() == TextEntryState.STATE_UNDO_COMMIT) {
             revertLastWord(deleteChar);
@@ -772,7 +777,9 @@
         if (mCorrectionMode == Suggest.CORRECTION_FULL) {
             correctionAvailable |= typedWordValid;
         }
-        
+        // Don't auto-correct words with multiple capital letter
+        correctionAvailable &= !mWord.isMostlyCaps();
+
         mCandidateView.setSuggestions(stringList, false, typedWordValid, correctionAvailable); 
         if (stringList.size() > 0) {
             if (correctionAvailable && !typedWordValid && stringList.size() > 1) {
diff --git a/src/com/android/inputmethod/latin/WordComposer.java b/src/com/android/inputmethod/latin/WordComposer.java
index c950a7f..6679fca 100644
--- a/src/com/android/inputmethod/latin/WordComposer.java
+++ b/src/com/android/inputmethod/latin/WordComposer.java
@@ -34,6 +34,8 @@
     private String mPreferredWord;
     
     private StringBuilder mTypedWord;
+
+    private int mCapsCount;
     
     /**
      * Whether the user chose to capitalize the word.
@@ -53,6 +55,7 @@
         mIsCapitalized = false;
         mPreferredWord = null;
         mTypedWord.setLength(0);
+        mCapsCount = 0;
     }
 
     /**
@@ -80,6 +83,7 @@
     public void add(int primaryCode, int[] codes) {
         mTypedWord.append((char) primaryCode);
         mCodes.add(codes);
+        if (Character.isUpperCase((char) primaryCode)) mCapsCount++;
     }
 
     /**
@@ -87,7 +91,10 @@
      */
     public void deleteLast() {
         mCodes.remove(mCodes.size() - 1);
-        mTypedWord.deleteCharAt(mTypedWord.length() - 1);
+        final int lastPos = mTypedWord.length() - 1;
+        char last = mTypedWord.charAt(lastPos);
+        mTypedWord.deleteCharAt(lastPos);
+        if (Character.isUpperCase(last)) mCapsCount--;
     }
 
     /**
@@ -138,4 +145,11 @@
     public CharSequence getPreferredWord() {
         return mPreferredWord != null ? mPreferredWord : getTypedWord();
     }
+
+    /**
+     * Returns true if more than one character is upper case, otherwise returns false.
+     */
+    public boolean isMostlyCaps() {
+        return mCapsCount > 1;
+    }
 }