19419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa/* 29419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa * Copyright (C) 2013 The Android Open Source Project 39419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa * 49419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa * Licensed under the Apache License, Version 2.0 (the "License"); 59419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa * you may not use this file except in compliance with the License. 69419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa * You may obtain a copy of the License at 79419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa * 89419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa * http://www.apache.org/licenses/LICENSE-2.0 99419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa * 109419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa * Unless required by applicable law or agreed to in writing, software 119419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa * distributed under the License is distributed on an "AS IS" BASIS, 129419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa * See the License for the specific language governing permissions and 149419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa * limitations under the License. 159419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa */ 169419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa 179419e02fd98e044136bf8888ad9781900ba42469Ken Wakasapackage com.android.inputmethod.latin.utils; 189419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa 199419e02fd98e044136bf8888ad9781900ba42469Ken Wakasaimport android.inputmethodservice.InputMethodService; 209419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa 219419e02fd98e044136bf8888ad9781900ba42469Ken Wakasaimport com.android.inputmethod.annotations.UsedForTesting; 22cfcf6660fc369fefd4028451334a9c2eda9bc4e5Ken Wakasaimport com.android.inputmethod.latin.LatinImeLogger; 23a7d2fc6befa1b16883200a653fc01deb4d94944dKen Wakasaimport com.android.inputmethod.latin.settings.Settings; 249419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa 259419e02fd98e044136bf8888ad9781900ba42469Ken Wakasapublic final class UserLogRingCharBuffer { 269419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa public /* for test */ static final int BUFSIZE = 20; 279419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa public /* for test */ int mLength = 0; 289419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa 299419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa private static UserLogRingCharBuffer sUserLogRingCharBuffer = new UserLogRingCharBuffer(); 309419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa private static final char PLACEHOLDER_DELIMITER_CHAR = '\uFFFC'; 319419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa private static final int INVALID_COORDINATE = -2; 329419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa private boolean mEnabled = false; 339419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa private int mEnd = 0; 349419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa private char[] mCharBuf = new char[BUFSIZE]; 359419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa private int[] mXBuf = new int[BUFSIZE]; 369419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa private int[] mYBuf = new int[BUFSIZE]; 379419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa 389419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa private UserLogRingCharBuffer() { 399419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa // Intentional empty constructor for singleton. 409419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa } 419419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa 429419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa @UsedForTesting 439419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa public static UserLogRingCharBuffer getInstance() { 449419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa return sUserLogRingCharBuffer; 459419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa } 469419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa 479419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa public static UserLogRingCharBuffer init(final InputMethodService context, 489419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa final boolean enabled, final boolean usabilityStudy) { 499419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa if (!(enabled || usabilityStudy)) { 509419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa return null; 519419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa } 529419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa sUserLogRingCharBuffer.mEnabled = true; 539419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa UsabilityStudyLogUtils.getInstance().init(context); 549419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa return sUserLogRingCharBuffer; 559419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa } 569419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa 579419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa private static int normalize(final int in) { 589419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa int ret = in % BUFSIZE; 599419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa return ret < 0 ? ret + BUFSIZE : ret; 609419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa } 619419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa 629419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa // TODO: accept code points 639419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa @UsedForTesting 649419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa public void push(final char c, final int x, final int y) { 659419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa if (!mEnabled) { 669419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa return; 679419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa } 68cfcf6660fc369fefd4028451334a9c2eda9bc4e5Ken Wakasa if (LatinImeLogger.sUsabilityStudy) { 69cfcf6660fc369fefd4028451334a9c2eda9bc4e5Ken Wakasa UsabilityStudyLogUtils.getInstance().writeChar(c, x, y); 70cfcf6660fc369fefd4028451334a9c2eda9bc4e5Ken Wakasa } 719419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa mCharBuf[mEnd] = c; 729419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa mXBuf[mEnd] = x; 739419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa mYBuf[mEnd] = y; 749419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa mEnd = normalize(mEnd + 1); 759419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa if (mLength < BUFSIZE) { 769419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa ++mLength; 779419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa } 789419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa } 799419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa 809419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa public char pop() { 819419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa if (mLength < 1) { 829419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa return PLACEHOLDER_DELIMITER_CHAR; 839419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa } 849419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa mEnd = normalize(mEnd - 1); 859419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa --mLength; 869419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa return mCharBuf[mEnd]; 879419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa } 889419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa 899419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa public char getBackwardNthChar(final int n) { 909419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa if (mLength <= n || n < 0) { 919419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa return PLACEHOLDER_DELIMITER_CHAR; 929419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa } 939419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa return mCharBuf[normalize(mEnd - n - 1)]; 949419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa } 959419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa 969419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa public int getPreviousX(final char c, final int back) { 979419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa final int index = normalize(mEnd - 2 - back); 989419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa if (mLength <= back 999419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa || Character.toLowerCase(c) != Character.toLowerCase(mCharBuf[index])) { 1009419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa return INVALID_COORDINATE; 1019419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa } 1029419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa return mXBuf[index]; 1039419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa } 1049419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa 1059419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa public int getPreviousY(final char c, final int back) { 1069419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa int index = normalize(mEnd - 2 - back); 1079419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa if (mLength <= back 1089419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa || Character.toLowerCase(c) != Character.toLowerCase(mCharBuf[index])) { 1099419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa return INVALID_COORDINATE; 1109419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa } 1119419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa return mYBuf[index]; 1129419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa } 1139419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa 1149419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa public String getLastWord(final int ignoreCharCount) { 1159419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa final StringBuilder sb = new StringBuilder(); 1169419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa int i = ignoreCharCount; 1179419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa for (; i < mLength; ++i) { 1189419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa final char c = mCharBuf[normalize(mEnd - 1 - i)]; 1199419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa if (!Settings.getInstance().isWordSeparator(c)) { 1209419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa break; 1219419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa } 1229419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa } 1239419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa for (; i < mLength; ++i) { 1249419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa char c = mCharBuf[normalize(mEnd - 1 - i)]; 1259419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa if (!Settings.getInstance().isWordSeparator(c)) { 1269419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa sb.append(c); 1279419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa } else { 1289419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa break; 1299419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa } 1309419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa } 1319419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa return sb.reverse().toString(); 1329419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa } 1339419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa 1349419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa public void reset() { 1359419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa mLength = 0; 1369419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa } 1379419e02fd98e044136bf8888ad9781900ba42469Ken Wakasa} 138