blob: cbcc074e30465cc3c06aa169c6d16531a3bb4769 [file] [log] [blame]
/*
* Copyright (C) 2008-2012 OMRON SOFTWARE Co., Ltd.
*
* 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 jp.co.omronsoft.openwnn;
import jp.co.omronsoft.openwnn.EN.OpenWnnEngineEN;
import jp.co.omronsoft.openwnn.JAJP.*;
import android.content.SharedPreferences;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.style.BackgroundColorSpan;
import android.text.style.CharacterStyle;
import android.text.style.ForegroundColorSpan;
import android.text.style.UnderlineSpan;
import android.util.Log;
import android.view.KeyEvent;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.MotionEvent;
import android.view.View;
import android.view.KeyCharacterMap;
import android.text.method.MetaKeyKeyListener;
import jp.co.omronsoft.openwnn.BaseInputView;
import jp.co.omronsoft.openwnn.OpenWnnControlPanelJAJP;
import java.util.HashMap;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
/**
* The OpenWnn Japanese IME class
*
* @author Copyright (C) 2009-2011 OMRON SOFTWARE CO., LTD. All Rights Reserved.
*/
public class OpenWnnJAJP extends OpenWnn {
/**
* Mode of the convert engine (Full-width KATAKANA).
* Use with {@code OpenWnn.CHANGE_MODE} event.
*/
public static final int ENGINE_MODE_FULL_KATAKANA = 101;
/**
* Mode of the convert engine (Half-width KATAKANA).
* Use with {@code OpenWnn.CHANGE_MODE} event.
*/
public static final int ENGINE_MODE_HALF_KATAKANA = 102;
/**
* Mode of the convert engine (EISU-KANA conversion).
* Use with {@code OpenWnn.CHANGE_MODE} event.
*/
public static final int ENGINE_MODE_EISU_KANA = 103;
/**
* Mode of the convert engine (Symbol list).
* Use with {@code OpenWnn.CHANGE_MODE} event.
*/
public static final int ENGINE_MODE_SYMBOL_NONE = 1040;
public static final int ENGINE_MODE_SYMBOL = 1041;
public static final int ENGINE_MODE_SYMBOL_KAO_MOJI = 1042;
/**
* Mode of the convert engine (Keyboard type is QWERTY).
* Use with {@code OpenWnn.CHANGE_MODE} event to change ambiguous searching pattern.
*/
public static final int ENGINE_MODE_OPT_TYPE_QWERTY = 105;
/**
* Mode of the convert engine (Keyboard type is 12-keys).
* Use with {@code OpenWnn.CHANGE_MODE} event to change ambiguous searching pattern.
*/
public static final int ENGINE_MODE_OPT_TYPE_12KEY = 106;
/** Never move cursor in to the composing text (adapting to IMF's specification change) */
private static final boolean FIX_CURSOR_TEXT_END = true;
/** Highlight color style for the converted clause */
private static final CharacterStyle SPAN_CONVERT_BGCOLOR_HL = new BackgroundColorSpan(0xFF8888FF);
/** Highlight color style for the selected string */
private static final CharacterStyle SPAN_EXACT_BGCOLOR_HL = new BackgroundColorSpan(0xFF66CDAA);
/** Highlight color style for EISU-KANA conversion */
private static final CharacterStyle SPAN_EISUKANA_BGCOLOR_HL = new BackgroundColorSpan(0xFF9FB6CD);
/** Highlight color style for the composing text */
private static final CharacterStyle SPAN_REMAIN_BGCOLOR_HL = new BackgroundColorSpan(0xFFF0FFFF);
/** Highlight text color */
private static final CharacterStyle SPAN_TEXTCOLOR = new ForegroundColorSpan(0xFF000000);
/** Underline style for the composing text */
private static final CharacterStyle SPAN_UNDERLINE = new UnderlineSpan();
/** IME's status for {@code mStatus} input/no candidates). */
private static final int STATUS_INIT = 0x0000;
/** IME's status for {@code mStatus}(input characters). */
private static final int STATUS_INPUT = 0x0001;
/** IME's status for {@code mStatus}(input functional keys). */
private static final int STATUS_INPUT_EDIT = 0x0003;
/** IME's status for {@code mStatus}(all candidates are displayed). */
private static final int STATUS_CANDIDATE_FULL = 0x0010;
/** Alphabet-last pattern */
private static final Pattern ENGLISH_CHARACTER_LAST = Pattern.compile(".*[a-zA-Z]$");
/**
* Private area character code got by {@link KeyEvent#getUnicodeChar()}.
* (SHIFT+ALT+X G1 specific)
*/
private static final int PRIVATE_AREA_CODE = 61184;
/** Maximum length of input string */
private static final int LIMIT_INPUT_NUMBER = 30;
/** Bit flag for English auto commit mode (ON) */
private static final int AUTO_COMMIT_ENGLISH_ON = 0x0000;
/** Bit flag for English auto commit mode (OFF) */
private static final int AUTO_COMMIT_ENGLISH_OFF = 0x0001;
/** Bit flag for English auto commit mode (symbol list) */
private static final int AUTO_COMMIT_ENGLISH_SYMBOL = 0x0010;
/** Message for {@code mHandler} (execute prediction) */
private static final int MSG_PREDICTION = 0;
/** Message for {@code mHandler} (execute tutorial) */
private static final int MSG_START_TUTORIAL = 1;
/** Message for {@code mHandler} (close) */
private static final int MSG_CLOSE = 2;
/** Delay time(msec.) to start prediction after key input when the candidates view is not shown. */
private static final int PREDICTION_DELAY_MS_1ST = 200;
/** Delay time(msec.) to start prediction after key input when the candidates view is shown. */
private static final int PREDICTION_DELAY_MS_SHOWING_CANDIDATE = 200;
/** H/W 12Keyboard keycode replace table */
private static final HashMap<Integer, Integer> HW12KEYBOARD_KEYCODE_REPLACE_TABLE
= new HashMap<Integer, Integer>() {{
put(KeyEvent.KEYCODE_0, DefaultSoftKeyboard.KEYCODE_JP12_0);
put(KeyEvent.KEYCODE_1, DefaultSoftKeyboard.KEYCODE_JP12_1);
put(KeyEvent.KEYCODE_2, DefaultSoftKeyboard.KEYCODE_JP12_2);
put(KeyEvent.KEYCODE_3, DefaultSoftKeyboard.KEYCODE_JP12_3);
put(KeyEvent.KEYCODE_4, DefaultSoftKeyboard.KEYCODE_JP12_4);
put(KeyEvent.KEYCODE_5, DefaultSoftKeyboard.KEYCODE_JP12_5);
put(KeyEvent.KEYCODE_6, DefaultSoftKeyboard.KEYCODE_JP12_6);
put(KeyEvent.KEYCODE_7, DefaultSoftKeyboard.KEYCODE_JP12_7);
put(KeyEvent.KEYCODE_8, DefaultSoftKeyboard.KEYCODE_JP12_8);
put(KeyEvent.KEYCODE_9, DefaultSoftKeyboard.KEYCODE_JP12_9);
put(KeyEvent.KEYCODE_POUND, DefaultSoftKeyboard.KEYCODE_JP12_SHARP);
put(KeyEvent.KEYCODE_STAR, DefaultSoftKeyboard.KEYCODE_JP12_ASTER);
put(KeyEvent.KEYCODE_CALL, DefaultSoftKeyboard.KEYCODE_JP12_REVERSE);
}};
/** Convert engine's state */
private class EngineState {
/** Definition for {@code EngineState.*} (invalid) */
public static final int INVALID = -1;
/** Definition for {@code EngineState.dictionarySet} (Japanese) */
public static final int DICTIONARYSET_JP = 0;
/** Definition for {@code EngineState.dictionarySet} (English) */
public static final int DICTIONARYSET_EN = 1;
/** Definition for {@code EngineState.convertType} (prediction/no conversion) */
public static final int CONVERT_TYPE_NONE = 0;
/** Definition for {@code EngineState.convertType} (consecutive clause conversion) */
public static final int CONVERT_TYPE_RENBUN = 1;
/** Definition for {@code EngineState.convertType} (EISU-KANA conversion) */
public static final int CONVERT_TYPE_EISU_KANA = 2;
/** Definition for {@code EngineState.temporaryMode} (change back to the normal dictionary) */
public static final int TEMPORARY_DICTIONARY_MODE_NONE = 0;
/** Definition for {@code EngineState.temporaryMode} (change to the symbol dictionary) */
public static final int TEMPORARY_DICTIONARY_MODE_SYMBOL = 1;
/** Definition for {@code EngineState.temporaryMode} (change to the user dictionary) */
public static final int TEMPORARY_DICTIONARY_MODE_USER = 2;
/** Definition for {@code EngineState.preferenceDictionary} (no preference dictionary) */
public static final int PREFERENCE_DICTIONARY_NONE = 0;
/** Definition for {@code EngineState.preferenceDictionary} (person's name) */
public static final int PREFERENCE_DICTIONARY_PERSON_NAME = 1;
/** Definition for {@code EngineState.preferenceDictionary} (place name) */
public static final int PREFERENCE_DICTIONARY_POSTAL_ADDRESS = 2;
/** Definition for {@code EngineState.preferenceDictionary} (email/URI) */
public static final int PREFERENCE_DICTIONARY_EMAIL_ADDRESS_URI = 3;
/** Definition for {@code EngineState.keyboard} (undefined) */
public static final int KEYBOARD_UNDEF = 0;
/** Definition for {@code EngineState.keyboard} (QWERTY) */
public static final int KEYBOARD_QWERTY = 1;
/** Definition for {@code EngineState.keyboard} (12-keys) */
public static final int KEYBOARD_12KEY = 2;
/** Set of dictionaries */
public int dictionarySet = INVALID;
/** Type of conversion */
public int convertType = INVALID;
/** Temporary mode */
public int temporaryMode = INVALID;
/** Preference dictionary setting */
public int preferenceDictionary = INVALID;
/** keyboard */
public int keyboard = INVALID;
/**
* Returns whether current type of conversion is consecutive clause(RENBUNSETSU) conversion.
*
* @return {@code true} if current type of conversion is consecutive clause conversion.
*/
public boolean isRenbun() {
return convertType == CONVERT_TYPE_RENBUN;
}
/**
* Returns whether current type of conversion is EISU-KANA conversion.
*
* @return {@code true} if current type of conversion is EISU-KANA conversion.
*/
public boolean isEisuKana() {
return convertType == CONVERT_TYPE_EISU_KANA;
}
/**
* Returns whether current type of conversion is no conversion.
*
* @return {@code true} if no conversion is executed currently.
*/
public boolean isConvertState() {
return convertType != CONVERT_TYPE_NONE;
}
/**
* Check whether or not the mode is "symbol list".
*
* @return {@code true} if the mode is "symbol list".
*/
public boolean isSymbolList() {
return temporaryMode == TEMPORARY_DICTIONARY_MODE_SYMBOL;
}
/**
* Check whether or not the current language is English.
*
* @return {@code true} if the current language is English.
*/
public boolean isEnglish() {
return dictionarySet == DICTIONARYSET_EN;
}
}
/** IME's status */
protected int mStatus = STATUS_INIT;
/** Whether exact match searching or not */
protected boolean mExactMatchMode = false;
/** Spannable string builder for displaying the composing text */
protected SpannableStringBuilder mDisplayText;
/** Instance of this service */
private static OpenWnnJAJP mSelf = null;
/** Backup for switching the converter */
private WnnEngine mConverterBack;
/** Backup for switching the pre-converter */
private LetterConverter mPreConverterBack;
/** OpenWnn conversion engine for Japanese */
private OpenWnnEngineJAJP mConverterJAJP;
/** OpenWnn conversion engine for English */
private OpenWnnEngineEN mConverterEN;
/** Conversion engine for listing symbols */
private SymbolList mConverterSymbolEngineBack;
/** Symbol lists to display when the symbol key is pressed */
private static final String[] SYMBOL_LISTS = {
SymbolList.SYMBOL_JAPANESE, SymbolList.SYMBOL_JAPANESE_FACE
};
/** Current symbol list */
private int mCurrentSymbol = -1;
/** Romaji-to-Kana converter (HIRAGANA) */
private Romkan mPreConverterHiragana;
/** Romaji-to-Kana converter (full-width KATAKANA) */
private RomkanFullKatakana mPreConverterFullKatakana;
/** Romaji-to-Kana converter (half-width KATAKANA) */
private RomkanHalfKatakana mPreConverterHalfKatakana;
/** Conversion Engine's state */
private EngineState mEngineState = new EngineState();
/** Whether learning function is active of not. */
private boolean mEnableLearning = true;
/** Whether prediction is active or not. */
private boolean mEnablePrediction = true;
/** Whether using the converter */
private boolean mEnableConverter = true;
/** Whether displaying the symbol list */
private boolean mEnableSymbolList = true;
/** Whether non ASCII code is enabled */
private boolean mEnableSymbolListNonHalf = true;
/** Enable mistyping spell correction or not */
private boolean mEnableSpellCorrection = true;
/** Auto commit state (in English mode) */
private int mDisableAutoCommitEnglishMask = AUTO_COMMIT_ENGLISH_ON;
/** Whether removing a space before a separator or not. (in English mode) */
private boolean mEnableAutoDeleteSpace = false;
/** Whether auto-spacing is enabled or not. */
private boolean mEnableAutoInsertSpace = true;
/** Whether dismissing the keyboard when the enter key is pressed */
private boolean mEnableAutoHideKeyboard = true;
/** Number of committed clauses on consecutive clause conversion */
private int mCommitCount = 0;
/** Target layer of the {@link ComposingText} */
private int mTargetLayer = 1;
/** Current orientation of the display */
private int mOrientation = Configuration.ORIENTATION_UNDEFINED;
/** Current normal dictionary set */
private int mPrevDictionarySet = OpenWnnEngineJAJP.DIC_LANG_INIT;
/** Regular expression pattern for English separators */
private Pattern mEnglishAutoCommitDelimiter = null;
/** Cursor position in the composing text */
private int mComposingStartCursor = 0;
/** Cursor position before committing text */
private int mCommitStartCursor = 0;
/** Previous committed text */
private StringBuffer mPrevCommitText = null;
/** Call count of {@code commitText} */
private int mPrevCommitCount = 0;
/** Shift lock status of the Hardware keyboard */
private int mHardShift;
/** SHIFT key state (pressing) */
private boolean mShiftPressing;
/** ALT lock status of the Hardware keyboard */
private int mHardAlt;
/** ALT key state (pressing) */
private boolean mAltPressing;
/** Shift lock toggle definition */
private static final int[] mShiftKeyToggle = {0, MetaKeyKeyListener.META_SHIFT_ON, MetaKeyKeyListener.META_CAP_LOCKED};
/** ALT lock toggle definition */
private static final int[] mAltKeyToggle = {0, MetaKeyKeyListener.META_ALT_ON, MetaKeyKeyListener.META_ALT_LOCKED};
/** Auto caps mode */
private boolean mAutoCaps = false;
/** List of words in the user dictionary */
private WnnWord[] mUserDictionaryWords = null;
/** Tutorial */
private TutorialJAJP mTutorial;
/** Whether tutorial mode or not */
private boolean mEnableTutorial;
/** Whether there is a continued predicted candidate */
private boolean mHasContinuedPrediction = false;
/** Whether text selection has started */
private boolean mHasStartedTextSelection = true;
/** Whether the H/W 12keyboard is active or not. */
private boolean mEnableHardware12Keyboard = false;
/** {@code Handler} for drawing candidates/displaying tutorial */
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_PREDICTION:
updatePrediction();
break;
case MSG_START_TUTORIAL:
if (mTutorial == null) {
if (isInputViewShown()) {
DefaultSoftKeyboardJAJP inputManager = ((DefaultSoftKeyboardJAJP) mInputViewManager);
View v = inputManager.getKeyboardView();
mTutorial = new TutorialJAJP(OpenWnnJAJP.this, v, inputManager);
mTutorial.start();
} else {
/* Try again soon if the view is not yet showing */
sendMessageDelayed(obtainMessage(MSG_START_TUTORIAL), 100);
}
}
break;
case MSG_CLOSE:
if (mConverterJAJP != null) mConverterJAJP.close();
if (mConverterEN != null) mConverterEN.close();
if (mConverterSymbolEngineBack != null) mConverterSymbolEngineBack.close();
break;
}
}
};
/** The candidate filter */
private CandidateFilter mFilter;
/**
* Constructor
*/
public OpenWnnJAJP() {
super();
mSelf = this;
mComposingText = new ComposingText();
mCandidatesViewManager = new TextCandidatesViewManager(-1);
mInputViewManager = new DefaultSoftKeyboardJAJP();
if (OpenWnn.getCurrentIme() != null) {
if (mConverter == null || mConverterJAJP == null) {
mConverter = mConverterJAJP = new OpenWnnEngineJAJP("/data/data/jp.co.omronsoft.openwnn/writableJAJP.dic");
}
if (mConverterEN == null) {
mConverterEN = new OpenWnnEngineEN("/data/data/jp.co.omronsoft.openwnn/writableEN.dic");
}
}
mPreConverter = mPreConverterHiragana = new Romkan();
mPreConverterFullKatakana = new RomkanFullKatakana();
mPreConverterHalfKatakana = new RomkanHalfKatakana();
mFilter = new CandidateFilter();
mDisplayText = new SpannableStringBuilder();
mAutoHideMode = false;
mPrevCommitText = new StringBuffer();
}
/**
* Constructor
*
* @param context The context
*/
public OpenWnnJAJP(Context context) {
this();
attachBaseContext(context);
}
/** @see jp.co.omronsoft.openwnn.OpenWnn#onCreate */
@Override public void onCreate() {
updateXLargeMode();
super.onCreate();
if (mConverter == null || mConverterJAJP == null) {
mConverter = mConverterJAJP = new OpenWnnEngineJAJP("/data/data/jp.co.omronsoft.openwnn/writableJAJP.dic");
}
if (mConverterEN == null) {
mConverterEN = new OpenWnnEngineEN("/data/data/jp.co.omronsoft.openwnn/writableEN.dic");
}
String delimiter = Pattern.quote(getResources().getString(R.string.en_word_separators));
mEnglishAutoCommitDelimiter = Pattern.compile(".*[" + delimiter + "]$");
if (mConverterSymbolEngineBack == null) {
mConverterSymbolEngineBack = new SymbolList(this, SymbolList.LANG_JA);
}
}
/** @see jp.co.omronsoft.openwnn.OpenWnn#onCreateInputView */
@Override public View onCreateInputView() {
int hiddenState = getResources().getConfiguration().hardKeyboardHidden;
boolean hidden = (hiddenState == Configuration.HARDKEYBOARDHIDDEN_YES);
boolean type12Key
= (getResources().getConfiguration().keyboard == Configuration.KEYBOARD_12KEY);
((DefaultSoftKeyboardJAJP) mInputViewManager).setHardKeyboardHidden(hidden);
((DefaultSoftKeyboard) mInputViewManager).setHardware12Keyboard(type12Key);
mTextCandidatesViewManager.setHardKeyboardHidden(hidden);
mEnableTutorial = hidden;
mEnableHardware12Keyboard = type12Key;
return super.onCreateInputView();
}
/** @see jp.co.omronsoft.openwnn.OpenWnn#onStartInputView */
@Override public void onStartInputView(EditorInfo attribute, boolean restarting) {
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
if (restarting) {
super.onStartInputView(attribute, restarting);
} else {
EngineState state = new EngineState();
state.temporaryMode = EngineState.TEMPORARY_DICTIONARY_MODE_NONE;
updateEngineState(state);
mPrevCommitCount = 0;
clearCommitInfo();
((DefaultSoftKeyboard) mInputViewManager).resetCurrentKeyboard();
super.onStartInputView(attribute, restarting);
if (OpenWnn.isXLarge()) {
mTextCandidatesViewManager.setPreferences(pref);
}
mCandidatesViewManager.clearCandidates();
mStatus = STATUS_INIT;
mExactMatchMode = false;
/* hardware keyboard support */
mHardShift = 0;
mHardAlt = 0;
updateMetaKeyStateDisplay();
}
/* initialize the engine's state */
fitInputType(pref, attribute);
if (OpenWnn.isXLarge()) {
mTextCandidates1LineViewManager.setAutoHide(true);
} else {
((TextCandidatesViewManager)mCandidatesViewManager).setAutoHide(true);
}
if (isEnableL2Converter()) {
breakSequence();
}
}
/** @see jp.co.omronsoft.openwnn.OpenWnn#hideWindow */
@Override public void hideWindow() {
mCandidatesViewManager.setCandidateMsgRemove();
BaseInputView baseInputView = ((BaseInputView)((DefaultSoftKeyboard) mInputViewManager).getCurrentView());
if (baseInputView != null) {
baseInputView.closeDialog();
}
mComposingText.clear();
mInputViewManager.onUpdateState(this);
clearCommitInfo();
mHandler.removeMessages(MSG_START_TUTORIAL);
mInputViewManager.closing();
if (mTutorial != null) {
mTutorial.close();
mTutorial = null;
}
if (OpenWnn.isXLarge()) {
mTextCandidates1LineViewManager.closeDialog();
} else {
mTextCandidatesViewManager.closeDialog();
}
super.hideWindow();
}
/** @see jp.co.omronsoft.openwnn.OpenWnn#onUpdateSelection */
@Override public void onUpdateSelection(int oldSelStart, int oldSelEnd, int newSelStart, int newSelEnd, int candidatesStart, int candidatesEnd) {
mComposingStartCursor = (candidatesStart < 0) ? newSelEnd : candidatesStart;
boolean prevSelection = mHasStartedTextSelection;
if (newSelStart != newSelEnd) {
clearCommitInfo();
mHasStartedTextSelection = true;
} else {
mHasStartedTextSelection = false;
}
if (mHasContinuedPrediction) {
mHasContinuedPrediction = false;
if (0 < mPrevCommitCount) {
mPrevCommitCount--;
}
return;
}
if (mEngineState.isSymbolList()) {
return;
}
boolean isNotComposing = ((candidatesStart < 0) && (candidatesEnd < 0));
if ((mComposingText.size(ComposingText.LAYER1) != 0)
&& !isNotComposing) {
updateViewStatus(mTargetLayer, false, true);
} else {
if (0 < mPrevCommitCount) {
mPrevCommitCount--;
} else {
int commitEnd = mCommitStartCursor + mPrevCommitText.length();
if ((((newSelEnd < oldSelEnd) || (commitEnd < newSelEnd)) && clearCommitInfo())
|| isNotComposing) {
if (isEnableL2Converter()) {
breakSequence();
}
if (mInputConnection != null) {
if (isNotComposing && (mComposingText.size(ComposingText.LAYER1) != 0)) {
mInputConnection.finishComposingText();
}
}
if ((prevSelection != mHasStartedTextSelection) || !mHasStartedTextSelection) {
initializeScreen();
}
}
}
}
}
/** @see jp.co.omronsoft.openwnn.OpenWnn#onConfigurationChanged */
@Override public void onConfigurationChanged(Configuration newConfig) {
try {
super.onConfigurationChanged(newConfig);
if (mInputConnection != null) {
if (super.isInputViewShown()) {
updateViewStatus(mTargetLayer, true, true);
}
/* display orientation */
if (mOrientation != newConfig.orientation) {
mOrientation = newConfig.orientation;
commitConvertingText();
initializeScreen();
}
/* Hardware keyboard */
int hiddenState = newConfig.hardKeyboardHidden;
boolean hidden = (hiddenState == Configuration.HARDKEYBOARDHIDDEN_YES);
boolean type12Key = (newConfig.keyboard == Configuration.KEYBOARD_12KEY);
((DefaultSoftKeyboardJAJP) mInputViewManager).setHardKeyboardHidden(hidden);
((DefaultSoftKeyboard) mInputViewManager).setHardware12Keyboard(type12Key);
mTextCandidatesViewManager.setHardKeyboardHidden(hidden);
mEnableTutorial = hidden;
mEnableHardware12Keyboard = type12Key;
}
} catch (Exception ex) {
/* do nothing if an error occurs. */
}
}
/** @see jp.co.omronsoft.openwnn.OpenWnn#onEvent */
@Override synchronized public boolean onEvent(OpenWnnEvent ev) {
EngineState state;
/* handling events which are valid when InputConnection is not active. */
switch (ev.code) {
case OpenWnnEvent.KEYUP:
onKeyUpEvent(ev.keyEvent);
return true;
case OpenWnnEvent.KEYLONGPRESS:
return onKeyLongPressEvent(ev.keyEvent);
case OpenWnnEvent.INITIALIZE_LEARNING_DICTIONARY:
mConverterEN.initializeDictionary(WnnEngine.DICTIONARY_TYPE_LEARN);
mConverterJAJP.initializeDictionary(WnnEngine.DICTIONARY_TYPE_LEARN);
return true;
case OpenWnnEvent.INITIALIZE_USER_DICTIONARY:
return mConverterJAJP.initializeDictionary( WnnEngine.DICTIONARY_TYPE_USER );
case OpenWnnEvent.LIST_WORDS_IN_USER_DICTIONARY:
mUserDictionaryWords = mConverterJAJP.getUserDictionaryWords( );
return true;
case OpenWnnEvent.GET_WORD:
if (mUserDictionaryWords != null) {
ev.word = mUserDictionaryWords[0];
for (int i = 0 ; i < mUserDictionaryWords.length - 1 ; i++) {
mUserDictionaryWords[i] = mUserDictionaryWords[i + 1];
}
mUserDictionaryWords[mUserDictionaryWords.length - 1] = null;
if (mUserDictionaryWords[0] == null) {
mUserDictionaryWords = null;
}
return true;
}
break;
case OpenWnnEvent.ADD_WORD:
mConverterJAJP.addWord(ev.word);
return true;
case OpenWnnEvent.DELETE_WORD:
mConverterJAJP.deleteWord(ev.word);
return true;
case OpenWnnEvent.CHANGE_MODE:
changeEngineMode(ev.mode);
if (!(ev.mode == ENGINE_MODE_SYMBOL || ev.mode == ENGINE_MODE_EISU_KANA)) {
initializeScreen();
}
return true;
case OpenWnnEvent.UPDATE_CANDIDATE:
if (mEngineState.isRenbun()) {
mComposingText.setCursor(ComposingText.LAYER1,
mComposingText.toString(ComposingText.LAYER1).length());
mExactMatchMode = false;
updateViewStatusForPrediction(true, true);
} else {
updateViewStatus(mTargetLayer, true, true);
}
return true;
case OpenWnnEvent.CHANGE_INPUT_VIEW:
setInputView(onCreateInputView());
return true;
case OpenWnnEvent.CANDIDATE_VIEW_TOUCH:
boolean ret;
ret = ((TextCandidatesViewManager)mCandidatesViewManager).onTouchSync();
return ret;
case OpenWnnEvent.TOUCH_OTHER_KEY:
mStatus |= STATUS_INPUT_EDIT;
return true;
case OpenWnnEvent.CANDIDATE_VIEW_SCROLL_UP:
if (mCandidatesViewManager instanceof TextCandidatesViewManager) {
((TextCandidatesViewManager) mCandidatesViewManager).setScrollUp();
}
return true;
case OpenWnnEvent.CANDIDATE_VIEW_SCROLL_DOWN:
if (mCandidatesViewManager instanceof TextCandidatesViewManager) {
((TextCandidatesViewManager) mCandidatesViewManager).setScrollDown();
}
return true;
case OpenWnnEvent.CANDIDATE_VIEW_SCROLL_FULL_UP:
if (mCandidatesViewManager instanceof TextCandidatesViewManager) {
((TextCandidatesViewManager) mCandidatesViewManager).setScrollFullUp();
}
return true;
case OpenWnnEvent.CANDIDATE_VIEW_SCROLL_FULL_DOWN:
if (mCandidatesViewManager instanceof TextCandidatesViewManager) {
((TextCandidatesViewManager) mCandidatesViewManager).setScrollFullDown();
}
return true;
case OpenWnnEvent.FOCUS_CANDIDATE_START:
return true;
case OpenWnnEvent.FOCUS_CANDIDATE_END:
mInputViewManager.onUpdateState(this);
return true;
default:
break;
}
KeyEvent keyEvent = ev.keyEvent;
int keyCode = 0;
if (keyEvent != null) {
keyCode = keyEvent.getKeyCode();
}
if (mDirectInputMode) {
if (mInputConnection != null) {
switch (ev.code) {
case OpenWnnEvent.INPUT_SOFT_KEY:
if (keyCode == KeyEvent.KEYCODE_ENTER) {
sendKeyChar('\n');
} else {
mInputConnection.sendKeyEvent(keyEvent);
mInputConnection.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP,
keyEvent.getKeyCode()));
}
break;
case OpenWnnEvent.INPUT_CHAR:
sendKeyChar(ev.chars[0]);
break;
default:
break;
}
}
/* return if InputConnection is not active */
return false;
}
if (mEngineState.isSymbolList()) {
if (keyEvent != null && keyEvent.isPrintingKey() && isTenKeyCode(keyCode) && !keyEvent.isNumLockOn()) {
return false;
}
switch (keyCode) {
case KeyEvent.KEYCODE_DEL:
return false;
case KeyEvent.KEYCODE_BACK:
initializeScreen();
return true;
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_ENTER:
case KeyEvent.KEYCODE_NUMPAD_ENTER:
if (mCandidatesViewManager.isFocusCandidate()) {
mCandidatesViewManager.selectFocusCandidate();
return true;
}
return false;
case KeyEvent.KEYCODE_DPAD_LEFT:
if (mCandidatesViewManager.isFocusCandidate()) {
processLeftKeyEvent();
return true;
}
return false;
case KeyEvent.KEYCODE_DPAD_RIGHT:
if (mCandidatesViewManager.isFocusCandidate()) {
processRightKeyEvent();
return true;
}
return false;
case KeyEvent.KEYCODE_DPAD_DOWN:
processDownKeyEvent();
return true;
case KeyEvent.KEYCODE_DPAD_UP:
if (mCandidatesViewManager.isFocusCandidate()) {
processUpKeyEvent();
return true;
}
return false;
case KeyEvent.KEYCODE_SPACE:
if (keyEvent != null) {
if (keyEvent.isShiftPressed()) {
onEvent(new OpenWnnEvent(OpenWnnEvent.CANDIDATE_VIEW_SCROLL_UP));
} else if (keyEvent.isAltPressed()) {
if (keyEvent.getRepeatCount() == 0) {
switchSymbolList();
}
} else {
onEvent(new OpenWnnEvent(OpenWnnEvent.CANDIDATE_VIEW_SCROLL_DOWN));
}
}
return true;
case KeyEvent.KEYCODE_SYM:
switchSymbolList();
return true;
case KeyEvent.KEYCODE_PAGE_UP:
onEvent(new OpenWnnEvent(OpenWnnEvent.CANDIDATE_VIEW_SCROLL_UP));
return true;
case KeyEvent.KEYCODE_PAGE_DOWN:
onEvent(new OpenWnnEvent(OpenWnnEvent.CANDIDATE_VIEW_SCROLL_DOWN));
return true;
case KeyEvent.KEYCODE_PICTSYMBOLS:
if (keyEvent != null) {
if (keyEvent.getRepeatCount() == 0) {
switchSymbolList();
}
}
return true;
default:
}
if ((ev.code == OpenWnnEvent.INPUT_KEY) &&
(keyCode != KeyEvent.KEYCODE_SEARCH) &&
(keyCode != KeyEvent.KEYCODE_ALT_LEFT) &&
(keyCode != KeyEvent.KEYCODE_ALT_RIGHT) &&
(keyCode != KeyEvent.KEYCODE_SHIFT_LEFT) &&
(keyCode != KeyEvent.KEYCODE_SHIFT_RIGHT)) {
state = new EngineState();
state.temporaryMode = EngineState.TEMPORARY_DICTIONARY_MODE_NONE;
updateEngineState(state);
}
}
if (!((ev.code == OpenWnnEvent.COMMIT_COMPOSING_TEXT)
|| ((keyEvent != null)
&& ((keyCode == KeyEvent.KEYCODE_SHIFT_LEFT)
|| (keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT)
|| (keyCode == KeyEvent.KEYCODE_ALT_LEFT)
|| (keyCode == KeyEvent.KEYCODE_ALT_RIGHT)
|| (keyEvent.isAltPressed() && (keyCode == KeyEvent.KEYCODE_SPACE)))))) {
clearCommitInfo();
}
/* change back the dictionary if necessary */
if (!((ev.code == OpenWnnEvent.SELECT_CANDIDATE)
|| (ev.code == OpenWnnEvent.LIST_CANDIDATES_NORMAL)
|| (ev.code == OpenWnnEvent.LIST_CANDIDATES_FULL)
|| ((keyEvent != null)
&& ((keyCode == KeyEvent.KEYCODE_SHIFT_LEFT)
||(keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT)
||(keyCode == KeyEvent.KEYCODE_ALT_LEFT)
||(keyCode == KeyEvent.KEYCODE_ALT_RIGHT)
||(keyCode == KeyEvent.KEYCODE_BACK && mCandidatesViewManager.getViewType() == CandidatesViewManager.VIEW_TYPE_FULL)
||(keyEvent.isAltPressed() && (keyCode == KeyEvent.KEYCODE_SPACE)))))) {
state = new EngineState();
state.temporaryMode = EngineState.TEMPORARY_DICTIONARY_MODE_NONE;
updateEngineState(state);
}
if ((ev.code == OpenWnnEvent.INPUT_KEY) && processHardware12Keyboard(keyEvent)) {
return true;
}
if (ev.code == OpenWnnEvent.LIST_CANDIDATES_FULL) {
mStatus |= STATUS_CANDIDATE_FULL;
mCandidatesViewManager.setViewType(CandidatesViewManager.VIEW_TYPE_FULL);
if (!mEngineState.isSymbolList()) {
mInputViewManager.hideInputView();
}
return true;
} else if (ev.code == OpenWnnEvent.LIST_CANDIDATES_NORMAL) {
mStatus &= ~STATUS_CANDIDATE_FULL;
mCandidatesViewManager.setViewType(CandidatesViewManager.VIEW_TYPE_NORMAL);
mInputViewManager.showInputView();
return true;
}
boolean ret = false;
switch (ev.code) {
case OpenWnnEvent.INPUT_CHAR:
if ((mPreConverter == null) && !isEnableL2Converter()) {
/* direct input (= full-width alphabet/number input) */
commitText(false);
commitText(new String(ev.chars));
mCandidatesViewManager.clearCandidates();
} else if (!isEnableL2Converter()) {
processSoftKeyboardCodeWithoutConversion(ev.chars);
} else {
processSoftKeyboardCode(ev.chars);
}
ret = true;
break;
case OpenWnnEvent.TOGGLE_CHAR:
processSoftKeyboardToggleChar(ev.toggleTable);
ret = true;
break;
case OpenWnnEvent.TOGGLE_REVERSE_CHAR:
if (((mStatus & ~STATUS_CANDIDATE_FULL) == STATUS_INPUT)
&& !(mEngineState.isConvertState()) && (ev.toggleTable != null)) {
int cursor = mComposingText.getCursor(ComposingText.LAYER1);
if (cursor > 0) {
String prevChar = mComposingText.getStrSegment(ComposingText.LAYER1, cursor - 1).string;
String c = searchToggleCharacter(prevChar, ev.toggleTable, true);
if (c != null) {
mComposingText.delete(ComposingText.LAYER1, false);
appendStrSegment(new StrSegment(c));
updateViewStatusForPrediction(true, true);
ret = true;
break;
}
}
}
break;
case OpenWnnEvent.REPLACE_CHAR:
int cursor = mComposingText.getCursor(ComposingText.LAYER1);
if ((cursor > 0)
&& !(mEngineState.isConvertState())) {
String search = mComposingText.getStrSegment(ComposingText.LAYER1, cursor - 1).string;
String c = (String)ev.replaceTable.get(search);
if (c != null) {
mComposingText.delete(1, false);
appendStrSegment(new StrSegment(c));
updateViewStatusForPrediction(true, true);
ret = true;
mStatus = STATUS_INPUT_EDIT;
break;
}
}
break;
case OpenWnnEvent.INPUT_KEY:
/* update shift/alt state */
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_DOWN:
case KeyEvent.KEYCODE_DPAD_LEFT:
case KeyEvent.KEYCODE_DPAD_RIGHT:
case KeyEvent.KEYCODE_DPAD_UP:
if (mTutorial != null) {
return true;
}
break;
case KeyEvent.KEYCODE_ALT_LEFT:
case KeyEvent.KEYCODE_ALT_RIGHT:
if (keyEvent.getRepeatCount() == 0) {
if (++mHardAlt > 2) { mHardAlt = 0; }
}
mAltPressing = true;
updateMetaKeyStateDisplay();
return false;
case KeyEvent.KEYCODE_SHIFT_LEFT:
case KeyEvent.KEYCODE_SHIFT_RIGHT:
if (keyEvent.getRepeatCount() == 0) {
if (++mHardShift > 2) { mHardShift = 0; }
}
mShiftPressing = true;
updateMetaKeyStateDisplay();
return false;
}
/* handle other key event */
ret = processKeyEvent(keyEvent);
break;
case OpenWnnEvent.INPUT_SOFT_KEY:
ret = processKeyEvent(keyEvent);
if (!ret) {
int code = keyEvent.getKeyCode();
if (code == KeyEvent.KEYCODE_ENTER) {
sendKeyChar('\n');
} else {
mInputConnection.sendKeyEvent(keyEvent);
mInputConnection.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, code));
}
ret = true;
}
break;
case OpenWnnEvent.SELECT_CANDIDATE:
initCommitInfoForWatchCursor();
if (isEnglishPrediction()) {
mComposingText.clear();
}
mStatus = commitText(ev.word);
if (isEnglishPrediction() && !mEngineState.isSymbolList() && mEnableAutoInsertSpace) {
commitSpaceJustOne();
}
checkCommitInfo();
if (mEngineState.isSymbolList()) {
mEnableAutoDeleteSpace = false;
}
break;
case OpenWnnEvent.CONVERT:
if (mEngineState.isRenbun()) {
if (mCandidatesViewManager instanceof TextCandidatesViewManager) {
if (!mCandidatesViewManager.isFocusCandidate()) {
processDownKeyEvent();
}
processRightKeyEvent();
} else {
mCandidatesViewManager.processMoveKeyEvent(KeyEvent.KEYCODE_DPAD_RIGHT);
}
break;
}
startConvert(EngineState.CONVERT_TYPE_RENBUN);
break;
case OpenWnnEvent.COMMIT_COMPOSING_TEXT:
commitAllText();
break;
}
return ret;
}
/** @see jp.co.omronsoft.openwnn.OpenWnn#onEvaluateFullscreenMode */
@Override public boolean onEvaluateFullscreenMode() {
/* never use full-screen mode */
return false;
}
/** @see jp.co.omronsoft.openwnn.OpenWnn#onEvaluateInputViewShown */
@Override public boolean onEvaluateInputViewShown() {
return true;
}
/**
* Get the instance of this service.
* <br>
* Before using this method, the constructor of this service must be invoked.
*
* @return The instance of this service
*/
public static OpenWnnJAJP getInstance() {
return mSelf;
}
/**
* Create a {@link StrSegment} from a character code.
* <br>
* @param charCode A character code
* @return {@link StrSegment} created; {@code null} if an error occurs.
*/
private StrSegment createStrSegment(int charCode) {
if (charCode == 0) {
return null;
}
return new StrSegment(Character.toChars(charCode));
}
/**
* Key event handler.
*
* @param ev A key event
* @return {@code true} if the event is handled in this method.
*/
private boolean processKeyEvent(KeyEvent ev) {
int key = ev.getKeyCode();
/* keys which produce a glyph */
if (ev.isPrintingKey()) {
if (isTenKeyCode(key) && !ev.isNumLockOn()) {
return false;
}
if (ev.isCtrlPressed()){
if (key == KeyEvent.KEYCODE_A || key == KeyEvent.KEYCODE_F || key == KeyEvent.KEYCODE_C ||
key == KeyEvent.KEYCODE_V || key == KeyEvent.KEYCODE_X || key == KeyEvent.KEYCODE_Z) {
if (mComposingText.size(ComposingText.LAYER1) < 1) {
return false;
} else {
return true;
}
}
}
/* do nothing if the character is not able to display or the character is dead key */
if ((mHardShift > 0 && mHardAlt > 0) ||
(ev.isAltPressed() && ev.isShiftPressed())) {
int charCode = ev.getUnicodeChar(MetaKeyKeyListener.META_SHIFT_ON | MetaKeyKeyListener.META_ALT_ON);
if (charCode == 0 || (charCode & KeyCharacterMap.COMBINING_ACCENT) != 0 || charCode == PRIVATE_AREA_CODE) {
if(mHardShift == 1){
mShiftPressing = false;
}
if(mHardAlt == 1){
mAltPressing = false;
}
if(!ev.isAltPressed()){
if (mHardAlt == 1) {
mHardAlt = 0;
}
}
if(!ev.isShiftPressed()){
if (mHardShift == 1) {
mHardShift = 0;
}
}
if(!ev.isShiftPressed() && !ev.isAltPressed()){
updateMetaKeyStateDisplay();
}
return true;
}
}
commitConvertingText();
EditorInfo edit = getCurrentInputEditorInfo();
StrSegment str;
/* get the key character */
if (mHardShift== 0 && mHardAlt == 0) {
/* no meta key is locked */
int shift = (mAutoCaps)? getShiftKeyState(edit) : 0;
if (shift != mHardShift && (key >= KeyEvent.KEYCODE_A && key <= KeyEvent.KEYCODE_Z)) {
/* handling auto caps for a alphabet character */
str = createStrSegment(ev.getUnicodeChar(MetaKeyKeyListener.META_SHIFT_ON));
} else {
str = createStrSegment(ev.getUnicodeChar());
}
} else {
str = createStrSegment(ev.getUnicodeChar(mShiftKeyToggle[mHardShift]
| mAltKeyToggle[mHardAlt]));
if(mHardShift == 1){
mShiftPressing = false;
}
if(mHardAlt == 1){
mAltPressing = false;
}
/* back to 0 (off) if 1 (on/not locked) */
if (!ev.isAltPressed()) {
if (mHardAlt == 1) {
mHardAlt = 0;
}
}
if (!ev.isShiftPressed()) {
if (mHardShift == 1) {
mHardShift = 0;
}
}
if (!ev.isShiftPressed() && !ev.isShiftPressed()) {
updateMetaKeyStateDisplay();
}
}
if (str == null) {
return true;
}
/* append the character to the composing text if the character is not TAB */
if (str.string.charAt(0) != '\u0009') {
processHardwareKeyboardInputChar(str);
return true;
} else {
commitText(true);
commitText(str.string);
initializeScreen();
return true;
}
} else if (key == KeyEvent.KEYCODE_SPACE) {
/* H/W space key */
processHardwareKeyboardSpaceKey(ev);
return true;
} else if (key == KeyEvent.KEYCODE_SYM) {
/* display the symbol list */
initCommitInfoForWatchCursor();
mStatus = commitText(true);
checkCommitInfo();
changeEngineMode(ENGINE_MODE_SYMBOL);
mHardAlt = 0;
updateMetaKeyStateDisplay();
return true;
}
/* Functional key */
if (mComposingText.size(ComposingText.LAYER1) > 0) {
switch (key) {
case KeyEvent.KEYCODE_DEL:
mStatus = STATUS_INPUT_EDIT;
if (mEngineState.isConvertState()) {
mComposingText.setCursor(ComposingText.LAYER1,
mComposingText.toString(ComposingText.LAYER1).length());
mExactMatchMode = false;
} else {
if ((mComposingText.size(ComposingText.LAYER1) == 1)
&& mComposingText.getCursor(ComposingText.LAYER1) != 0) {
initializeScreen();
return true;
} else {
mComposingText.delete(ComposingText.LAYER1, false);
}
}
updateViewStatusForPrediction(true, true);
return true;
case KeyEvent.KEYCODE_BACK:
if (mCandidatesViewManager.getViewType() == CandidatesViewManager.VIEW_TYPE_FULL) {
mStatus &= ~STATUS_CANDIDATE_FULL;
mCandidatesViewManager.setViewType(CandidatesViewManager.VIEW_TYPE_NORMAL);
mInputViewManager.showInputView();
} else {
if (!mEngineState.isConvertState()) {
initializeScreen();
if (mConverter != null) {
mConverter.init();
}
} else {
mCandidatesViewManager.clearCandidates();
mStatus = STATUS_INPUT_EDIT;
mExactMatchMode = false;
mComposingText.setCursor(ComposingText.LAYER1,
mComposingText.toString(ComposingText.LAYER1).length());
updateViewStatusForPrediction(true, true);
}
}
return true;
case KeyEvent.KEYCODE_DPAD_LEFT:
if (!isEnableL2Converter()) {
commitText(false);
return false;
} else {
processLeftKeyEvent();
return true;
}
case KeyEvent.KEYCODE_DPAD_RIGHT:
if (!isEnableL2Converter()) {
if (mEngineState.keyboard == EngineState.KEYBOARD_12KEY) {
commitText(false);
}
} else {
processRightKeyEvent();
}
return true;
case KeyEvent.KEYCODE_DPAD_DOWN:
processDownKeyEvent();
return true;
case KeyEvent.KEYCODE_DPAD_UP:
if (OpenWnn.isXLarge()) {
updateViewStatusForPrediction(true, true);
} else {
if (mCandidatesViewManager.isFocusCandidate()) {
processUpKeyEvent();
}
}
return true;
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_ENTER:
case KeyEvent.KEYCODE_NUMPAD_ENTER:
if (mCandidatesViewManager.isFocusCandidate()) {
mCandidatesViewManager.selectFocusCandidate();
return true;
}
if (!isEnglishPrediction()) {
int cursor = mComposingText.getCursor(ComposingText.LAYER1);
if (cursor < 1) {
return true;
}
}
initCommitInfoForWatchCursor();
mStatus = commitText(true);
checkCommitInfo();
if (isEnglishPrediction()) {
initializeScreen();
}
if (mEnableAutoHideKeyboard) {
mInputViewManager.closing();
requestHideSelf(0);
}
return true;
case KeyEvent.KEYCODE_CALL:
case KeyEvent.KEYCODE_VOLUME_DOWN:
case KeyEvent.KEYCODE_VOLUME_UP:
return false;
default:
return !isThroughKeyCode(key);
}
} else {
/* if there is no composing string. */
if (mCandidatesViewManager.getCurrentView().isShown()) {
/* displaying relational prediction candidates */
switch (key) {
case KeyEvent.KEYCODE_DPAD_LEFT:
if (mCandidatesViewManager.isFocusCandidate()) {
mCandidatesViewManager.processMoveKeyEvent(KeyEvent.KEYCODE_DPAD_LEFT);
return true;
}
if (isEnableL2Converter()) {
/* initialize the converter */
mConverter.init();
}
mStatus = STATUS_INPUT_EDIT;
updateViewStatusForPrediction(true, true);
return false;
case KeyEvent.KEYCODE_DPAD_RIGHT:
if (mCandidatesViewManager.isFocusCandidate()) {
mCandidatesViewManager.processMoveKeyEvent(KeyEvent.KEYCODE_DPAD_RIGHT);
return true;
}
if (isEnableL2Converter()) {
/* initialize the converter */
mConverter.init();
}
mStatus = STATUS_INPUT_EDIT;
updateViewStatusForPrediction(true, true);
return false;
case KeyEvent.KEYCODE_DPAD_DOWN:
processDownKeyEvent();
return true;
case KeyEvent.KEYCODE_DPAD_UP:
if (mCandidatesViewManager.isFocusCandidate()) {
processUpKeyEvent();
return true;
}
break;
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_ENTER:
case KeyEvent.KEYCODE_NUMPAD_ENTER:
if (mCandidatesViewManager.isFocusCandidate()) {
mCandidatesViewManager.selectFocusCandidate();
return true;
}
break;
default:
return processKeyEventNoInputCandidateShown(ev);
}
} else {
switch (key) {
case KeyEvent.KEYCODE_BACK:
/*
* If 'BACK' key is pressed when the SW-keyboard is shown
* and the candidates view is not shown, dismiss the SW-keyboard.
*/
if (isInputViewShown()) {
mInputViewManager.closing();
requestHideSelf(0);
return true;
}
break;
default:
break;
}
}
}
return false;
}
/**
* Handle the space key event from the Hardware keyboard.
*
* @param ev The space key event
*/
private void processHardwareKeyboardSpaceKey(KeyEvent ev) {
/* H/W space key */
if (ev.isShiftPressed()) {
/* change Japanese <-> English mode */
mHardAlt = 0;
mHardShift = 0;
updateMetaKeyStateDisplay();
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
if (mEngineState.isEnglish()) {
/* English mode to Japanese mode */
((DefaultSoftKeyboardJAJP) mInputViewManager).changeKeyMode(DefaultSoftKeyboard.KEYMODE_JA_FULL_HIRAGANA);
mConverter = mConverterJAJP;
mEnableLearning = pref.getBoolean("opt_enable_learning_ja", true);
mEnablePrediction = pref.getBoolean("opt_prediction_ja", true);
} else {
/* Japanese mode to English mode */
((DefaultSoftKeyboardJAJP) mInputViewManager).changeKeyMode(DefaultSoftKeyboard.KEYMODE_JA_HALF_ALPHABET);
mConverter = mConverterEN;
mEnableLearning = pref.getBoolean("opt_enable_learning_en", true);
mEnablePrediction = pref.getBoolean("opt_prediction_en", false);
if (OpenWnn.isXLarge()) {
mEnableSpellCorrection = pref.getBoolean("opt_spell_correction_en", false);
} else {
mEnableSpellCorrection = pref.getBoolean("opt_spell_correction_en", true);
}
}
mCandidatesViewManager.clearCandidates();
} else if(ev.isAltPressed()){
/* display the symbol list (G1 specific. same as KEYCODE_SYM) */
if (!mEngineState.isSymbolList()) {
commitAllText();
}
changeEngineMode(ENGINE_MODE_SYMBOL);
mHardAlt = 0;
updateMetaKeyStateDisplay();
} else if (isEnglishPrediction()) {
/* Auto commit if English mode */
if (mComposingText.size(0) == 0) {
commitText(" ");
mCandidatesViewManager.clearCandidates();
breakSequence();
} else {
initCommitInfoForWatchCursor();
commitText(true);
commitSpaceJustOne();
checkCommitInfo();
}
mEnableAutoDeleteSpace = false;
} else if (mEngineState.isRenbun()) {
if (mCandidatesViewManager instanceof TextCandidatesViewManager) {
if (!mCandidatesViewManager.isFocusCandidate()) {
processDownKeyEvent();
}
processRightKeyEvent();
} else {
mCandidatesViewManager.processMoveKeyEvent(KeyEvent.KEYCODE_DPAD_RIGHT);
}
} else {
/* start consecutive clause conversion if Japanese mode */
if (mComposingText.size(0) == 0) {
commitText(" ");
mCandidatesViewManager.clearCandidates();
breakSequence();
} else {
startConvert(EngineState.CONVERT_TYPE_RENBUN);
}
}
}
/**
* Handle the character code from the hardware keyboard except the space key.
*
* @param str The input character
*/
private void processHardwareKeyboardInputChar(StrSegment str) {
if (isEnableL2Converter()) {
boolean commit = false;
if (mPreConverter == null) {
Matcher m = mEnglishAutoCommitDelimiter.matcher(str.string);
if (m.matches()) {
commitText(true);
commit = true;
}
appendStrSegment(str);
} else {
appendStrSegment(str);
mPreConverter.convert(mComposingText);
}
if (commit) {
commitText(true);
} else {
mStatus = STATUS_INPUT;
updateViewStatusForPrediction(true, true);
}
} else {
appendStrSegment(str);
boolean completed = true;
if (mPreConverter != null) {
completed = mPreConverter.convert(mComposingText);
}
if (completed) {
if (!mEngineState.isEnglish()) {
commitTextWithoutLastAlphabet();
} else {
commitText(false);
}
} else {
updateViewStatus(ComposingText.LAYER1, false, true);
}
}
}
/** Thread for updating the candidates view */
private void updatePrediction() {
int candidates = 0;
int cursor = mComposingText.getCursor(ComposingText.LAYER1);
if (isEnableL2Converter() || mEngineState.isSymbolList()) {
if (mExactMatchMode) {
/* exact matching */
candidates = mConverter.predict(mComposingText, 0, cursor);
} else {
/* normal prediction */
candidates = mConverter.predict(mComposingText, 0, -1);
}
}
/* update the candidates view */
if (candidates > 0) {
mHasContinuedPrediction = ((mComposingText.size(ComposingText.LAYER1) == 0)
&& !mEngineState.isSymbolList());
mCandidatesViewManager.displayCandidates(mConverter);
} else {
mCandidatesViewManager.clearCandidates();
}
}
/**
* Handle a left key event.
*/
private void processLeftKeyEvent() {
if (mCandidatesViewManager.isFocusCandidate()) {
mCandidatesViewManager.processMoveKeyEvent(KeyEvent.KEYCODE_DPAD_LEFT);
return;
}
if (mEngineState.isConvertState()) {
if (mEngineState.isEisuKana()) {
mExactMatchMode = true;
}
if (1 < mComposingText.getCursor(ComposingText.LAYER1)) {
mComposingText.moveCursor(ComposingText.LAYER1, -1);
}
} else if (mExactMatchMode) {
mComposingText.moveCursor(ComposingText.LAYER1, -1);
} else {
if (isEnglishPrediction()) {
mComposingText.moveCursor(ComposingText.LAYER1, -1);
} else {
mExactMatchMode = true;
}
}
mCommitCount = 0; /* retry consecutive clause conversion if necessary. */
mStatus = STATUS_INPUT_EDIT;
updateViewStatus(mTargetLayer, true, true);
}
/**
* Handle a right key event.
*/
private void processRightKeyEvent() {
if (mCandidatesViewManager.isFocusCandidate()) {
mCandidatesViewManager.processMoveKeyEvent(KeyEvent.KEYCODE_DPAD_RIGHT);
return;
}
int layer = mTargetLayer;
ComposingText composingText = mComposingText;
if (mExactMatchMode || (mEngineState.isConvertState())) {
int textSize = composingText.size(ComposingText.LAYER1);
if (composingText.getCursor(ComposingText.LAYER1) == textSize) {
mExactMatchMode = false;
layer = ComposingText.LAYER1; /* convert -> prediction */
EngineState state = new EngineState();
state.convertType = EngineState.CONVERT_TYPE_NONE;
updateEngineState(state);
} else {
if (mEngineState.isEisuKana()) {
mExactMatchMode = true;
}
composingText.moveCursor(ComposingText.LAYER1, 1);
}
} else {
if (composingText.getCursor(ComposingText.LAYER1)
< composingText.size(ComposingText.LAYER1)) {
composingText.moveCursor(ComposingText.LAYER1, 1);
}
}
mCommitCount = 0; /* retry consecutive clause conversion if necessary. */
mStatus = STATUS_INPUT_EDIT;
updateViewStatus(layer, true, true);
}
/**
* Handle a down key event.
*/
private void processDownKeyEvent() {
mCandidatesViewManager.processMoveKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN);
}
/**
* Handle a up key event.
*/
private void processUpKeyEvent() {
mCandidatesViewManager.processMoveKeyEvent(KeyEvent.KEYCODE_DPAD_UP);
}
/**
* Handle a key event which is not right or left key when the
* composing text is empty and some candidates are shown.
*
* @param ev A key event
* @return {@code true} if this consumes the event; {@code false} if not.
*/
boolean processKeyEventNoInputCandidateShown(KeyEvent ev) {
boolean ret = true;
int key = ev.getKeyCode();
switch (key) {
case KeyEvent.KEYCODE_DEL:
ret = true;
break;
case KeyEvent.KEYCODE_ENTER:
case KeyEvent.KEYCODE_NUMPAD_ENTER:
case KeyEvent.KEYCODE_DPAD_UP:
case KeyEvent.KEYCODE_DPAD_DOWN:
case KeyEvent.KEYCODE_MENU:
ret = false;
break;
case KeyEvent.KEYCODE_CALL:
case KeyEvent.KEYCODE_VOLUME_DOWN:
case KeyEvent.KEYCODE_VOLUME_UP:
return false;
case KeyEvent.KEYCODE_DPAD_CENTER:
ret = true;
break;
case KeyEvent.KEYCODE_BACK:
if (mCandidatesViewManager.getViewType() == CandidatesViewManager.VIEW_TYPE_FULL) {
mStatus &= ~STATUS_CANDIDATE_FULL;
mCandidatesViewManager.setViewType(CandidatesViewManager.VIEW_TYPE_NORMAL);
mInputViewManager.showInputView();
return true;
} else {
ret = true;
}
break;
default:
return !isThroughKeyCode(key);
}
if (mConverter != null) {
/* initialize the converter */
mConverter.init();
}
updateViewStatusForPrediction(true, true);
return ret;
}
/**
* Update views and the display of the composing text for predict mode.
*
* @param updateCandidates {@code true} to update the candidates view
* @param updateEmptyText {@code false} to update the composing text if it is not empty; {@code true} to update always.
*/
private void updateViewStatusForPrediction(boolean updateCandidates, boolean updateEmptyText) {
EngineState state = new EngineState();
state.convertType = EngineState.CONVERT_TYPE_NONE;
updateEngineState(state);
updateViewStatus(ComposingText.LAYER1, updateCandidates, updateEmptyText);
}
/**
* Update views and the display of the composing text.
*
* @param layer Display layer of the composing text
* @param updateCandidates {@code true} to update the candidates view
* @param updateEmptyText {@code false} to update the composing text if it is not empty; {@code true} to update always.
*/
private void updateViewStatus(int layer, boolean updateCandidates, boolean updateEmptyText) {
mTargetLayer = layer;
if (updateCandidates) {
updateCandidateView();
}
/* notice to the input view */
mInputViewManager.onUpdateState(this);
/* set the text for displaying as the composing text */
mDisplayText.clear();
mDisplayText.insert(0, mComposingText.toString(layer));
/* add decoration to the text */
int cursor = mComposingText.getCursor(layer);
if ((mInputConnection != null) && (mDisplayText.length() != 0 || updateEmptyText)) {
if (cursor != 0) {
int highlightEnd = 0;
if ((mExactMatchMode && (!mEngineState.isEisuKana()))
|| (FIX_CURSOR_TEXT_END && isEnglishPrediction()
&& (cursor < mComposingText.size(ComposingText.LAYER1)))){
mDisplayText.setSpan(SPAN_EXACT_BGCOLOR_HL, 0, cursor,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
highlightEnd = cursor;
} else if (FIX_CURSOR_TEXT_END && mEngineState.isEisuKana()) {
mDisplayText.setSpan(SPAN_EISUKANA_BGCOLOR_HL, 0, cursor,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
highlightEnd = cursor;
} else if (layer == ComposingText.LAYER2) {
highlightEnd = mComposingText.toString(layer, 0, 0).length();
/* highlights the first segment */
mDisplayText.setSpan(SPAN_CONVERT_BGCOLOR_HL, 0,
highlightEnd,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
if (FIX_CURSOR_TEXT_END && (highlightEnd != 0)) {
/* highlights remaining text */
mDisplayText.setSpan(SPAN_REMAIN_BGCOLOR_HL, highlightEnd,
mComposingText.toString(layer).length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
/* text color in the highlight */
mDisplayText.setSpan(SPAN_TEXTCOLOR, 0,
mComposingText.toString(layer).length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
mDisplayText.setSpan(SPAN_UNDERLINE, 0, mDisplayText.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
int displayCursor = mComposingText.toString(layer, 0, cursor - 1).length();
if (FIX_CURSOR_TEXT_END) {
displayCursor = (cursor == 0) ? 0 : 1;
}
/* update the composing text on the EditView */
if ((mDisplayText.length() != 0) || !mHasStartedTextSelection) {
mInputConnection.setComposingText(mDisplayText, displayCursor);
}
}
}
/**
* Update the candidates view.
*/
private void updateCandidateView() {
switch (mTargetLayer) {
case ComposingText.LAYER0:
case ComposingText.LAYER1: /* prediction */
if (mEnablePrediction || mEngineState.isSymbolList() || mEngineState.isEisuKana()) {
/* update the candidates view */
if ((mComposingText.size(ComposingText.LAYER1) != 0)
&& !mEngineState.isConvertState()) {
mHandler.removeMessages(MSG_PREDICTION);
if (mCandidatesViewManager.getCurrentView().isShown()) {
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_PREDICTION),
PREDICTION_DELAY_MS_SHOWING_CANDIDATE);
} else {
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_PREDICTION),
PREDICTION_DELAY_MS_1ST);
}
} else {
mHandler.removeMessages(MSG_PREDICTION);
updatePrediction();
}
} else {
mHandler.removeMessages(MSG_PREDICTION);
mCandidatesViewManager.clearCandidates();
}
break;
case ComposingText.LAYER2: /* convert */
if (mCommitCount == 0) {
mHandler.removeMessages(MSG_PREDICTION);
mConverter.convert(mComposingText);
}
int candidates = mConverter.makeCandidateListOf(mCommitCount);
if (candidates != 0) {
mComposingText.setCursor(ComposingText.LAYER2, 1);
mCandidatesViewManager.displayCandidates(mConverter);
} else {
mComposingText.setCursor(ComposingText.LAYER1,
mComposingText.toString(ComposingText.LAYER1).length());
mCandidatesViewManager.clearCandidates();
}
break;
default:
break;
}
}
/**
* Commit the displaying composing text.
*
* @param learn {@code true} to register the committed string to the learning dictionary.
* @return IME's status after commit
*/
private int commitText(boolean learn) {
if (isEnglishPrediction()) {
mComposingText.setCursor(ComposingText.LAYER1,
mComposingText.size(ComposingText.LAYER1));
}
int layer = mTargetLayer;
int cursor = mComposingText.getCursor(layer);
if (cursor == 0) {
return mStatus;
}
String tmp = mComposingText.toString(layer, 0, cursor - 1);
if (mConverter != null) {
if (learn) {
if (mEngineState.isRenbun()) {
learnWord(0); /* select the top of the clauses */
} else {
if (mComposingText.size(ComposingText.LAYER1) != 0) {
String stroke = mComposingText.toString(ComposingText.LAYER1, 0, mComposingText.getCursor(layer) - 1);
WnnWord word = new WnnWord(tmp, stroke);
learnWord(word);
}
}
} else {
breakSequence();
}
}
return commitTextThroughInputConnection(tmp);
}
/**
* Commit the composing text except the alphabet character at the tail.
*/
private void commitTextWithoutLastAlphabet() {
int layer = mTargetLayer;
String tmp = mComposingText.getStrSegment(layer, -1).string;
if (isAlphabetLast(tmp)) {
mComposingText.moveCursor(ComposingText.LAYER1, -1);
commitText(false);
mComposingText.moveCursor(ComposingText.LAYER1, 1);
} else {
commitText(false);
}
}
/**
* Commit all uncommitted words.
*/
private void commitAllText() {
initCommitInfoForWatchCursor();
if (mEngineState.isConvertState()) {
commitConvertingText();
} else {
mComposingText.setCursor(ComposingText.LAYER1,
mComposingText.size(ComposingText.LAYER1));
mStatus = commitText(true);
}
checkCommitInfo();
}
/**
* Commit a word.
*
* @param word A word to commit
* @return IME's status after commit
*/
private int commitText(WnnWord word) {
if (mConverter != null) {
learnWord(word);
}
return commitTextThroughInputConnection(word.candidate);
}
/**
* Commit a string.
*
* @param str A string to commit
*/
private void commitText(String str) {
mInputConnection.commitText(str, (FIX_CURSOR_TEXT_END ? 1 : str.length()));
mPrevCommitText.append(str);
mPrevCommitCount++;
mEnableAutoDeleteSpace = true;
updateViewStatusForPrediction(false, false);
}
/**
* Commit a string through {@link InputConnection}.
*
* @param string A string to commit
* @return IME's status after commit
*/
private int commitTextThroughInputConnection(String string) {
int layer = mTargetLayer;
mInputConnection.commitText(string, (FIX_CURSOR_TEXT_END ? 1 : string.length()));
mPrevCommitText.append(string);
mPrevCommitCount++;
int cursor = mComposingText.getCursor(layer);
if (cursor > 0) {
mComposingText.deleteStrSegment(layer, 0, mComposingText.getCursor(layer) - 1);
mComposingText.setCursor(layer, mComposingText.size(layer));
}
mExactMatchMode = false;
mCommitCount++;
if ((layer == ComposingText.LAYER2) && (mComposingText.size(layer) == 0)) {
layer = 1; /* for connected prediction */
}
boolean committed = autoCommitEnglish();
mEnableAutoDeleteSpace = true;
if (layer == ComposingText.LAYER2) {
EngineState state = new EngineState();
state.convertType = EngineState.CONVERT_TYPE_RENBUN;
updateEngineState(state);
updateViewStatus(layer, !committed, false);
} else {
updateViewStatusForPrediction(!committed, false);
}
if (mComposingText.size(ComposingText.LAYER0) == 0) {
return STATUS_INIT;
} else {
return STATUS_INPUT_EDIT;
}
}
/**
* Returns whether it is English prediction mode or not.
*
* @return {@code true} if it is English prediction mode; otherwise, {@code false}.
*/
private boolean isEnglishPrediction() {
return (mEngineState.isEnglish() && isEnableL2Converter());
}
/**
* Change the conversion engine and the letter converter(Romaji-to-Kana converter).
*
* @param mode Engine's mode to be changed
* @see jp.co.omronsoft.openwnn.OpenWnnEvent.Mode
* @see jp.co.omronsoft.openwnn.JAJP.DefaultSoftKeyboardJAJP
*/
private void changeEngineMode(int mode) {
EngineState state = new EngineState();
switch (mode) {
case ENGINE_MODE_OPT_TYPE_QWERTY:
state.keyboard = EngineState.KEYBOARD_QWERTY;
updateEngineState(state);
clearCommitInfo();
return;
case ENGINE_MODE_OPT_TYPE_12KEY:
state.keyboard = EngineState.KEYBOARD_12KEY;
updateEngineState(state);
clearCommitInfo();
return;
case ENGINE_MODE_EISU_KANA:
if (mEngineState.isEisuKana()) {
state.temporaryMode = EngineState.TEMPORARY_DICTIONARY_MODE_NONE;
updateEngineState(state);
updateViewStatusForPrediction(true, true); /* prediction only */
} else {
startConvert(EngineState.CONVERT_TYPE_EISU_KANA);
}
return;
case ENGINE_MODE_SYMBOL:
if (mEnableSymbolList && !mDirectInputMode) {
state.temporaryMode = EngineState.TEMPORARY_DICTIONARY_MODE_SYMBOL;
updateEngineState(state);
updateViewStatusForPrediction(true, true);
}
return;
case ENGINE_MODE_SYMBOL_KAO_MOJI:
changeSymbolEngineState(state, ENGINE_MODE_SYMBOL_KAO_MOJI);
return;
default:
break;
}
state = new EngineState();
state.temporaryMode = EngineState.TEMPORARY_DICTIONARY_MODE_NONE;
updateEngineState(state);
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
state = new EngineState();
switch (mode) {
case OpenWnnEvent.Mode.DIRECT:
/* Full/Half-width number or Full-width alphabet */
mConverter = null;
mPreConverter = null;
break;
case OpenWnnEvent.Mode.NO_LV1_CONV:
/* no Romaji-to-Kana conversion (=English prediction mode) */
state.dictionarySet = EngineState.DICTIONARYSET_EN;
updateEngineState(state);
mConverter = mConverterEN;
mPreConverter = null;
mEnableLearning = pref.getBoolean("opt_enable_learning_en", true);
mEnablePrediction = pref.getBoolean("opt_prediction_en", false);
if (OpenWnn.isXLarge()) {
mEnableSpellCorrection = pref.getBoolean("opt_spell_correction_en", false);
} else {
mEnableSpellCorrection = pref.getBoolean("opt_spell_correction_en", true);
}
break;
case OpenWnnEvent.Mode.NO_LV2_CONV:
mConverter = null;
mPreConverter = mPreConverterHiragana;
break;
case ENGINE_MODE_FULL_KATAKANA:
mConverter = null;
mPreConverter = mPreConverterFullKatakana;
break;
case ENGINE_MODE_HALF_KATAKANA:
mConverter = null;
mPreConverter = mPreConverterHalfKatakana;
break;
default:
/* HIRAGANA input mode */
state.dictionarySet = EngineState.DICTIONARYSET_JP;
updateEngineState(state);
mConverter = mConverterJAJP;
mPreConverter = mPreConverterHiragana;
mEnableLearning = pref.getBoolean("opt_enable_learning_ja", true);
mEnablePrediction = pref.getBoolean("opt_prediction_ja", true);
break;
}
mPreConverterBack = mPreConverter;
mConverterBack = mConverter;
}
/**
* Update the conversion engine's state.
*
* @param state Engine's state to be updated
*/
private void updateEngineState(EngineState state) {
EngineState myState = mEngineState;
/* language */
if ((state.dictionarySet != EngineState.INVALID)
&& (myState.dictionarySet != state.dictionarySet)) {
switch (state.dictionarySet) {
case EngineState.DICTIONARYSET_EN:
setDictionary(OpenWnnEngineJAJP.DIC_LANG_EN);
break;
case EngineState.DICTIONARYSET_JP:
default:
setDictionary(OpenWnnEngineJAJP.DIC_LANG_JP);
break;
}
myState.dictionarySet = state.dictionarySet;
breakSequence();
/* update keyboard setting */
if (state.keyboard == EngineState.INVALID) {
state.keyboard = myState.keyboard;
}
}
/* type of conversion */
if ((state.convertType != EngineState.INVALID)
&& (myState.convertType != state.convertType)) {
switch (state.convertType) {
case EngineState.CONVERT_TYPE_NONE:
setDictionary(mPrevDictionarySet);
break;
case EngineState.CONVERT_TYPE_EISU_KANA:
setDictionary(OpenWnnEngineJAJP.DIC_LANG_JP_EISUKANA);
break;
case EngineState.CONVERT_TYPE_RENBUN:
default:
setDictionary(OpenWnnEngineJAJP.DIC_LANG_JP);
break;
}
myState.convertType = state.convertType;
}
/* temporary dictionary */
if (state.temporaryMode != EngineState.INVALID) {
switch (state.temporaryMode) {
case EngineState.TEMPORARY_DICTIONARY_MODE_NONE:
if (myState.temporaryMode != EngineState.TEMPORARY_DICTIONARY_MODE_NONE) {
setDictionary(mPrevDictionarySet);
mCurrentSymbol = -1;
mPreConverter = mPreConverterBack;
mConverter = mConverterBack;
mDisableAutoCommitEnglishMask &= ~AUTO_COMMIT_ENGLISH_SYMBOL;
((DefaultSoftKeyboard)mInputViewManager).setNormalKeyboard();
mTextCandidatesViewManager.setSymbolMode(false, ENGINE_MODE_SYMBOL_NONE);
if (OpenWnn.isXLarge()) {
mCandidatesViewManager = mTextCandidates1LineViewManager;
View view = mTextCandidates1LineViewManager.getCurrentView();
if (view != null) {
setCandidatesView(view);
}
}
}
break;
case EngineState.TEMPORARY_DICTIONARY_MODE_SYMBOL:
if (++mCurrentSymbol >= SYMBOL_LISTS.length) {
mCurrentSymbol = 0;
}
if (mEnableSymbolListNonHalf) {
mConverterSymbolEngineBack.setDictionary(SYMBOL_LISTS[mCurrentSymbol]);
} else {
mConverterSymbolEngineBack.setDictionary(SymbolList.SYMBOL_ENGLISH);
}
mConverter = mConverterSymbolEngineBack;
mDisableAutoCommitEnglishMask |= AUTO_COMMIT_ENGLISH_SYMBOL;
int engineModeSymbol = 0;
if (SYMBOL_LISTS[mCurrentSymbol] == SymbolList.SYMBOL_JAPANESE) {
engineModeSymbol = ENGINE_MODE_SYMBOL;
} else if (SYMBOL_LISTS[mCurrentSymbol] == SymbolList.SYMBOL_JAPANESE_FACE) {
engineModeSymbol = ENGINE_MODE_SYMBOL_KAO_MOJI;
} else {
}
mTextCandidatesViewManager.setSymbolMode(true, engineModeSymbol);
if (OpenWnn.isXLarge()) {
mCandidatesViewManager = mTextCandidatesViewManager;
View view = mTextCandidatesViewManager.getCurrentView();
if (view != null) {
setCandidatesView(view);
}
}
breakSequence();
((DefaultSoftKeyboard)mInputViewManager).setSymbolKeyboard();
break;
default:
break;
}
myState.temporaryMode = state.temporaryMode;
}
/* preference dictionary */
if ((state.preferenceDictionary != EngineState.INVALID)
&& (myState.preferenceDictionary != state.preferenceDictionary)) {
myState.preferenceDictionary = state.preferenceDictionary;
setDictionary(mPrevDictionarySet);
}
/* keyboard type */
if (state.keyboard != EngineState.INVALID) {
switch (state.keyboard) {
case EngineState.KEYBOARD_12KEY:
mConverterJAJP.setKeyboardType(OpenWnnEngineJAJP.KEYBOARD_KEYPAD12);
mConverterEN.setDictionary(OpenWnnEngineEN.DICT_DEFAULT);
break;
case EngineState.KEYBOARD_QWERTY:
default:
mConverterJAJP.setKeyboardType(OpenWnnEngineJAJP.KEYBOARD_QWERTY);
if (mEnableSpellCorrection) {
mConverterEN.setDictionary(OpenWnnEngineEN.DICT_FOR_CORRECT_MISTYPE);
} else {
mConverterEN.setDictionary(OpenWnnEngineEN.DICT_DEFAULT);
}
break;
}
myState.keyboard = state.keyboard;
}
}
/**
* Set dictionaries to be used.
*
* @param mode Definition of dictionaries
*/
private void setDictionary(int mode) {
int target = mode;
switch (target) {
case OpenWnnEngineJAJP.DIC_LANG_JP:
switch (mEngineState.preferenceDictionary) {
case EngineState.PREFERENCE_DICTIONARY_PERSON_NAME:
target = OpenWnnEngineJAJP.DIC_LANG_JP_PERSON_NAME;
break;
case EngineState.PREFERENCE_DICTIONARY_POSTAL_ADDRESS:
target = OpenWnnEngineJAJP.DIC_LANG_JP_POSTAL_ADDRESS;
break;
default:
break;
}
break;
case OpenWnnEngineJAJP.DIC_LANG_EN:
switch (mEngineState.preferenceDictionary) {
case EngineState.PREFERENCE_DICTIONARY_EMAIL_ADDRESS_URI:
target = OpenWnnEngineJAJP.DIC_LANG_EN_EMAIL_ADDRESS;
break;
default:
break;
}
break;
default:
break;
}
switch (mode) {
case OpenWnnEngineJAJP.DIC_LANG_JP:
case OpenWnnEngineJAJP.DIC_LANG_EN:
mPrevDictionarySet = mode;
break;
default:
break;
}
mConverterJAJP.setDictionary(target);
}
/**
* Handle a toggle key input event.
*
* @param table Table of toggle characters
*/
private void processSoftKeyboardToggleChar(String[] table) {
if (table == null) {
return;
}
commitConvertingText();
boolean toggled = false;
if ((mStatus & ~STATUS_CANDIDATE_FULL) == STATUS_INPUT) {
int cursor = mComposingText.getCursor(ComposingText.LAYER1);
if (cursor > 0) {
String prevChar = mComposingText.getStrSegment(ComposingText.LAYER1,
cursor - 1).string;
String c = searchToggleCharacter(prevChar, table, false);
if (c != null) {
mComposingText.delete(ComposingText.LAYER1, false);
appendStrSegment(new StrSegment(c));
toggled = true;
}
}
}
if (!toggled) {
if (!isEnableL2Converter()) {
commitText(false);
}
String str = table[0];
/* shift on */
if (mAutoCaps && (getShiftKeyState(getCurrentInputEditorInfo()) == 1)) {
char top = table[0].charAt(0);
if (Character.isLowerCase(top)) {
str = Character.toString(Character.toUpperCase(top));
}
}
appendStrSegment(new StrSegment(str));
}
mStatus = STATUS_INPUT;
updateViewStatusForPrediction(true, true);
}
/**
* Handle character input from the software keyboard without listing candidates.
*
* @param chars The input character(s)
*/
private void processSoftKeyboardCodeWithoutConversion(char[] chars) {
if (chars == null) {
return;
}
ComposingText text = mComposingText;
appendStrSegment(new StrSegment(chars));
if (!isAlphabetLast(text.toString(ComposingText.LAYER1))) {
/* commit if the input character is not alphabet */
commitText(false);
} else {
boolean completed = mPreConverter.convert(text);
if (completed) {
commitTextWithoutLastAlphabet();
} else {
mStatus = STATUS_INPUT;
updateViewStatusForPrediction(true, true);
}
}
}
/**
* Handle character input from the software keyboard.
*
* @param chars The input character(s)
*/
private void processSoftKeyboardCode(char[] chars) {
if (chars == null) {
return;
}
if ((chars[0] == ' ') || (chars[0] == '\u3000' /* Full-width space */)) {
if (mComposingText.size(0) == 0) {
mCandidatesViewManager.clearCandidates();
commitText(new String(chars));
breakSequence();
} else {
if (isEnglishPrediction()) {
initCommitInfoForWatchCursor();
commitText(true);
commitSpaceJustOne();
checkCommitInfo();
} else {
if (mEngineState.isRenbun()) {
if (mCandidatesViewManager instanceof TextCandidatesViewManager) {
if (!mCandidatesViewManager.isFocusCandidate()) {
processDownKeyEvent();
}
processRightKeyEvent();
} else {
mCandidatesViewManager.processMoveKeyEvent(KeyEvent.KEYCODE_DPAD_RIGHT);
}
} else {
startConvert(EngineState.CONVERT_TYPE_RENBUN);
}
}
}
mEnableAutoDeleteSpace = false;
} else {
commitConvertingText();
/* Auto-commit a word if it is English and Qwerty mode */
boolean commit = false;
if (isEnglishPrediction()
&& (mEngineState.keyboard == EngineState.KEYBOARD_QWERTY)) {
Matcher m = mEnglishAutoCommitDelimiter.matcher(new String(chars));
if (m.matches()) {
commit = true;
}
}
if (commit) {
commitText(true);
appendStrSegment(new StrSegment(chars));
commitText(true);
} else {
appendStrSegment(new StrSegment(chars));
if (mPreConverter != null) {
mPreConverter.convert(mComposingText);
mStatus = STATUS_INPUT;
}
updateViewStatusForPrediction(true, true);
}
}
}
/**
* Start consecutive clause conversion or EISU-KANA conversion mode.
*
* @param convertType The conversion type({@code EngineState.CONVERT_TYPE_*})
*/
private void startConvert(int convertType) {
if (!isEnableL2Converter()) {
return;
}
if (mEngineState.convertType != convertType) {
/* adjust the cursor position */
if (!mExactMatchMode) {
if (convertType == EngineState.CONVERT_TYPE_RENBUN) {
/* not specify */
mComposingText.setCursor(ComposingText.LAYER1, 0);
} else {
if (mEngineState.isRenbun()) {
/* EISU-KANA conversion specifying the position of the segment if previous mode is conversion mode */
mExactMatchMode = true;
} else {
/* specify all range */
mComposingText.setCursor(ComposingText.LAYER1,
mComposingText.size(ComposingText.LAYER1));
}
}
}
if (convertType == EngineState.CONVERT_TYPE_RENBUN) {
/* clears variables for the prediction */
mExactMatchMode = false;
}
/* clears variables for the convert */
mCommitCount = 0;
int layer;
if (convertType == EngineState.CONVERT_TYPE_EISU_KANA) {
layer = ComposingText.LAYER1;
} else {
layer = ComposingText.LAYER2;
}
EngineState state = new EngineState();
state.convertType = convertType;
updateEngineState(state);
updateViewStatus(layer, true, true);
}
}
/**
* Auto commit a word in English (on half-width alphabet mode).
*
* @return {@code true} if auto-committed; otherwise, {@code false}.
*/
private boolean autoCommitEnglish() {
if (isEnglishPrediction() && (mDisableAutoCommitEnglishMask == AUTO_COMMIT_ENGLISH_ON)) {
CharSequence seq = mInputConnection.getTextBeforeCursor(2, 0);
Matcher m = mEnglishAutoCommitDelimiter.matcher(seq);
if (m.matches()) {
if ((seq.charAt(0) == ' ') && mEnableAutoDeleteSpace) {
mInputConnection.deleteSurroundingText(2, 0);
CharSequence str = seq.subSequence(1, 2);
mInputConnection.commitText(str, 1);
mPrevCommitText.append(str);
mPrevCommitCount++;
}
mHandler.removeMessages(MSG_PREDICTION);
mCandidatesViewManager.clearCandidates();
return true;
}
}
return false;
}
/**
* Insert a white space if the previous character is not a white space.
*/
private void commitSpaceJustOne() {
CharSequence seq = mInputConnection.getTextBeforeCursor(1, 0);
if (seq.charAt(0) != ' ') {
commitText(" ");
}
}
/**
* Get the shift key state from the editor.
*
* @param editor The editor
* @return State ID of the shift key (0:off, 1:on)
*/
protected int getShiftKeyState(EditorInfo editor) {
return (getCurrentInputConnection().getCursorCapsMode(editor.inputType) == 0) ? 0 : 1;
}
/**
* Display current meta-key state.
*/
private void updateMetaKeyStateDisplay() {
int mode = 0;
if(mHardShift == 0 && mHardAlt == 0){
mode = DefaultSoftKeyboard.HARD_KEYMODE_SHIFT_OFF_ALT_OFF;
}else if(mHardShift == 1 && mHardAlt == 0){
mode = DefaultSoftKeyboard.HARD_KEYMODE_SHIFT_ON_ALT_OFF;
}else if(mHardShift == 2 && mHardAlt == 0){
mode = DefaultSoftKeyboard.HARD_KEYMODE_SHIFT_LOCK_ALT_OFF;
}else if(mHardShift == 0 && mHardAlt == 1){
mode = DefaultSoftKeyboard.HARD_KEYMODE_SHIFT_OFF_ALT_ON;
}else if(mHardShift == 0 && mHardAlt == 2){
mode = DefaultSoftKeyboard.HARD_KEYMODE_SHIFT_OFF_ALT_LOCK;
}else if(mHardShift == 1 && mHardAlt == 1){
mode = DefaultSoftKeyboard.HARD_KEYMODE_SHIFT_ON_ALT_ON;
}else if(mHardShift == 1 && mHardAlt == 2){
mode = DefaultSoftKeyboard.HARD_KEYMODE_SHIFT_ON_ALT_LOCK;
}else if(mHardShift == 2 && mHardAlt == 1){
mode = DefaultSoftKeyboard.HARD_KEYMODE_SHIFT_LOCK_ALT_ON;
}else if(mHardShift == 2 && mHardAlt == 2){
mode = DefaultSoftKeyboard.HARD_KEYMODE_SHIFT_LOCK_ALT_LOCK;
}else{
mode = DefaultSoftKeyboard.HARD_KEYMODE_SHIFT_OFF_ALT_OFF;
}
((DefaultSoftKeyboard) mInputViewManager).updateIndicator(mode);
}
/**
* Memory a selected word.
*
* @param word A selected word
*/
private void learnWord(WnnWord word) {
if (mEnableLearning && word != null) {
mConverter.learn(word);
}
}
/**
* Memory a clause which is generated by consecutive clause conversion.
*
* @param index Index of a clause
*/
private void learnWord(int index) {
ComposingText composingText = mComposingText;
if (mEnableLearning && composingText.size(ComposingText.LAYER2) > index) {
StrSegment seg = composingText.getStrSegment(ComposingText.LAYER2, index);
if (seg instanceof StrSegmentClause) {
mConverter.learn(((StrSegmentClause)seg).clause);
} else {
String stroke = composingText.toString(ComposingText.LAYER1, seg.from, seg.to);
mConverter.learn(new WnnWord(seg.string, stroke));
}
}
}
/**
* Fits an editor info.
*
* @param preferences The preference data.
* @param info The editor info.
*/
private void fitInputType(SharedPreferences preference, EditorInfo info) {
if (info.inputType == EditorInfo.TYPE_NULL) {
mDirectInputMode = true;
return;
}
if (mConverter == mConverterEN) {
mEnableLearning = preference.getBoolean("opt_enable_learning_en", true);
mEnablePrediction = preference.getBoolean("opt_prediction_en", false);
if (OpenWnn.isXLarge()) {
mEnableSpellCorrection = preference.getBoolean("opt_spell_correction_en", false);
} else {
mEnableSpellCorrection = preference.getBoolean("opt_spell_correction_en", true);
}
} else {
mEnableLearning = preference.getBoolean("opt_enable_learning_ja", true);
mEnablePrediction = preference.getBoolean("opt_prediction_ja", true);
}
mDisableAutoCommitEnglishMask &= ~AUTO_COMMIT_ENGLISH_OFF;
int preferenceDictionary = EngineState.PREFERENCE_DICTIONARY_NONE;
mEnableConverter = true;
mEnableSymbolList = true;
mEnableSymbolListNonHalf = true;
setEnabledTabs(true);
mAutoCaps = preference.getBoolean("auto_caps", true);
mFilter.filter = 0;
mEnableAutoInsertSpace = true;
mEnableAutoHideKeyboard = false;
switch (info.inputType & EditorInfo.TYPE_MASK_CLASS) {
case EditorInfo.TYPE_CLASS_NUMBER:
case EditorInfo.TYPE_CLASS_DATETIME:
mEnableConverter = false;
break;
case EditorInfo.TYPE_CLASS_PHONE:
mEnableSymbolList = false;
mEnableConverter = false;
break;
case EditorInfo.TYPE_CLASS_TEXT:
switch (info.inputType & EditorInfo.TYPE_MASK_VARIATION) {
case EditorInfo.TYPE_TEXT_VARIATION_PERSON_NAME:
preferenceDictionary = EngineState.PREFERENCE_DICTIONARY_PERSON_NAME;
break;
case EditorInfo.TYPE_TEXT_VARIATION_PASSWORD:
case EditorInfo.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD:
mEnableLearning = false;
mEnableConverter = false;
mEnableSymbolListNonHalf = false;
mFilter.filter = CandidateFilter.FILTER_NON_ASCII;
mDisableAutoCommitEnglishMask |= AUTO_COMMIT_ENGLISH_OFF;
mTextCandidatesViewManager.setEnableEmoticon(false);
break;
case EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS:
mEnableAutoInsertSpace = false;
mDisableAutoCommitEnglishMask |= AUTO_COMMIT_ENGLISH_OFF;
preferenceDictionary = EngineState.PREFERENCE_DICTIONARY_EMAIL_ADDRESS_URI;
break;
case EditorInfo.TYPE_TEXT_VARIATION_URI:
mEnableAutoInsertSpace = false;
mDisableAutoCommitEnglishMask |= AUTO_COMMIT_ENGLISH_OFF;
preferenceDictionary = EngineState.PREFERENCE_DICTIONARY_EMAIL_ADDRESS_URI;
break;
case EditorInfo.TYPE_TEXT_VARIATION_POSTAL_ADDRESS:
preferenceDictionary = EngineState.PREFERENCE_DICTIONARY_POSTAL_ADDRESS;
break;
case EditorInfo.TYPE_TEXT_VARIATION_PHONETIC:
mEnableLearning = false;
mEnableConverter = false;
mEnableSymbolList = false;
break;
default:
break;
}
break;
default:
break;
}
if (mFilter.filter == 0) {
mConverterEN.setFilter(null);
mConverterJAJP.setFilter(null);
} else {
mConverterEN.setFilter(mFilter);
mConverterJAJP.setFilter(mFilter);
}
EngineState state = new EngineState();
state.preferenceDictionary = preferenceDictionary;
state.convertType = EngineState.CONVERT_TYPE_NONE;
state.keyboard = mEngineState.keyboard;
updateEngineState(state);
updateMetaKeyStateDisplay();
if (!OpenWnn.isXLarge()) {
checkTutorial(info.privateImeOptions);
}
}
/**
* Append a {@link StrSegment} to the composing text
* <br>
* If the length of the composing text exceeds
* {@code LIMIT_INPUT_NUMBER}, the appending operation is ignored.
*
* @param str Input segment
*/
private void appendStrSegment(StrSegment str) {
ComposingText composingText = mComposingText;
if (composingText.size(ComposingText.LAYER1) >= LIMIT_INPUT_NUMBER) {
return; /* do nothing */
}
composingText.insertStrSegment(ComposingText.LAYER0, ComposingText.LAYER1, str);
return;
}
/**
* Commit the consecutive clause conversion.
*/
private void commitConvertingText() {
if (mEngineState.isConvertState()) {
int size = mComposingText.size(ComposingText.LAYER2);
for (int i = 0; i < size; i++) {
learnWord(i);
}
String text = mComposingText.toString(ComposingText.LAYER2);
mInputConnection.commitText(text, (FIX_CURSOR_TEXT_END ? 1 : text.length()));
mPrevCommitText.append(text);
mPrevCommitCount++;
initializeScreen();
}
}
/**
* Initialize the screen displayed by IME
*/
private void initializeScreen() {
if (mComposingText.size(ComposingText.LAYER0) != 0) {
mInputConnection.setComposingText("", 0);
}
mComposingText.clear();
mExactMatchMode = false;
mStatus = STATUS_INIT;
mHandler.removeMessages(MSG_PREDICTION);
View candidateView = mCandidatesViewManager.getCurrentView();
if ((candidateView != null) && candidateView.isShown()) {
mCandidatesViewManager.clearCandidates();
}
mInputViewManager.onUpdateState(this);
EngineState state = new EngineState();
state.temporaryMode = EngineState.TEMPORARY_DICTIONARY_MODE_NONE;
updateEngineState(state);
}
/**
* Whether the tail of the string is alphabet or not.
*
* @param str The string
* @return {@code true} if the tail is alphabet; {@code false} if otherwise.
*/
private boolean isAlphabetLast(String str) {
Matcher m = ENGLISH_CHARACTER_LAST.matcher(str);
return m.matches();
}
/** @see jp.co.omronsoft.openwnn.OpenWnn#onFinishInput */
@Override public void onFinishInput() {
if (mInputConnection != null) {
initializeScreen();
}
super.onFinishInput();
}
/**
* Check whether or not the converter is active.
*
* @return {@code true} if the converter is active.
*/
private boolean isEnableL2Converter() {
if (mConverter == null || !mEnableConverter) {
return false;
}
if (mEngineState.isEnglish() && !mEnablePrediction) {
return false;
}
return true;
}
/**
* Handling KeyEvent(KEYUP)
* <br>
* This method is called from {@link #onEvent()}.
*
* @param ev An up key event
*/
private void onKeyUpEvent(KeyEvent ev) {
int key = ev.getKeyCode();
if(!mShiftPressing){
if(key == KeyEvent.KEYCODE_SHIFT_LEFT || key == KeyEvent.KEYCODE_SHIFT_RIGHT){
mHardShift = 0;
mShiftPressing = true;
updateMetaKeyStateDisplay();
}
}
if(!mAltPressing ){
if(key == KeyEvent.KEYCODE_ALT_LEFT || key == KeyEvent.KEYCODE_ALT_RIGHT){
mHardAlt = 0;
mAltPressing = true;
updateMetaKeyStateDisplay();
}
}
if (mEnableHardware12Keyboard && !mDirectInputMode) {
if (isHardKeyboard12KeyLongPress(key)
&& ((ev.getFlags() & KeyEvent.FLAG_CANCELED_LONG_PRESS) == 0)) {
switch (key) {
case KeyEvent.KEYCODE_SOFT_LEFT:
if (mEngineState.isSymbolList()) {
switchSymbolList();
} else if ((mComposingText.size(0) != 0) && !mEngineState.isRenbun()
&& (((DefaultSoftKeyboardJAJP)mInputViewManager).getKeyMode()
== DefaultSoftKeyboardJAJP.KEYMODE_JA_FULL_HIRAGANA)) {
startConvert(EngineState.CONVERT_TYPE_RENBUN);
} else {
((DefaultSoftKeyboard) mInputViewManager).onKey(
DefaultSoftKeyboard.KEYCODE_JP12_EMOJI, null);
}
break;
case KeyEvent.KEYCODE_SOFT_RIGHT:
((DefaultSoftKeyboardJAJP) mInputViewManager).showInputModeSwitchDialog();
break;
case KeyEvent.KEYCODE_DEL:
int newKeyCode = KeyEvent.KEYCODE_FORWARD_DEL;
int composingTextSize = mComposingText.size(ComposingText.LAYER1);
if (composingTextSize > 0) {
if (mComposingText.getCursor(ComposingText.LAYER1) > (composingTextSize - 1)) {
newKeyCode = KeyEvent.KEYCODE_DEL;
}
KeyEvent keyEvent = new KeyEvent(ev.getAction(), newKeyCode);
if (!processKeyEvent(keyEvent)) {
sendDownUpKeyEvents(keyEvent.getKeyCode());
}
} else {
if (mInputConnection != null) {
CharSequence text = mInputConnection.getTextAfterCursor(1, 0);
if ((text == null) || (text.length() == 0)) {
newKeyCode = KeyEvent.KEYCODE_DEL;
}
}
sendDownUpKeyEvents(newKeyCode);
}
break;
default:
break;
}
}
}
}
/**
* Handling KeyEvent(KEYLONGPRESS)
* <br>
* This method is called from {@link #handleEvent}.
*
* @param ev An long press key event
* @return {@code true} if the event is processed in this method; {@code false} if not.
*/
private boolean onKeyLongPressEvent(KeyEvent ev) {
if (mEnableHardware12Keyboard) {
int keyCode = 0;
if (ev != null) {
keyCode = ev.getKeyCode();
}
switch (keyCode) {
case KeyEvent.KEYCODE_DEL:
initializeScreen();
if (mInputConnection != null) {
mInputConnection.deleteSurroundingText(Integer.MAX_VALUE, Integer.MAX_VALUE);
}
return true;
default:
break;
}
}
return false;
}
/**
* Initialize the committed text's information.
*/
private void initCommitInfoForWatchCursor() {
if (!isEnableL2Converter()) {
return;
}
mCommitStartCursor = mComposingStartCursor;
mPrevCommitText.delete(0, mPrevCommitText.length());
}
/**
* Clear the commit text's info.
* @return {@code true}:cleared, {@code false}:has already cleared.
*/
private boolean clearCommitInfo() {
if (mCommitStartCursor < 0) {
return false;
}
mCommitStartCursor = -1;
return true;
}
/**
* Verify the commit text.
*/
private void checkCommitInfo() {
if (mCommitStartCursor < 0) {
return;
}
int composingLength = mComposingText.toString(mTargetLayer).length();
CharSequence seq = mInputConnection.getTextBeforeCursor(mPrevCommitText.length() + composingLength, 0);
seq = seq.subSequence(0, seq.length() - composingLength);
if (!seq.equals(mPrevCommitText.toString())) {
mPrevCommitCount = 0;
clearCommitInfo();
}
}
/**
* Check and start the tutorial if it is the tutorial mode.
*
* @param privateImeOptions IME's options
*/
private void checkTutorial(String privateImeOptions) {
if (privateImeOptions == null) return;
if (privateImeOptions.equals("com.google.android.setupwizard:ShowTutorial")) {
if ((mTutorial == null) && mEnableTutorial) startTutorial();
} else if (privateImeOptions.equals("com.google.android.setupwizard:HideTutorial")) {
if (mTutorial != null) {
if (mTutorial.close()) {
mTutorial = null;
}
}
}
}
/**
* Start the tutorial
*/
private void startTutorial() {
DefaultSoftKeyboardJAJP manager = (DefaultSoftKeyboardJAJP) mInputViewManager;
manager.setDefaultKeyboard();
if (mEngineState.keyboard == EngineState.KEYBOARD_QWERTY) {
manager.changeKeyboardType(DefaultSoftKeyboard.KEYBOARD_12KEY);
}
DefaultSoftKeyboardJAJP inputManager = ((DefaultSoftKeyboardJAJP) mInputViewManager);
View v = inputManager.getKeyboardView();
v.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
return true;
}});
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_START_TUTORIAL), 500);
}
/**
* Close the tutorial
*/
public void tutorialDone() {
mTutorial = null;
}
/** @see OpenWnn#close */
@Override protected void close() {
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CLOSE), 0);
}
/**
* Break the sequence of words.
*/
private void breakSequence() {
mEnableAutoDeleteSpace = false;
mConverterJAJP.breakSequence();
mConverterEN.breakSequence();
}
/**
* Switch symbol list.
*/
private void switchSymbolList(){
changeSymbolEngineState(new EngineState(), ENGINE_MODE_SYMBOL);
mHardAlt = 0;
updateMetaKeyStateDisplay();
}
/**
* Change symbol engine state.
*
* @param state Engine state
* @param mode Engine mode
*/
private void changeSymbolEngineState(EngineState state, int mode) {
state.temporaryMode = EngineState.TEMPORARY_DICTIONARY_MODE_SYMBOL;
updateEngineState(state);
}
/**
* Set enable tabs.
*
* @param enableEmoticon {@code true} - Emoticon is enabled.
* {@code false} - Emoticon is disabled.
*/
private void setEnabledTabs(boolean enableEmoticon) {
mTextCandidatesViewManager.setEnableEmoticon(enableEmoticon);
}
/**
* Is enable hard keyboard 12Key long press keycode.
*
* @param keyCode keycode.
* @return {@code true} if enable long press keycode; {@code false} if not.
*/
private boolean isHardKeyboard12KeyLongPress(int keyCode) {
boolean isLongPress = false;
switch (keyCode) {
case KeyEvent.KEYCODE_SOFT_LEFT:
case KeyEvent.KEYCODE_SOFT_RIGHT:
case KeyEvent.KEYCODE_DEL:
isLongPress = true;
break;
default:
break;
}
return isLongPress;
}
/**
* Key event handler for hardware 12Keyboard.
*
* @param keyEvent A key event
* @return {@code true} if the event is handled in this method.
*/
private boolean processHardware12Keyboard(KeyEvent keyEvent) {
boolean ret = false;
if (mEnableHardware12Keyboard && (keyEvent != null)) {
int keyCode = keyEvent.getKeyCode();
if (isHardKeyboard12KeyLongPress(keyCode)) {
if (keyEvent.getRepeatCount() == 0) {
keyEvent.startTracking();
}
ret = true;
} else {
Integer code = HW12KEYBOARD_KEYCODE_REPLACE_TABLE.get(keyCode);
if (code != null) {
if (keyEvent.getRepeatCount() == 0) {
((DefaultSoftKeyboard) mInputViewManager).onKey(code.intValue(), null);
}
ret = true;
}
}
}
return ret;
}
}