Home | History | Annotate | Download | only in utils
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.inputmethod.latin.utils;
     18 
     19 import android.inputmethodservice.InputMethodService;
     20 
     21 import com.android.inputmethod.annotations.UsedForTesting;
     22 import com.android.inputmethod.latin.LatinImeLogger;
     23 import com.android.inputmethod.latin.settings.Settings;
     24 
     25 public final class UserLogRingCharBuffer {
     26     public /* for test */ static final int BUFSIZE = 20;
     27     public /* for test */ int mLength = 0;
     28 
     29     private static UserLogRingCharBuffer sUserLogRingCharBuffer = new UserLogRingCharBuffer();
     30     private static final char PLACEHOLDER_DELIMITER_CHAR = '\uFFFC';
     31     private static final int INVALID_COORDINATE = -2;
     32     private boolean mEnabled = false;
     33     private int mEnd = 0;
     34     private char[] mCharBuf = new char[BUFSIZE];
     35     private int[] mXBuf = new int[BUFSIZE];
     36     private int[] mYBuf = new int[BUFSIZE];
     37 
     38     private UserLogRingCharBuffer() {
     39         // Intentional empty constructor for singleton.
     40     }
     41 
     42     @UsedForTesting
     43     public static UserLogRingCharBuffer getInstance() {
     44         return sUserLogRingCharBuffer;
     45     }
     46 
     47     public static UserLogRingCharBuffer init(final InputMethodService context,
     48             final boolean enabled, final boolean usabilityStudy) {
     49         if (!(enabled || usabilityStudy)) {
     50             return null;
     51         }
     52         sUserLogRingCharBuffer.mEnabled = true;
     53         UsabilityStudyLogUtils.getInstance().init(context);
     54         return sUserLogRingCharBuffer;
     55     }
     56 
     57     private static int normalize(final int in) {
     58         int ret = in % BUFSIZE;
     59         return ret < 0 ? ret + BUFSIZE : ret;
     60     }
     61 
     62     // TODO: accept code points
     63     @UsedForTesting
     64     public void push(final char c, final int x, final int y) {
     65         if (!mEnabled) {
     66             return;
     67         }
     68         if (LatinImeLogger.sUsabilityStudy) {
     69             UsabilityStudyLogUtils.getInstance().writeChar(c, x, y);
     70         }
     71         mCharBuf[mEnd] = c;
     72         mXBuf[mEnd] = x;
     73         mYBuf[mEnd] = y;
     74         mEnd = normalize(mEnd + 1);
     75         if (mLength < BUFSIZE) {
     76             ++mLength;
     77         }
     78     }
     79 
     80     public char pop() {
     81         if (mLength < 1) {
     82             return PLACEHOLDER_DELIMITER_CHAR;
     83         }
     84         mEnd = normalize(mEnd - 1);
     85         --mLength;
     86         return mCharBuf[mEnd];
     87     }
     88 
     89     public char getBackwardNthChar(final int n) {
     90         if (mLength <= n || n < 0) {
     91             return PLACEHOLDER_DELIMITER_CHAR;
     92         }
     93         return mCharBuf[normalize(mEnd - n - 1)];
     94     }
     95 
     96     public int getPreviousX(final char c, final int back) {
     97         final int index = normalize(mEnd - 2 - back);
     98         if (mLength <= back
     99                 || Character.toLowerCase(c) != Character.toLowerCase(mCharBuf[index])) {
    100             return INVALID_COORDINATE;
    101         }
    102         return mXBuf[index];
    103     }
    104 
    105     public int getPreviousY(final char c, final int back) {
    106         int index = normalize(mEnd - 2 - back);
    107         if (mLength <= back
    108                 || Character.toLowerCase(c) != Character.toLowerCase(mCharBuf[index])) {
    109             return INVALID_COORDINATE;
    110         }
    111         return mYBuf[index];
    112     }
    113 
    114     public String getLastWord(final int ignoreCharCount) {
    115         final StringBuilder sb = new StringBuilder();
    116         int i = ignoreCharCount;
    117         for (; i < mLength; ++i) {
    118             final char c = mCharBuf[normalize(mEnd - 1 - i)];
    119             if (!Settings.getInstance().isWordSeparator(c)) {
    120                 break;
    121             }
    122         }
    123         for (; i < mLength; ++i) {
    124             char c = mCharBuf[normalize(mEnd - 1 - i)];
    125             if (!Settings.getInstance().isWordSeparator(c)) {
    126                 sb.append(c);
    127             } else {
    128                 break;
    129             }
    130         }
    131         return sb.reverse().toString();
    132     }
    133 
    134     public void reset() {
    135         mLength = 0;
    136     }
    137 }
    138