Merge "Import revised translations.  DO NOT MERGE" into gingerbread
diff --git a/java/res/anim/key_preview_fadein.xml b/java/res/anim/key_preview_fadein.xml
new file mode 100644
index 0000000..9fad7b9
--- /dev/null
+++ b/java/res/anim/key_preview_fadein.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2010, 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.
+*/
+-->
+
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:interpolator="@android:anim/decelerate_interpolator"
+>
+    <alpha
+        android:fromAlpha="0.5"
+        android:toAlpha="1.0"
+        android:duration="@integer/config_preview_fadein_anim_time" />
+</set>
diff --git a/java/res/anim/key_preview_fadeout.xml b/java/res/anim/key_preview_fadeout.xml
new file mode 100644
index 0000000..7de5123
--- /dev/null
+++ b/java/res/anim/key_preview_fadeout.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2010, 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.
+*/
+-->
+
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:interpolator="@android:anim/accelerate_interpolator"
+>
+    <alpha
+        android:fromAlpha="1.0"
+        android:toAlpha="0.0"
+        android:duration="@integer/config_preview_fadeout_anim_time" />
+</set>
diff --git a/java/res/anim/mini_keyboard_fadein.xml b/java/res/anim/mini_keyboard_fadein.xml
new file mode 100644
index 0000000..9fad7b9
--- /dev/null
+++ b/java/res/anim/mini_keyboard_fadein.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2010, 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.
+*/
+-->
+
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:interpolator="@android:anim/decelerate_interpolator"
+>
+    <alpha
+        android:fromAlpha="0.5"
+        android:toAlpha="1.0"
+        android:duration="@integer/config_preview_fadein_anim_time" />
+</set>
diff --git a/java/res/anim/mini_keyboard_fadeout.xml b/java/res/anim/mini_keyboard_fadeout.xml
new file mode 100644
index 0000000..7de5123
--- /dev/null
+++ b/java/res/anim/mini_keyboard_fadeout.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2010, 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.
+*/
+-->
+
+<set
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:interpolator="@android:anim/accelerate_interpolator"
+>
+    <alpha
+        android:fromAlpha="1.0"
+        android:toAlpha="0.0"
+        android:duration="@integer/config_preview_fadeout_anim_time" />
+</set>
diff --git a/java/res/drawable-mdpi/keyboard_hint_0.9.png b/java/res/drawable-mdpi/keyboard_hint_0.9.png
index 271264e..61ad1b5 100644
--- a/java/res/drawable-mdpi/keyboard_hint_0.9.png
+++ b/java/res/drawable-mdpi/keyboard_hint_0.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/keyboard_hint_1.9.png b/java/res/drawable-mdpi/keyboard_hint_1.9.png
index eaf3742..cd7772e 100644
--- a/java/res/drawable-mdpi/keyboard_hint_1.9.png
+++ b/java/res/drawable-mdpi/keyboard_hint_1.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/keyboard_hint_2.9.png b/java/res/drawable-mdpi/keyboard_hint_2.9.png
index 8a16571..fa5f8b7 100644
--- a/java/res/drawable-mdpi/keyboard_hint_2.9.png
+++ b/java/res/drawable-mdpi/keyboard_hint_2.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/keyboard_hint_3.9.png b/java/res/drawable-mdpi/keyboard_hint_3.9.png
index 34b5011..0c7336c 100644
--- a/java/res/drawable-mdpi/keyboard_hint_3.9.png
+++ b/java/res/drawable-mdpi/keyboard_hint_3.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/keyboard_hint_4.9.png b/java/res/drawable-mdpi/keyboard_hint_4.9.png
index d4cc250..73ef06c 100644
--- a/java/res/drawable-mdpi/keyboard_hint_4.9.png
+++ b/java/res/drawable-mdpi/keyboard_hint_4.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/keyboard_hint_5.9.png b/java/res/drawable-mdpi/keyboard_hint_5.9.png
index 6a054b4..aea460e 100644
--- a/java/res/drawable-mdpi/keyboard_hint_5.9.png
+++ b/java/res/drawable-mdpi/keyboard_hint_5.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/keyboard_hint_6.9.png b/java/res/drawable-mdpi/keyboard_hint_6.9.png
index 66e9140..16a9237 100644
--- a/java/res/drawable-mdpi/keyboard_hint_6.9.png
+++ b/java/res/drawable-mdpi/keyboard_hint_6.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/keyboard_hint_7.9.png b/java/res/drawable-mdpi/keyboard_hint_7.9.png
index 5eae24f..6747a19 100644
--- a/java/res/drawable-mdpi/keyboard_hint_7.9.png
+++ b/java/res/drawable-mdpi/keyboard_hint_7.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/keyboard_hint_8.9.png b/java/res/drawable-mdpi/keyboard_hint_8.9.png
index ea7f512..28be2fb 100644
--- a/java/res/drawable-mdpi/keyboard_hint_8.9.png
+++ b/java/res/drawable-mdpi/keyboard_hint_8.9.png
Binary files differ
diff --git a/java/res/drawable-mdpi/keyboard_hint_9.9.png b/java/res/drawable-mdpi/keyboard_hint_9.9.png
index 0bf85de..731d63b 100644
--- a/java/res/drawable-mdpi/keyboard_hint_9.9.png
+++ b/java/res/drawable-mdpi/keyboard_hint_9.9.png
Binary files differ
diff --git a/java/res/values/config.xml b/java/res/values/config.xml
new file mode 100644
index 0000000..6e941ba
--- /dev/null
+++ b/java/res/values/config.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2010, 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.
+*/
+-->
+
+<resources>
+    <integer name="config_delay_before_preview">0</integer>
+    <integer name="config_delay_after_preview">10</integer>
+    <integer name="config_preview_fadein_anim_time">0</integer>
+    <integer name="config_preview_fadeout_anim_time">90</integer>
+    <integer name="config_mini_keyboard_fadein_anim_time">0</integer>
+    <integer name="config_mini_keyboard_fadeout_anim_time">100</integer>
+</resources>
diff --git a/java/res/values/styles.xml b/java/res/values/styles.xml
index 60fffe8..5e23948 100644
--- a/java/res/values/styles.xml
+++ b/java/res/values/styles.xml
@@ -33,4 +33,12 @@
         <item name="backgroundDimAmount">0.5</item>
         <item name="symbolColorScheme">white</item>
     </style>
+    <style name="KeyPreviewAnimation">
+        <item name="android:windowEnterAnimation">@anim/key_preview_fadein</item>
+        <item name="android:windowExitAnimation">@anim/key_preview_fadeout</item>
+    </style>
+    <style name="MiniKeyboardAnimation">
+        <item name="android:windowEnterAnimation">@anim/mini_keyboard_fadein</item>
+        <item name="android:windowExitAnimation">@anim/mini_keyboard_fadeout</item>
+    </style>
 </resources>
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 2c0b809..696f530 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -16,6 +16,7 @@
 
 package com.android.inputmethod.latin;
 
+import com.android.inputmethod.latin.LatinIMEUtil.RingCharBuffer;
 import com.android.inputmethod.voice.FieldContext;
 import com.android.inputmethod.voice.SettingsUtil;
 import com.android.inputmethod.voice.VoiceInput;
@@ -1197,7 +1198,8 @@
                 if (primaryCode != KEYCODE_ENTER) {
                     mJustAddedAutoSpace = false;
                 }
-                LatinImeLogger.logOnInputChar((char)primaryCode, x, y);
+                RingCharBuffer.getInstance().push((char)primaryCode, x, y);
+                LatinImeLogger.logOnInputChar();
                 if (isWordSeparator(primaryCode)) {
                     handleSeparator(primaryCode);
                 } else {
diff --git a/java/src/com/android/inputmethod/latin/LatinIMEUtil.java b/java/src/com/android/inputmethod/latin/LatinIMEUtil.java
index 34b5284..85ecaee 100644
--- a/java/src/com/android/inputmethod/latin/LatinIMEUtil.java
+++ b/java/src/com/android/inputmethod/latin/LatinIMEUtil.java
@@ -80,4 +80,92 @@
         return ((InputMethodManager) context.getSystemService(
                 Context.INPUT_METHOD_SERVICE)).getEnabledInputMethodList().size() > 1;
     }
+
+    /* package */ static class RingCharBuffer {
+        private static RingCharBuffer sRingCharBuffer = new RingCharBuffer();
+        private static final char PLACEHOLDER_DELIMITER_CHAR = '\uFFFC';
+        private static final int INVALID_COORDINATE = -2;
+        /* package */ static final int BUFSIZE = 20;
+        private Context mContext;
+        private boolean mEnabled = false;
+        private int mEnd = 0;
+        /* package */ int mLength = 0;
+        private char[] mCharBuf = new char[BUFSIZE];
+        private int[] mXBuf = new int[BUFSIZE];
+        private int[] mYBuf = new int[BUFSIZE];
+
+        private RingCharBuffer() {
+        }
+        public static RingCharBuffer getInstance() {
+            return sRingCharBuffer;
+        }
+        public static RingCharBuffer init(Context context, boolean enabled) {
+            sRingCharBuffer.mContext = context;
+            sRingCharBuffer.mEnabled = enabled;
+            return sRingCharBuffer;
+        }
+        private int normalize(int in) {
+            int ret = in % BUFSIZE;
+            return ret < 0 ? ret + BUFSIZE : ret;
+        }
+        public void push(char c, int x, int y) {
+            if (!mEnabled) return;
+            mCharBuf[mEnd] = c;
+            mXBuf[mEnd] = x;
+            mYBuf[mEnd] = y;
+            mEnd = normalize(mEnd + 1);
+            if (mLength < BUFSIZE) {
+                ++mLength;
+            }
+        }
+        public char pop() {
+            if (mLength < 1) {
+                return PLACEHOLDER_DELIMITER_CHAR;
+            } else {
+                mEnd = normalize(mEnd - 1);
+                --mLength;
+                return mCharBuf[mEnd];
+            }
+        }
+        public char getLastChar() {
+            if (mLength < 1) {
+                return PLACEHOLDER_DELIMITER_CHAR;
+            } else {
+                return mCharBuf[normalize(mEnd - 1)];
+            }
+        }
+        public int getPreviousX(char c, int back) {
+            int index = normalize(mEnd - 2 - back);
+            if (mLength <= back
+                    || Character.toLowerCase(c) != Character.toLowerCase(mCharBuf[index])) {
+                return INVALID_COORDINATE;
+            } else {
+                return mXBuf[index];
+            }
+        }
+        public int getPreviousY(char c, int back) {
+            int index = normalize(mEnd - 2 - back);
+            if (mLength <= back
+                    || Character.toLowerCase(c) != Character.toLowerCase(mCharBuf[index])) {
+                return INVALID_COORDINATE;
+            } else {
+                return mYBuf[index];
+            }
+        }
+        public String getLastString() {
+            StringBuffer sb = new StringBuffer();
+            for (int i = 0; i < mLength; ++i) {
+                char c = mCharBuf[normalize(mEnd - 1 - i)];
+                if (!((LatinIME)mContext).isWordSeparator(c)) {
+                    sb.append(c);
+                } else {
+                    break;
+                }
+            }
+            return sb.reverse().toString();
+        }
+        public void reset() {
+            mLength = 0;
+        }
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/LatinImeLogger.java b/java/src/com/android/inputmethod/latin/LatinImeLogger.java
index 007d0cc..6d15d21 100644
--- a/java/src/com/android/inputmethod/latin/LatinImeLogger.java
+++ b/java/src/com/android/inputmethod/latin/LatinImeLogger.java
@@ -50,7 +50,7 @@
     public static void logOnDelete() {
     }
 
-    public static void logOnInputChar(char c, int x, int y) {
+    public static void logOnInputChar() {
     }
 
     public static void logOnException(String metaData, Throwable e) {
diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java
index eeccb96..3761dab 100644
--- a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java
+++ b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java
@@ -154,8 +154,6 @@
     }
 
     // Timing constants
-    private static final int DELAY_BEFORE_PREVIEW = 0;
-    private static final int DELAY_AFTER_PREVIEW = 100;
     private static final int REPEAT_INTERVAL = PointerTracker.REPEAT_INTERVAL;
 
     // Miscellaneous constants
@@ -194,6 +192,8 @@
     private int mPopupPreviewOffsetY;
     private int mWindowY;
     private int mPopupPreviewDisplayedY;
+    private final int mDelayBeforePreview;
+    private final int mDelayAfterPreview;
 
     // Popup mini keyboard
     private PopupWindow mMiniKeyboardPopup;
@@ -255,7 +255,7 @@
                     showKey(msg.arg1, (PointerTracker)msg.obj);
                     break;
                 case MSG_DISMISS_PREVIEW:
-                    mPreviewText.setVisibility(INVISIBLE);
+                    mPreviewPopup.dismiss();
                     break;
                 case MSG_REPEAT_KEY: {
                     final PointerTracker tracker = (PointerTracker)msg.obj;
@@ -460,6 +460,8 @@
             }
         }
 
+        final Resources res = getResources();
+
         mPreviewPopup = new PopupWindow(context);
         if (previewLayout != 0) {
             mPreviewText = (TextView) inflate.inflate(previewLayout, null);
@@ -470,10 +472,14 @@
             mShowPreview = false;
         }
         mPreviewPopup.setTouchable(false);
-        mMiniKeyboardParent = this;
+        mPreviewPopup.setAnimationStyle(R.style.KeyPreviewAnimation);
+        mDelayBeforePreview = res.getInteger(R.integer.config_delay_before_preview);
+        mDelayAfterPreview = res.getInteger(R.integer.config_delay_after_preview);
 
+        mMiniKeyboardParent = this;
         mMiniKeyboardPopup = new PopupWindow(context);
         mMiniKeyboardPopup.setBackgroundDrawable(null);
+        mMiniKeyboardPopup.setAnimationStyle(R.style.MiniKeyboardAnimation);
 
         mPaint = new Paint();
         mPaint.setAntiAlias(true);
@@ -485,7 +491,6 @@
         mMiniKeyboardCache = new HashMap<Key,View>();
         mKeyBackground.getPadding(mPadding);
 
-        final Resources res = getResources();
         mSwipeThreshold = (int) (500 * res.getDisplayMetrics().density);
         // TODO: Refer frameworks/base/core/res/res/values/config.xml
         mDisambiguateSwipe = res.getBoolean(R.bool.config_swipeDisambiguation);
@@ -657,9 +662,7 @@
     public void setPopupOffset(int x, int y) {
         mPopupPreviewOffsetX = x;
         mPopupPreviewOffsetY = y;
-        if (mPreviewPopup.isShowing()) {
-            mPreviewPopup.dismiss();
-        }
+        mPreviewPopup.dismiss();
     }
 
     /**
@@ -895,9 +898,9 @@
                         || (hidePreviewOrShowSpaceKeyPreview && isLanguageSwitchEnabled))) {
             if (keyIndex == NOT_A_KEY) {
                 mHandler.cancelPopupPreview();
-                mHandler.dismissPreview(DELAY_AFTER_PREVIEW);
+                mHandler.dismissPreview(mDelayAfterPreview);
             } else if (tracker != null) {
-                mHandler.popupPreview(DELAY_BEFORE_PREVIEW, keyIndex, tracker);
+                mHandler.popupPreview(mDelayBeforePreview, keyIndex, tracker);
             }
         }
     }
@@ -1375,9 +1378,7 @@
     }
 
     public void closing() {
-        if (mPreviewPopup.isShowing()) {
-            mPreviewPopup.dismiss();
-        }
+        mPreviewPopup.dismiss();
         mHandler.cancelAllMessages();
 
         dismissPopupKeyboard();
diff --git a/java/src/com/android/inputmethod/latin/UserDictionary.java b/java/src/com/android/inputmethod/latin/UserDictionary.java
index 3315cf6..49b95e9 100644
--- a/java/src/com/android/inputmethod/latin/UserDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserDictionary.java
@@ -89,13 +89,19 @@
         super.addWord(word, frequency);
 
         // Update the user dictionary provider
-        ContentValues values = new ContentValues(5);
+        final ContentValues values = new ContentValues(5);
         values.put(Words.WORD, word);
         values.put(Words.FREQUENCY, frequency);
         values.put(Words.LOCALE, mLocale);
         values.put(Words.APP_ID, 0);
 
-        getContext().getContentResolver().insert(Words.CONTENT_URI, values);
+        final ContentResolver contentResolver = getContext().getContentResolver();
+        new Thread("addWord") {
+            public void run() {
+                contentResolver.insert(Words.CONTENT_URI, values);
+            }
+        }.start();
+
         // In case the above does a synchronous callback of the change observer
         setRequiresReload(false);
     }