Merge "Import translations. DO NOT MERGE"
diff --git a/java/res/layout/more_suggestions.xml b/java/res/layout/more_suggestions.xml
index 49a00c6..b41bb8a 100644
--- a/java/res/layout/more_suggestions.xml
+++ b/java/res/layout/more_suggestions.xml
@@ -29,6 +29,7 @@
             android:id="@+id/more_suggestions_view"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
+            latin:keyLetterSize="@dimen/suggestion_text_size"
             latin:keyLabelSize="@dimen/suggestion_text_size"
             latin:keyHintLetterRatio="@fraction/more_suggestions_info_ratio"
             latin:keyHintLetterColor="@android:color/white"
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 5236591..00d4dfe 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -1804,14 +1804,7 @@
 
     @Override
     public void pickSuggestionManually(final int index, final CharSequence suggestion,
-            int x, int y) {
-        mConnection.beginBatchEdit(getCurrentInputConnection());
-        pickSuggestionManuallyWhileInBatchEdit(index, suggestion, x, y);
-        mConnection.endBatchEdit();
-    }
-
-    public void pickSuggestionManuallyWhileInBatchEdit(final int index,
-        final CharSequence suggestion, final int x, final int y) {
+            final int x, final int y) {
         final SuggestedWords suggestedWords = mSuggestionsView.getSuggestions();
         // If this is a punctuation picked from the suggestion strip, pass it to onCodeInput
         if (suggestion.length() == 1 && isShowingPunctuationList()) {
@@ -1846,7 +1839,9 @@
             mKeyboardSwitcher.updateShiftState();
             resetComposingState(true /* alsoResetLastComposedWord */);
             final CompletionInfo completionInfo = mApplicationSpecifiedCompletions[index];
+            mConnection.beginBatchEdit(getCurrentInputConnection());
             mConnection.commitCompletion(completionInfo);
+            mConnection.endBatchEdit();
             if (ProductionFlag.IS_EXPERIMENTAL) {
                 ResearchLogger.latinIME_pickApplicationSpecifiedCompletion(index,
                         completionInfo.getText(), x, y);
diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java
index 227990a..0c19bed 100644
--- a/java/src/com/android/inputmethod/latin/RichInputConnection.java
+++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java
@@ -65,66 +65,70 @@
         if (--mNestLevel == 0 && null != mIC) mIC.endBatchEdit();
     }
 
+    private void checkBatchEdit() {
+        if (mNestLevel != 1) {
+            // TODO: exception instead
+            Log.e(TAG, "Batch edit level incorrect : " + mNestLevel);
+            Log.e(TAG, Utils.getStackTrace(4));
+        }
+    }
+
     public void finishComposingText() {
-        if (mNestLevel <= 0) Log.e(TAG, "Batch edit not in progress!"); // TODO: exception instead
+        checkBatchEdit();
         if (null != mIC) mIC.finishComposingText();
     }
 
     public void commitText(final CharSequence text, final int i) {
-        if (mNestLevel <= 0) Log.e(TAG, "Batch edit not in progress!"); // TODO: exception instead
+        checkBatchEdit();
         if (null != mIC) mIC.commitText(text, i);
     }
 
     public int getCursorCapsMode(final int inputType) {
-        if (mNestLevel <= 0) Log.e(TAG, "Batch edit not in progress!"); // TODO: exception instead
         if (null == mIC) return Constants.TextUtils.CAP_MODE_OFF;
         return mIC.getCursorCapsMode(inputType);
     }
 
     public CharSequence getTextBeforeCursor(final int i, final int j) {
-        if (mNestLevel <= 0) Log.e(TAG, "Batch edit not in progress!"); // TODO: exception instead
         if (null != mIC) return mIC.getTextBeforeCursor(i, j);
         return null;
     }
 
     public CharSequence getTextAfterCursor(final int i, final int j) {
-        if (mNestLevel <= 0) Log.e(TAG, "Batch edit not in progress!"); // TODO: exception instead
         if (null != mIC) return mIC.getTextAfterCursor(i, j);
         return null;
     }
 
     public void deleteSurroundingText(final int i, final int j) {
-        if (mNestLevel <= 0) Log.e(TAG, "Batch edit not in progress!"); // TODO: exception instead
+        checkBatchEdit();
         if (null != mIC) mIC.deleteSurroundingText(i, j);
     }
 
     public void performEditorAction(final int actionId) {
-        if (mNestLevel <= 0) Log.e(TAG, "Batch edit not in progress!"); // TODO: exception instead
         if (null != mIC) mIC.performEditorAction(actionId);
     }
 
     public void sendKeyEvent(final KeyEvent keyEvent) {
-        if (mNestLevel <= 0) Log.e(TAG, "Batch edit not in progress!"); // TODO: exception instead
+        checkBatchEdit();
         if (null != mIC) mIC.sendKeyEvent(keyEvent);
     }
 
     public void setComposingText(final CharSequence text, final int i) {
-        if (mNestLevel <= 0) Log.e(TAG, "Batch edit not in progress!"); // TODO: exception instead
+        checkBatchEdit();
         if (null != mIC) mIC.setComposingText(text, i);
     }
 
     public void setSelection(final int from, final int to) {
-        if (mNestLevel <= 0) Log.e(TAG, "Batch edit not in progress!"); // TODO: exception instead
+        checkBatchEdit();
         if (null != mIC) mIC.setSelection(from, to);
     }
 
     public void commitCorrection(final CorrectionInfo correctionInfo) {
-        if (mNestLevel <= 0) Log.e(TAG, "Batch edit not in progress!"); // TODO: exception instead
+        checkBatchEdit();
         if (null != mIC) mIC.commitCorrection(correctionInfo);
     }
 
     public void commitCompletion(final CompletionInfo completionInfo) {
-        if (mNestLevel <= 0) Log.e(TAG, "Batch edit not in progress!"); // TODO: exception instead
+        checkBatchEdit();
         if (null != mIC) mIC.commitCompletion(completionInfo);
     }
 
@@ -316,6 +320,7 @@
     }
 
     public void removeTrailingSpace() {
+        checkBatchEdit();
         final CharSequence lastOne = getTextBeforeCursor(1, 0);
         if (lastOne != null && lastOne.length() == 1
                 && lastOne.charAt(0) == Keyboard.CODE_SPACE) {
@@ -372,6 +377,7 @@
     }
 
     public boolean revertDoubleSpace() {
+        checkBatchEdit();
         // Here we test whether we indeed have a period and a space before us. This should not
         // be needed, but it's there just in case something went wrong.
         final CharSequence textBeforeCursor = getTextBeforeCursor(2, 0);
@@ -395,6 +401,7 @@
     }
 
     public boolean revertSwapPunctuation() {
+        checkBatchEdit();
         // Here we test whether we indeed have a space and something else before us. This should not
         // be needed, but it's there just in case something went wrong.
         final CharSequence textBeforeCursor = getTextBeforeCursor(2, 0);
diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java
index 903b5a3..f2d21ab 100644
--- a/java/src/com/android/inputmethod/latin/Utils.java
+++ b/java/src/com/android/inputmethod/latin/Utils.java
@@ -204,18 +204,24 @@
     }
 
     // Get the current stack trace
-    public static String getStackTrace() {
+    public static String getStackTrace(final int limit) {
         StringBuilder sb = new StringBuilder();
         try {
             throw new RuntimeException();
         } catch (RuntimeException e) {
             StackTraceElement[] frames = e.getStackTrace();
             // Start at 1 because the first frame is here and we don't care about it
-            for (int j = 1; j < frames.length; ++j) sb.append(frames[j].toString() + "\n");
+            for (int j = 1; j < frames.length && j < limit + 1; ++j) {
+                sb.append(frames[j].toString() + "\n");
+            }
         }
         return sb.toString();
     }
 
+    public static String getStackTrace() {
+        return getStackTrace(Integer.MAX_VALUE);
+    }
+
     public static class UsabilityStudyLogUtils {
         // TODO: remove code duplication with ResearchLog class
         private static final String USABILITY_TAG = UsabilityStudyLogUtils.class.getSimpleName();