Merge "Remove useless processing (A65)"
diff --git a/java/AndroidManifest.xml b/java/AndroidManifest.xml
index 06d852b..6b82382 100644
--- a/java/AndroidManifest.xml
+++ b/java/AndroidManifest.xml
@@ -1,3 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.
+-->
+
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         coreApp="true"
         package="com.android.inputmethod.latin">
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java b/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java
index c41d245..dc27769 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardActionListener.java
@@ -64,6 +64,20 @@
      */
     public void onTextInput(CharSequence text);
 
+    // TODO: Should move this method to some more appropriate interface.
+    /**
+     * Called when user started batch input.
+     */
+    public void onStartBatchInput();
+
+    // TODO: Should move this method to some more appropriate interface.
+    /**
+     * Sends a sequence of characters to the listener as batch input.
+     *
+     * @param text the sequence of characters to be displayed as composing text.
+     */
+    public void onEndBatchInput(CharSequence text);
+
     /**
      * Called when user released a finger outside any key.
      */
@@ -85,6 +99,10 @@
         @Override
         public void onTextInput(CharSequence text) {}
         @Override
+        public void onStartBatchInput() {}
+        @Override
+        public void onEndBatchInput(CharSequence text) {}
+        @Override
         public void onCancelInput() {}
         @Override
         public boolean onCustomRequest(int requestCode) {
diff --git a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java
index be7644f..9c80691 100644
--- a/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MoreKeysKeyboardView.java
@@ -58,6 +58,16 @@
         }
 
         @Override
+        public void onStartBatchInput() {
+            mListener.onStartBatchInput();
+        }
+
+        @Override
+        public void onEndBatchInput(CharSequence text) {
+            mListener.onEndBatchInput(text);
+        }
+
+        @Override
         public void onCancelInput() {
             mListener.onCancelInput();
         }
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 571f717..5ed4fb4 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -1272,6 +1272,9 @@
             if (mCurrentSettings.isWordSeparator(primaryCode)) {
                 didAutoCorrect = handleSeparator(primaryCode, x, y, spaceState);
             } else {
+                if (SPACE_STATE_PHANTOM == spaceState) {
+                    commitTyped(LastComposedWord.NOT_A_SEPARATOR);
+                }
                 final Keyboard keyboard = mKeyboardSwitcher.getKeyboard();
                 if (keyboard != null && keyboard.hasProximityCharsCorrection(primaryCode)) {
                     handleCharacter(primaryCode, x, y, spaceState);
@@ -1313,6 +1316,31 @@
         resetComposingState(true /* alsoResetLastComposedWord */);
     }
 
+    @Override
+    public void onStartBatchInput() {
+        mConnection.beginBatchEdit();
+        if (mWordComposer.isComposingWord()) {
+            commitTyped(LastComposedWord.NOT_A_SEPARATOR);
+            mExpectingUpdateSelection = true;
+            // TODO: Can we remove this?
+            mSpaceState = SPACE_STATE_PHANTOM;
+        }
+        mConnection.endBatchEdit();
+    }
+
+    @Override
+    public void onEndBatchInput(CharSequence text) {
+        mConnection.beginBatchEdit();
+        if (SPACE_STATE_PHANTOM == mSpaceState) {
+            sendKeyCodePoint(Keyboard.CODE_SPACE);
+        }
+        mConnection.setComposingText(text, 1);
+        mExpectingUpdateSelection = true;
+        mConnection.endBatchEdit();
+        mKeyboardSwitcher.updateShiftState();
+        mSpaceState = SPACE_STATE_PHANTOM;
+    }
+
     private CharSequence specificTldProcessingOnTextInput(final CharSequence text) {
         if (text.length() <= 1 || text.charAt(0) != Keyboard.CODE_PERIOD
                 || !Character.isLetter(text.charAt(1))) {
@@ -1359,7 +1387,12 @@
         if (mWordComposer.isComposingWord()) {
             final int length = mWordComposer.size();
             if (length > 0) {
-                mWordComposer.deleteLast();
+                // Immediately after a batch input.
+                if (SPACE_STATE_PHANTOM == spaceState) {
+                    mWordComposer.reset();
+                } else {
+                    mWordComposer.deleteLast();
+                }
                 mConnection.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1);
                 // If we have deleted the last remaining character of a word, then we are not
                 // isComposingWord() any more.
@@ -1789,6 +1822,7 @@
             return;
         }
 
+        mConnection.beginBatchEdit();
         if (SPACE_STATE_PHANTOM == mSpaceState && suggestion.length() > 0) {
             int firstChar = Character.codePointAt(suggestion, 0);
             if ((!mCurrentSettings.isWeakSpaceStripper(firstChar))
@@ -1806,7 +1840,6 @@
             mKeyboardSwitcher.updateShiftState();
             resetComposingState(true /* alsoResetLastComposedWord */);
             final CompletionInfo completionInfo = mApplicationSpecifiedCompletions[index];
-            mConnection.beginBatchEdit();
             mConnection.commitCompletion(completionInfo);
             mConnection.endBatchEdit();
             if (ProductionFlag.IS_EXPERIMENTAL) {
@@ -1827,6 +1860,7 @@
         mExpectingUpdateSelection = true;
         commitChosenWord(suggestion, LastComposedWord.COMMIT_TYPE_MANUAL_PICK,
                 LastComposedWord.NOT_A_SEPARATOR);
+        mConnection.endBatchEdit();
         // Don't allow cancellation of manual pick
         mLastComposedWord.deactivate();
         mSpaceState = SPACE_STATE_PHANTOM;
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index bf5e05e..bfa41c7 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -34,7 +34,7 @@
 
     private int[] mPrimaryKeyCodes;
     private final InputPointers mInputPointers = new InputPointers();
-    private StringBuilder mTypedWord;
+    private final StringBuilder mTypedWord;
     private CharSequence mAutoCorrection;
     private boolean mIsResumed;
 
@@ -59,10 +59,6 @@
     }
 
     public WordComposer(WordComposer source) {
-        init(source);
-    }
-
-    public void init(WordComposer source) {
         mPrimaryKeyCodes = Arrays.copyOf(source.mPrimaryKeyCodes, source.mPrimaryKeyCodes.length);
         mTypedWord = new StringBuilder(source.mTypedWord);
         mInputPointers.copy(source.mInputPointers);