2009-03-13 22:11:42 +00:00
|
|
|
/*
|
2010-03-26 22:07:10 +00:00
|
|
|
* Copyright (C) 2008 The Android Open Source Project
|
2009-03-13 22:11:42 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package com.android.inputmethod.latin;
|
|
|
|
|
|
|
|
import android.content.Context;
|
|
|
|
import android.text.format.DateFormat;
|
|
|
|
import android.util.Log;
|
|
|
|
|
|
|
|
import android.inputmethodservice.Keyboard.Key;
|
|
|
|
|
|
|
|
import java.io.FileOutputStream;
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.util.Calendar;
|
|
|
|
|
|
|
|
public class TextEntryState {
|
|
|
|
|
|
|
|
private static boolean LOGGING = false;
|
|
|
|
|
|
|
|
private static int sBackspaceCount = 0;
|
|
|
|
|
|
|
|
private static int sAutoSuggestCount = 0;
|
|
|
|
|
|
|
|
private static int sAutoSuggestUndoneCount = 0;
|
|
|
|
|
|
|
|
private static int sManualSuggestCount = 0;
|
|
|
|
|
|
|
|
private static int sWordNotInDictionaryCount = 0;
|
|
|
|
|
|
|
|
private static int sSessionCount = 0;
|
|
|
|
|
|
|
|
private static int sTypedChars;
|
2010-07-23 09:56:42 +00:00
|
|
|
|
2009-03-13 22:11:42 +00:00
|
|
|
private static int sActualChars;
|
2010-07-23 09:56:42 +00:00
|
|
|
|
2009-03-13 22:11:42 +00:00
|
|
|
public static final int STATE_UNKNOWN = 0;
|
|
|
|
public static final int STATE_START = 1;
|
|
|
|
public static final int STATE_IN_WORD = 2;
|
|
|
|
public static final int STATE_ACCEPTED_DEFAULT = 3;
|
|
|
|
public static final int STATE_PICKED_SUGGESTION = 4;
|
|
|
|
public static final int STATE_PUNCTUATION_AFTER_WORD = 5;
|
|
|
|
public static final int STATE_PUNCTUATION_AFTER_ACCEPTED = 6;
|
|
|
|
public static final int STATE_SPACE_AFTER_ACCEPTED = 7;
|
|
|
|
public static final int STATE_SPACE_AFTER_PICKED = 8;
|
|
|
|
public static final int STATE_UNDO_COMMIT = 9;
|
2010-02-27 15:53:56 +00:00
|
|
|
public static final int STATE_CORRECTING = 10;
|
|
|
|
public static final int STATE_PICKED_CORRECTION = 11;
|
|
|
|
|
2009-03-13 22:11:42 +00:00
|
|
|
private static int sState = STATE_UNKNOWN;
|
2010-02-27 15:53:56 +00:00
|
|
|
|
2009-03-13 22:11:42 +00:00
|
|
|
private static FileOutputStream sKeyLocationFile;
|
|
|
|
private static FileOutputStream sUserActionFile;
|
|
|
|
|
|
|
|
public static void newSession(Context context) {
|
|
|
|
sSessionCount++;
|
|
|
|
sAutoSuggestCount = 0;
|
|
|
|
sBackspaceCount = 0;
|
|
|
|
sAutoSuggestUndoneCount = 0;
|
|
|
|
sManualSuggestCount = 0;
|
|
|
|
sWordNotInDictionaryCount = 0;
|
|
|
|
sTypedChars = 0;
|
|
|
|
sActualChars = 0;
|
|
|
|
sState = STATE_START;
|
|
|
|
|
|
|
|
if (LOGGING) {
|
|
|
|
try {
|
|
|
|
sKeyLocationFile = context.openFileOutput("key.txt", Context.MODE_APPEND);
|
|
|
|
sUserActionFile = context.openFileOutput("action.txt", Context.MODE_APPEND);
|
|
|
|
} catch (IOException ioe) {
|
|
|
|
Log.e("TextEntryState", "Couldn't open file for output: " + ioe);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void endSession() {
|
|
|
|
if (sKeyLocationFile == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
sKeyLocationFile.close();
|
|
|
|
// Write to log file
|
|
|
|
// Write timestamp, settings,
|
|
|
|
String out = DateFormat.format("MM:dd hh:mm:ss", Calendar.getInstance().getTime())
|
|
|
|
.toString()
|
|
|
|
+ " BS: " + sBackspaceCount
|
|
|
|
+ " auto: " + sAutoSuggestCount
|
|
|
|
+ " manual: " + sManualSuggestCount
|
|
|
|
+ " typed: " + sWordNotInDictionaryCount
|
|
|
|
+ " undone: " + sAutoSuggestUndoneCount
|
|
|
|
+ " saved: " + ((float) (sActualChars - sTypedChars) / sActualChars)
|
|
|
|
+ "\n";
|
|
|
|
sUserActionFile.write(out.getBytes());
|
|
|
|
sUserActionFile.close();
|
|
|
|
sKeyLocationFile = null;
|
|
|
|
sUserActionFile = null;
|
|
|
|
} catch (IOException ioe) {
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void acceptedDefault(CharSequence typedWord, CharSequence actualWord) {
|
2010-01-30 04:09:49 +00:00
|
|
|
if (typedWord == null) return;
|
2009-03-13 22:11:42 +00:00
|
|
|
if (!typedWord.equals(actualWord)) {
|
|
|
|
sAutoSuggestCount++;
|
|
|
|
}
|
|
|
|
sTypedChars += typedWord.length();
|
|
|
|
sActualChars += actualWord.length();
|
|
|
|
sState = STATE_ACCEPTED_DEFAULT;
|
2010-05-07 17:03:29 +00:00
|
|
|
LatinImeLogger.logOnAutoSuggestion(typedWord.toString(), actualWord.toString());
|
2009-03-13 22:11:42 +00:00
|
|
|
}
|
2010-05-31 08:47:33 +00:00
|
|
|
|
|
|
|
// STATE_ACCEPTED_DEFAULT will be changed to other sub-states
|
|
|
|
// (see "case STATE_ACCEPTED_DEFAULT" in typedCharacter() below),
|
|
|
|
// and should be restored back to STATE_ACCEPTED_DEFAULT after processing for each sub-state.
|
2010-07-01 21:36:02 +00:00
|
|
|
public static void backToAcceptedDefault(CharSequence typedWord) {
|
|
|
|
if (typedWord == null) return;
|
2010-05-31 08:47:33 +00:00
|
|
|
switch (sState) {
|
|
|
|
case STATE_SPACE_AFTER_ACCEPTED:
|
|
|
|
case STATE_PUNCTUATION_AFTER_ACCEPTED:
|
|
|
|
case STATE_IN_WORD:
|
|
|
|
sState = STATE_ACCEPTED_DEFAULT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-03-13 22:11:42 +00:00
|
|
|
public static void acceptedTyped(CharSequence typedWord) {
|
|
|
|
sWordNotInDictionaryCount++;
|
|
|
|
sState = STATE_PICKED_SUGGESTION;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void acceptedSuggestion(CharSequence typedWord, CharSequence actualWord) {
|
|
|
|
sManualSuggestCount++;
|
2010-02-27 15:53:56 +00:00
|
|
|
int oldState = sState;
|
2009-03-13 22:11:42 +00:00
|
|
|
if (typedWord.equals(actualWord)) {
|
|
|
|
acceptedTyped(typedWord);
|
|
|
|
}
|
2010-02-27 15:53:56 +00:00
|
|
|
sState = oldState == STATE_CORRECTING ? STATE_PICKED_CORRECTION : STATE_PICKED_SUGGESTION;
|
2009-03-13 22:11:42 +00:00
|
|
|
}
|
2010-02-27 15:53:56 +00:00
|
|
|
|
|
|
|
public static void selectedForCorrection() {
|
|
|
|
sState = STATE_CORRECTING;
|
|
|
|
}
|
|
|
|
|
2009-03-13 22:11:42 +00:00
|
|
|
public static void typedCharacter(char c, boolean isSeparator) {
|
|
|
|
boolean isSpace = c == ' ';
|
|
|
|
switch (sState) {
|
|
|
|
case STATE_IN_WORD:
|
|
|
|
if (isSpace || isSeparator) {
|
|
|
|
sState = STATE_START;
|
|
|
|
} else {
|
|
|
|
// State hasn't changed.
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case STATE_ACCEPTED_DEFAULT:
|
|
|
|
case STATE_SPACE_AFTER_PICKED:
|
|
|
|
if (isSpace) {
|
|
|
|
sState = STATE_SPACE_AFTER_ACCEPTED;
|
|
|
|
} else if (isSeparator) {
|
|
|
|
sState = STATE_PUNCTUATION_AFTER_ACCEPTED;
|
|
|
|
} else {
|
|
|
|
sState = STATE_IN_WORD;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case STATE_PICKED_SUGGESTION:
|
2010-02-27 15:53:56 +00:00
|
|
|
case STATE_PICKED_CORRECTION:
|
2009-03-13 22:11:42 +00:00
|
|
|
if (isSpace) {
|
|
|
|
sState = STATE_SPACE_AFTER_PICKED;
|
|
|
|
} else if (isSeparator) {
|
|
|
|
// Swap
|
|
|
|
sState = STATE_PUNCTUATION_AFTER_ACCEPTED;
|
|
|
|
} else {
|
|
|
|
sState = STATE_IN_WORD;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case STATE_START:
|
|
|
|
case STATE_UNKNOWN:
|
|
|
|
case STATE_SPACE_AFTER_ACCEPTED:
|
|
|
|
case STATE_PUNCTUATION_AFTER_ACCEPTED:
|
|
|
|
case STATE_PUNCTUATION_AFTER_WORD:
|
|
|
|
if (!isSpace && !isSeparator) {
|
|
|
|
sState = STATE_IN_WORD;
|
|
|
|
} else {
|
|
|
|
sState = STATE_START;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case STATE_UNDO_COMMIT:
|
|
|
|
if (isSpace || isSeparator) {
|
|
|
|
sState = STATE_ACCEPTED_DEFAULT;
|
|
|
|
} else {
|
|
|
|
sState = STATE_IN_WORD;
|
|
|
|
}
|
2010-02-27 15:53:56 +00:00
|
|
|
break;
|
|
|
|
case STATE_CORRECTING:
|
|
|
|
sState = STATE_START;
|
|
|
|
break;
|
2009-03-13 22:11:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void backspace() {
|
|
|
|
if (sState == STATE_ACCEPTED_DEFAULT) {
|
|
|
|
sState = STATE_UNDO_COMMIT;
|
|
|
|
sAutoSuggestUndoneCount++;
|
2010-05-07 17:03:29 +00:00
|
|
|
LatinImeLogger.logOnAutoSuggestionCanceled();
|
2009-03-13 22:11:42 +00:00
|
|
|
} else if (sState == STATE_UNDO_COMMIT) {
|
|
|
|
sState = STATE_IN_WORD;
|
|
|
|
}
|
|
|
|
sBackspaceCount++;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void reset() {
|
|
|
|
sState = STATE_START;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static int getState() {
|
|
|
|
return sState;
|
|
|
|
}
|
2010-02-27 15:53:56 +00:00
|
|
|
|
|
|
|
public static boolean isCorrecting() {
|
|
|
|
return sState == STATE_CORRECTING || sState == STATE_PICKED_CORRECTION;
|
|
|
|
}
|
|
|
|
|
2009-03-13 22:11:42 +00:00
|
|
|
public static void keyPressedAt(Key key, int x, int y) {
|
|
|
|
if (LOGGING && sKeyLocationFile != null && key.codes[0] >= 32) {
|
|
|
|
String out =
|
|
|
|
"KEY: " + (char) key.codes[0]
|
|
|
|
+ " X: " + x
|
|
|
|
+ " Y: " + y
|
|
|
|
+ " MX: " + (key.x + key.width / 2)
|
|
|
|
+ " MY: " + (key.y + key.height / 2)
|
|
|
|
+ "\n";
|
|
|
|
try {
|
|
|
|
sKeyLocationFile.write(out.getBytes());
|
|
|
|
} catch (IOException ioe) {
|
|
|
|
// TODO: May run out of space
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|