Move RingCharBuffer as a singleton in Util

Change-Id: I08d09555a99a64038374e62019777d331c48319b
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) {