1/*
2 * Copyright (C) 2008-2012  OMRON SOFTWARE Co., Ltd.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package jp.co.omronsoft.openwnn.JAJP;
18
19import android.app.AlertDialog;
20import jp.co.omronsoft.openwnn.*;
21import android.content.DialogInterface;
22import android.content.res.Resources;
23import android.view.KeyEvent;
24import android.view.inputmethod.EditorInfo;
25import android.view.inputmethod.InputConnection;
26import android.util.Log;
27import android.view.View;
28import android.content.SharedPreferences;
29
30import jp.co.omronsoft.openwnn.Keyboard;
31import jp.co.omronsoft.openwnn.BaseInputView;
32import jp.co.omronsoft.openwnn.R;
33
34import java.util.HashMap;
35import java.util.Locale;
36import java.util.List;
37
38/**
39 * The default Software Keyboard class for Japanese IME.
40 *
41 * @author Copyright (C) 2009 OMRON SOFTWARE CO., LTD.  All Rights Reserved.
42 */
43public class DefaultSoftKeyboardJAJP extends DefaultSoftKeyboard {
44    /** Enable English word prediction on half-width alphabet mode */
45    private static final boolean USE_ENGLISH_PREDICT = true;
46
47    /** Key code for switching to full-width HIRAGANA mode */
48    private static final int KEYCODE_SWITCH_FULL_HIRAGANA = -301;
49
50    /** Key code for switching to full-width KATAKANA mode */
51    private static final int KEYCODE_SWITCH_FULL_KATAKANA = -302;
52
53    /** Key code for switching to full-width alphabet mode */
54    private static final int KEYCODE_SWITCH_FULL_ALPHABET = -303;
55
56    /** Key code for switching to full-width number mode */
57    private static final int KEYCODE_SWITCH_FULL_NUMBER = -304;
58
59    /** Key code for switching to half-width KATAKANA mode */
60    private static final int KEYCODE_SWITCH_HALF_KATAKANA = -306;
61
62    /** Key code for switching to half-width alphabet mode */
63    private static final int KEYCODE_SWITCH_HALF_ALPHABET = -307;
64
65    /** Key code for switching to half-width number mode */
66    private static final int KEYCODE_SWITCH_HALF_NUMBER = -308;
67
68    /** Key code for case toggle key */
69    private static final int KEYCODE_SELECT_CASE = -309;
70
71    /** Key code for EISU-KANA conversion */
72    private static final int KEYCODE_EISU_KANA = -305;
73
74    /** Key code for NOP (no-operation) */
75    private static final int KEYCODE_NOP = -310;
76
77
78    /** Input mode toggle cycle table */
79    private static final int[] JP_MODE_CYCLE_TABLE = {
80        KEYMODE_JA_FULL_HIRAGANA, KEYMODE_JA_HALF_ALPHABET, KEYMODE_JA_HALF_NUMBER
81    };
82
83    /** Definition for {@code mInputType} (toggle) */
84    private static final int INPUT_TYPE_TOGGLE = 1;
85
86    /** Definition for {@code mInputType} (commit instantly) */
87    private static final int INPUT_TYPE_INSTANT = 2;
88
89    /** Max key number of the 12 key keyboard (depends on the definition of keyboards) */
90    private static final int KEY_NUMBER_12KEY = 20;
91
92    /** Toggle cycle table for full-width HIRAGANA */
93    private static final String[][] JP_FULL_HIRAGANA_CYCLE_TABLE = {
94        {"\u3042", "\u3044", "\u3046", "\u3048", "\u304a", "\u3041", "\u3043", "\u3045", "\u3047", "\u3049"},
95        {"\u304b", "\u304d", "\u304f", "\u3051", "\u3053"},
96        {"\u3055", "\u3057", "\u3059", "\u305b", "\u305d"},
97        {"\u305f", "\u3061", "\u3064", "\u3066", "\u3068", "\u3063"},
98        {"\u306a", "\u306b", "\u306c", "\u306d", "\u306e"},
99        {"\u306f", "\u3072", "\u3075", "\u3078", "\u307b"},
100        {"\u307e", "\u307f", "\u3080", "\u3081", "\u3082"},
101        {"\u3084", "\u3086", "\u3088", "\u3083", "\u3085", "\u3087"},
102        {"\u3089", "\u308a", "\u308b", "\u308c", "\u308d"},
103        {"\u308f", "\u3092", "\u3093", "\u308e", "\u30fc"},
104        {"\u3001", "\u3002", "\uff1f", "\uff01", "\u30fb", "\u3000"},
105    };
106
107    /** Replace table for full-width HIRAGANA */
108    private static final HashMap<String, String> JP_FULL_HIRAGANA_REPLACE_TABLE = new HashMap<String, String>() {{
109          put("\u3042", "\u3041"); put("\u3044", "\u3043"); put("\u3046", "\u3045"); put("\u3048", "\u3047"); put("\u304a", "\u3049");
110          put("\u3041", "\u3042"); put("\u3043", "\u3044"); put("\u3045", "\u30f4"); put("\u3047", "\u3048"); put("\u3049", "\u304a");
111          put("\u304b", "\u304c"); put("\u304d", "\u304e"); put("\u304f", "\u3050"); put("\u3051", "\u3052"); put("\u3053", "\u3054");
112          put("\u304c", "\u304b"); put("\u304e", "\u304d"); put("\u3050", "\u304f"); put("\u3052", "\u3051"); put("\u3054", "\u3053");
113          put("\u3055", "\u3056"); put("\u3057", "\u3058"); put("\u3059", "\u305a"); put("\u305b", "\u305c"); put("\u305d", "\u305e");
114          put("\u3056", "\u3055"); put("\u3058", "\u3057"); put("\u305a", "\u3059"); put("\u305c", "\u305b"); put("\u305e", "\u305d");
115          put("\u305f", "\u3060"); put("\u3061", "\u3062"); put("\u3064", "\u3063"); put("\u3066", "\u3067"); put("\u3068", "\u3069");
116          put("\u3060", "\u305f"); put("\u3062", "\u3061"); put("\u3063", "\u3065"); put("\u3067", "\u3066"); put("\u3069", "\u3068");
117          put("\u3065", "\u3064"); put("\u30f4", "\u3046");
118          put("\u306f", "\u3070"); put("\u3072", "\u3073"); put("\u3075", "\u3076"); put("\u3078", "\u3079"); put("\u307b", "\u307c");
119          put("\u3070", "\u3071"); put("\u3073", "\u3074"); put("\u3076", "\u3077"); put("\u3079", "\u307a"); put("\u307c", "\u307d");
120          put("\u3071", "\u306f"); put("\u3074", "\u3072"); put("\u3077", "\u3075"); put("\u307a", "\u3078"); put("\u307d", "\u307b");
121          put("\u3084", "\u3083"); put("\u3086", "\u3085"); put("\u3088", "\u3087");
122          put("\u3083", "\u3084"); put("\u3085", "\u3086"); put("\u3087", "\u3088");
123          put("\u308f", "\u308e");
124          put("\u308e", "\u308f");
125          put("\u309b", "\u309c");
126          put("\u309c", "\u309b");
127    }};
128
129    /** Toggle cycle table for full-width KATAKANA */
130    private static final String[][] JP_FULL_KATAKANA_CYCLE_TABLE = {
131        {"\u30a2", "\u30a4", "\u30a6", "\u30a8", "\u30aa", "\u30a1", "\u30a3",
132         "\u30a5", "\u30a7", "\u30a9"},
133        {"\u30ab", "\u30ad", "\u30af", "\u30b1", "\u30b3"},
134        {"\u30b5", "\u30b7", "\u30b9", "\u30bb", "\u30bd"},
135        {"\u30bf", "\u30c1", "\u30c4", "\u30c6", "\u30c8", "\u30c3"},
136        {"\u30ca", "\u30cb", "\u30cc", "\u30cd", "\u30ce"},
137        {"\u30cf", "\u30d2", "\u30d5", "\u30d8", "\u30db"},
138        {"\u30de", "\u30df", "\u30e0", "\u30e1", "\u30e2"},
139        {"\u30e4", "\u30e6", "\u30e8", "\u30e3", "\u30e5", "\u30e7"},
140        {"\u30e9", "\u30ea", "\u30eb", "\u30ec", "\u30ed"},
141        {"\u30ef", "\u30f2", "\u30f3", "\u30ee", "\u30fc"},
142        {"\u3001", "\u3002", "\uff1f", "\uff01", "\u30fb", "\u3000"}
143    };
144
145    /** Replace table for full-width KATAKANA */
146    private static final HashMap<String,String> JP_FULL_KATAKANA_REPLACE_TABLE = new HashMap<String,String>() {{
147        put("\u30a2", "\u30a1"); put("\u30a4", "\u30a3"); put("\u30a6", "\u30a5"); put("\u30a8", "\u30a7"); put("\u30aa", "\u30a9");
148        put("\u30a1", "\u30a2"); put("\u30a3", "\u30a4"); put("\u30a5", "\u30f4"); put("\u30a7", "\u30a8"); put("\u30a9", "\u30aa");
149        put("\u30ab", "\u30ac"); put("\u30ad", "\u30ae"); put("\u30af", "\u30b0"); put("\u30b1", "\u30b2"); put("\u30b3", "\u30b4");
150        put("\u30ac", "\u30ab"); put("\u30ae", "\u30ad"); put("\u30b0", "\u30af"); put("\u30b2", "\u30b1"); put("\u30b4", "\u30b3");
151        put("\u30b5", "\u30b6"); put("\u30b7", "\u30b8"); put("\u30b9", "\u30ba"); put("\u30bb", "\u30bc"); put("\u30bd", "\u30be");
152        put("\u30b6", "\u30b5"); put("\u30b8", "\u30b7"); put("\u30ba", "\u30b9"); put("\u30bc", "\u30bb"); put("\u30be", "\u30bd");
153        put("\u30bf", "\u30c0"); put("\u30c1", "\u30c2"); put("\u30c4", "\u30c3"); put("\u30c6", "\u30c7"); put("\u30c8", "\u30c9");
154        put("\u30c0", "\u30bf"); put("\u30c2", "\u30c1"); put("\u30c3", "\u30c5"); put("\u30c7", "\u30c6"); put("\u30c9", "\u30c8");
155        put("\u30c5", "\u30c4"); put("\u30f4", "\u30a6");
156        put("\u30cf", "\u30d0"); put("\u30d2", "\u30d3"); put("\u30d5", "\u30d6"); put("\u30d8", "\u30d9"); put("\u30db", "\u30dc");
157        put("\u30d0", "\u30d1"); put("\u30d3", "\u30d4"); put("\u30d6", "\u30d7"); put("\u30d9", "\u30da"); put("\u30dc", "\u30dd");
158        put("\u30d1", "\u30cf"); put("\u30d4", "\u30d2"); put("\u30d7", "\u30d5"); put("\u30da", "\u30d8"); put("\u30dd", "\u30db");
159        put("\u30e4", "\u30e3"); put("\u30e6", "\u30e5"); put("\u30e8", "\u30e7");
160        put("\u30e3", "\u30e4"); put("\u30e5", "\u30e6"); put("\u30e7", "\u30e8");
161        put("\u30ef", "\u30ee");
162        put("\u30ee", "\u30ef");
163    }};
164
165    /** Toggle cycle table for half-width KATAKANA */
166    private static final String[][] JP_HALF_KATAKANA_CYCLE_TABLE = {
167        {"\uff71", "\uff72", "\uff73", "\uff74", "\uff75", "\uff67", "\uff68", "\uff69", "\uff6a", "\uff6b"},
168        {"\uff76", "\uff77", "\uff78", "\uff79", "\uff7a"},
169        {"\uff7b", "\uff7c", "\uff7d", "\uff7e", "\uff7f"},
170        {"\uff80", "\uff81", "\uff82", "\uff83", "\uff84", "\uff6f"},
171        {"\uff85", "\uff86", "\uff87", "\uff88", "\uff89"},
172        {"\uff8a", "\uff8b", "\uff8c", "\uff8d", "\uff8e"},
173        {"\uff8f", "\uff90", "\uff91", "\uff92", "\uff93"},
174        {"\uff94", "\uff95", "\uff96", "\uff6c", "\uff6d", "\uff6e"},
175        {"\uff97", "\uff98", "\uff99", "\uff9a", "\uff9b"},
176        {"\uff9c", "\uff66", "\uff9d", "\uff70"},
177        {"\uff64", "\uff61", "?", "!", "\uff65", " "},
178    };
179
180    /** Replace table for half-width KATAKANA */
181    private static final HashMap<String,String> JP_HALF_KATAKANA_REPLACE_TABLE = new HashMap<String,String>() {{
182        put("\uff71", "\uff67");  put("\uff72", "\uff68");  put("\uff73", "\uff69");  put("\uff74", "\uff6a");  put("\uff75", "\uff6b");
183        put("\uff67", "\uff71");  put("\uff68", "\uff72");  put("\uff69", "\uff73\uff9e");  put("\uff6a", "\uff74");  put("\uff6b", "\uff75");
184        put("\uff76", "\uff76\uff9e"); put("\uff77", "\uff77\uff9e"); put("\uff78", "\uff78\uff9e"); put("\uff79", "\uff79\uff9e"); put("\uff7a", "\uff7a\uff9e");
185        put("\uff76\uff9e", "\uff76"); put("\uff77\uff9e", "\uff77"); put("\uff78\uff9e", "\uff78"); put("\uff79\uff9e", "\uff79"); put("\uff7a\uff9e", "\uff7a");
186        put("\uff7b", "\uff7b\uff9e"); put("\uff7c", "\uff7c\uff9e"); put("\uff7d", "\uff7d\uff9e"); put("\uff7e", "\uff7e\uff9e"); put("\uff7f", "\uff7f\uff9e");
187        put("\uff7b\uff9e", "\uff7b"); put("\uff7c\uff9e", "\uff7c"); put("\uff7d\uff9e", "\uff7d"); put("\uff7e\uff9e", "\uff7e"); put("\uff7f\uff9e", "\uff7f");
188        put("\uff80", "\uff80\uff9e"); put("\uff81", "\uff81\uff9e"); put("\uff82", "\uff6f");  put("\uff83", "\uff83\uff9e"); put("\uff84", "\uff84\uff9e");
189        put("\uff80\uff9e", "\uff80"); put("\uff81\uff9e", "\uff81"); put("\uff6f", "\uff82\uff9e"); put("\uff83\uff9e", "\uff83"); put("\uff84\uff9e", "\uff84");
190        put("\uff82\uff9e", "\uff82");
191        put("\uff8a", "\uff8a\uff9e"); put("\uff8b", "\uff8b\uff9e"); put("\uff8c", "\uff8c\uff9e"); put("\uff8d", "\uff8d\uff9e"); put("\uff8e", "\uff8e\uff9e");
192        put("\uff8a\uff9e", "\uff8a\uff9f");put("\uff8b\uff9e", "\uff8b\uff9f");put("\uff8c\uff9e", "\uff8c\uff9f");put("\uff8d\uff9e", "\uff8d\uff9f");put("\uff8e\uff9e", "\uff8e\uff9f");
193        put("\uff8a\uff9f", "\uff8a"); put("\uff8b\uff9f", "\uff8b"); put("\uff8c\uff9f", "\uff8c"); put("\uff8d\uff9f", "\uff8d"); put("\uff8e\uff9f", "\uff8e");
194        put("\uff94", "\uff6c");  put("\uff95", "\uff6d");  put("\uff96", "\uff6e");
195        put("\uff6c", "\uff94");  put("\uff6d", "\uff95");  put("\uff6e", "\uff96");
196        put("\uff9c", "\uff9c"); put("\uff73\uff9e", "\uff73");
197    }};
198
199    /** Toggle cycle table for full-width alphabet */
200    private static final String[][] JP_FULL_ALPHABET_CYCLE_TABLE = {
201        {"\uff0e", "\uff20", "\uff0d", "\uff3f", "\uff0f", "\uff1a", "\uff5e", "\uff11"},
202        {"\uff41", "\uff42", "\uff43", "\uff21", "\uff22", "\uff23", "\uff12"},
203        {"\uff44", "\uff45", "\uff46", "\uff24", "\uff25", "\uff26", "\uff13"},
204        {"\uff47", "\uff48", "\uff49", "\uff27", "\uff28", "\uff29", "\uff14"},
205        {"\uff4a", "\uff4b", "\uff4c", "\uff2a", "\uff2b", "\uff2c", "\uff15"},
206        {"\uff4d", "\uff4e", "\uff4f", "\uff2d", "\uff2e", "\uff2f", "\uff16"},
207        {"\uff50", "\uff51", "\uff52", "\uff53", "\uff30", "\uff31", "\uff32", "\uff33", "\uff17"},
208        {"\uff54", "\uff55", "\uff56", "\uff34", "\uff35", "\uff36", "\uff18"},
209        {"\uff57", "\uff58", "\uff59", "\uff5a", "\uff37", "\uff38", "\uff39", "\uff3a", "\uff19"},
210        {"\uff0d", "\uff10"},
211        {"\uff0c", "\uff0e", "\uff1f", "\uff01", "\u30fb", "\u3000"}
212    };
213
214    /** Replace table for full-width alphabet */
215    private static final HashMap<String,String> JP_FULL_ALPHABET_REPLACE_TABLE = new HashMap<String,String>() {{
216        put("\uff21", "\uff41"); put("\uff22", "\uff42"); put("\uff23", "\uff43"); put("\uff24", "\uff44"); put("\uff25", "\uff45");
217        put("\uff41", "\uff21"); put("\uff42", "\uff22"); put("\uff43", "\uff23"); put("\uff44", "\uff24"); put("\uff45", "\uff25");
218        put("\uff26", "\uff46"); put("\uff27", "\uff47"); put("\uff28", "\uff48"); put("\uff29", "\uff49"); put("\uff2a", "\uff4a");
219        put("\uff46", "\uff26"); put("\uff47", "\uff27"); put("\uff48", "\uff28"); put("\uff49", "\uff29"); put("\uff4a", "\uff2a");
220        put("\uff2b", "\uff4b"); put("\uff2c", "\uff4c"); put("\uff2d", "\uff4d"); put("\uff2e", "\uff4e"); put("\uff2f", "\uff4f");
221        put("\uff4b", "\uff2b"); put("\uff4c", "\uff2c"); put("\uff4d", "\uff2d"); put("\uff4e", "\uff2e"); put("\uff4f", "\uff2f");
222        put("\uff30", "\uff50"); put("\uff31", "\uff51"); put("\uff32", "\uff52"); put("\uff33", "\uff53"); put("\uff34", "\uff54");
223        put("\uff50", "\uff30"); put("\uff51", "\uff31"); put("\uff52", "\uff32"); put("\uff53", "\uff33"); put("\uff54", "\uff34");
224        put("\uff35", "\uff55"); put("\uff36", "\uff56"); put("\uff37", "\uff57"); put("\uff38", "\uff58"); put("\uff39", "\uff59");
225        put("\uff55", "\uff35"); put("\uff56", "\uff36"); put("\uff57", "\uff37"); put("\uff58", "\uff38"); put("\uff59", "\uff39");
226        put("\uff3a", "\uff5a");
227        put("\uff5a", "\uff3a");
228    }};
229
230    /** Toggle cycle table for half-width alphabet */
231    private static final String[][] JP_HALF_ALPHABET_CYCLE_TABLE = {
232        {".", "@", "-", "_", "/", ":", "~", "1"},
233        {"a", "b", "c", "A", "B", "C", "2"},
234        {"d", "e", "f", "D", "E", "F", "3"},
235        {"g", "h", "i", "G", "H", "I", "4"},
236        {"j", "k", "l", "J", "K", "L", "5"},
237        {"m", "n", "o", "M", "N", "O", "6"},
238        {"p", "q", "r", "s", "P", "Q", "R", "S", "7"},
239        {"t", "u", "v", "T", "U", "V", "8"},
240        {"w", "x", "y", "z", "W", "X", "Y", "Z", "9"},
241        {"-", "0"},
242        {",", ".", "?", "!", ";", " "}
243    };
244
245    /** Replace table for half-width alphabet */
246    private static final HashMap<String,String> JP_HALF_ALPHABET_REPLACE_TABLE = new HashMap<String,String>() {{
247        put("A", "a"); put("B", "b"); put("C", "c"); put("D", "d"); put("E", "e");
248        put("a", "A"); put("b", "B"); put("c", "C"); put("d", "D"); put("e", "E");
249        put("F", "f"); put("G", "g"); put("H", "h"); put("I", "i"); put("J", "j");
250        put("f", "F"); put("g", "G"); put("h", "H"); put("i", "I"); put("j", "J");
251        put("K", "k"); put("L", "l"); put("M", "m"); put("N", "n"); put("O", "o");
252        put("k", "K"); put("l", "L"); put("m", "M"); put("n", "N"); put("o", "O");
253        put("P", "p"); put("Q", "q"); put("R", "r"); put("S", "s"); put("T", "t");
254        put("p", "P"); put("q", "Q"); put("r", "R"); put("s", "S"); put("t", "T");
255        put("U", "u"); put("V", "v"); put("W", "w"); put("X", "x"); put("Y", "y");
256        put("u", "U"); put("v", "V"); put("w", "W"); put("x", "X"); put("y", "Y");
257        put("Z", "z");
258        put("z", "Z");
259    }};
260
261    /** Character table for full-width number */
262    private static final char[] INSTANT_CHAR_CODE_FULL_NUMBER =
263        "\uff11\uff12\uff13\uff14\uff15\uff16\uff17\uff18\uff19\uff10\uff03\uff0a".toCharArray();
264
265    /** Character table for half-width number */
266    private static final char[] INSTANT_CHAR_CODE_HALF_NUMBER =
267        "1234567890#*".toCharArray();
268
269    /** The constant for mFixedKeyMode. It means that input mode is not fixed. */
270    private static final int INVALID_KEYMODE = -1;
271
272    /** KeyIndex of "Moji" key on 12 keyboard (depends on the definition of keyboards) */
273    private static final int KEY_INDEX_CHANGE_MODE_12KEY = 15;
274
275    /** KeyIndex of "Moji" key on QWERTY keyboard (depends on the definition of keyboards) */
276    private static final int KEY_INDEX_CHANGE_MODE_QWERTY = 29;
277
278    /** Type of input mode */
279    private int mInputType = INPUT_TYPE_TOGGLE;
280
281    /** Previous input character code */
282    private int mPrevInputKeyCode = 0;
283
284    /**
285     * Character table to input when mInputType becomes INPUT_TYPE_INSTANT.
286     * (Either INSTANT_CHAR_CODE_FULL_NUMBER or INSTANT_CHAR_CODE_HALF_NUMBER)
287     */
288    private char[] mCurrentInstantTable = null;
289
290    /** Input mode that is not able to be changed. If ENABLE_CHANGE_KEYMODE is set, input mode can change. */
291    private int[] mLimitedKeyMode = null;
292
293    /** Input mode that is given the first priority. If ENABLE_CHANGE_KEYMODE is set, input mode can change. */
294    private int mPreferenceKeyMode = INVALID_KEYMODE;
295
296    /** The last input type */
297    private int mLastInputType = 0;
298
299    /** Auto caps mode */
300    private boolean mEnableAutoCaps = true;
301
302    /** PopupResId of "Moji" key (this is used for canceling long-press) */
303    private int mPopupResId = 0;
304
305    /** Whether the InputType is null */
306    private boolean mIsInputTypeNull = false;
307
308    /** {@code SharedPreferences} for save the keyboard type */
309    private SharedPreferences.Editor mPrefEditor = null;
310
311    /** "Moji" key (this is used for canceling long-press) */
312    private Keyboard.Key mChangeModeKey = null;
313
314
315    /** Default constructor */
316    public DefaultSoftKeyboardJAJP() {
317        mCurrentLanguage     = LANG_JA;
318        if (OpenWnn.isXLarge()) {
319            mCurrentKeyboardType = KEYBOARD_QWERTY;
320        } else {
321            mCurrentKeyboardType = KEYBOARD_12KEY;
322        }
323        mShiftOn             = KEYBOARD_SHIFT_OFF;
324        mCurrentKeyMode      = KEYMODE_JA_FULL_HIRAGANA;
325    }
326
327    /** @see jp.co.omronsoft.openwnn.DefaultSoftKeyboard#createKeyboards */
328    @Override protected void createKeyboards(OpenWnn parent) {
329
330        /* Keyboard[# of Languages][portrait/landscape][# of keyboard type][shift off/on][max # of key-modes][noinput/input] */
331        mKeyboard = new Keyboard[3][2][4][2][8][2];
332
333        if (mHardKeyboardHidden) {
334            /* Create the suitable keyboard object */
335            if (mDisplayMode == DefaultSoftKeyboard.PORTRAIT) {
336                createKeyboardsPortrait(parent);
337            } else {
338                createKeyboardsLandscape(parent);
339            }
340
341            if (mCurrentKeyboardType == KEYBOARD_12KEY) {
342                mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.CHANGE_MODE,
343                                              OpenWnnJAJP.ENGINE_MODE_OPT_TYPE_12KEY));
344            } else {
345                mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.CHANGE_MODE,
346                                              OpenWnnJAJP.ENGINE_MODE_OPT_TYPE_QWERTY));
347            }
348        } else if (mEnableHardware12Keyboard) {
349            mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.CHANGE_MODE,
350                                          OpenWnnJAJP.ENGINE_MODE_OPT_TYPE_12KEY));
351        } else {
352            mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.CHANGE_MODE,
353                                          OpenWnnJAJP.ENGINE_MODE_OPT_TYPE_QWERTY));
354        }
355    }
356
357    /**
358     * Commit the pre-edit string for committing operation that is not explicit
359     * (ex. when a candidate is selected)
360     */
361    private void commitText() {
362        if (!mNoInput) {
363            mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.COMMIT_COMPOSING_TEXT));
364        }
365    }
366
367    /**
368     * Change input mode
369     * <br>
370     * @param keyMode   The type of input mode
371     */
372    public void changeKeyMode(int keyMode) {
373        int targetMode = filterKeyMode(keyMode);
374        if (targetMode == INVALID_KEYMODE) {
375            return;
376        }
377
378        commitText();
379
380        if (mCapsLock) {
381            mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.INPUT_SOFT_KEY,
382                                          new KeyEvent(KeyEvent.ACTION_UP,
383                                                       KeyEvent.KEYCODE_SHIFT_LEFT)));
384            mCapsLock = false;
385        }
386        mShiftOn = KEYBOARD_SHIFT_OFF;
387        Keyboard kbd = getModeChangeKeyboard(targetMode);
388        mCurrentKeyMode = targetMode;
389        mPrevInputKeyCode = 0;
390
391        int mode = OpenWnnEvent.Mode.DIRECT;
392
393        switch (targetMode) {
394        case KEYMODE_JA_FULL_HIRAGANA:
395            mInputType = INPUT_TYPE_TOGGLE;
396            mode = OpenWnnEvent.Mode.DEFAULT;
397            break;
398
399        case KEYMODE_JA_HALF_ALPHABET:
400            if (USE_ENGLISH_PREDICT) {
401                mInputType = INPUT_TYPE_TOGGLE;
402                mode = OpenWnnEvent.Mode.NO_LV1_CONV;
403            } else {
404                mInputType = INPUT_TYPE_TOGGLE;
405                mode = OpenWnnEvent.Mode.DIRECT;
406            }
407            break;
408
409        case KEYMODE_JA_FULL_NUMBER:
410            mInputType = INPUT_TYPE_INSTANT;
411            mode = OpenWnnEvent.Mode.DIRECT;
412            mCurrentInstantTable = INSTANT_CHAR_CODE_FULL_NUMBER;
413            break;
414
415        case KEYMODE_JA_HALF_NUMBER:
416            mInputType = INPUT_TYPE_INSTANT;
417            mode = OpenWnnEvent.Mode.DIRECT;
418            mCurrentInstantTable = INSTANT_CHAR_CODE_HALF_NUMBER;
419            break;
420
421        case KEYMODE_JA_FULL_KATAKANA:
422            mInputType = INPUT_TYPE_TOGGLE;
423            mode = OpenWnnJAJP.ENGINE_MODE_FULL_KATAKANA;
424            break;
425
426        case KEYMODE_JA_FULL_ALPHABET:
427            mInputType = INPUT_TYPE_TOGGLE;
428            mode = OpenWnnEvent.Mode.DIRECT;
429            break;
430
431        case KEYMODE_JA_HALF_KATAKANA:
432            mInputType = INPUT_TYPE_TOGGLE;
433            mode = OpenWnnJAJP.ENGINE_MODE_HALF_KATAKANA;
434            break;
435
436        default:
437            break;
438        }
439
440        setStatusIcon();
441        changeKeyboard(kbd);
442        mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.CHANGE_MODE, mode));
443    }
444
445     /** @see jp.co.omronsoft.openwnn.DefaultSoftKeyboard#initView */
446     @Override public View initView(OpenWnn parent, int width, int height) {
447
448        View view = super.initView(parent, width, height);
449        changeKeyboard(mKeyboard[mCurrentLanguage][mDisplayMode][mCurrentKeyboardType][mShiftOn][mCurrentKeyMode][0]);
450
451        return view;
452     }
453
454    /** @see jp.co.omronsoft.openwnn.DefaultSoftKeyboard#changeKeyboard */
455    @Override protected boolean changeKeyboard(Keyboard keyboard) {
456        if (keyboard != null) {
457            if (mIsInputTypeNull && mChangeModeKey != null) {
458                mChangeModeKey.popupResId = mPopupResId;
459            }
460
461            List<Keyboard.Key> keys = keyboard.getKeys();
462            int keyIndex = (KEY_NUMBER_12KEY < keys.size())
463                ? KEY_INDEX_CHANGE_MODE_QWERTY : KEY_INDEX_CHANGE_MODE_12KEY;
464            mChangeModeKey = keys.get(keyIndex);
465
466            if (mIsInputTypeNull && mChangeModeKey != null) {
467                mPopupResId = mChangeModeKey.popupResId;
468                mChangeModeKey.popupResId = 0;
469            }
470        }
471
472        return super.changeKeyboard(keyboard);
473    }
474
475    /** @see jp.co.omronsoft.openwnn.DefaultSoftKeyboard#changeKeyboardType */
476    @Override public void changeKeyboardType(int type) {
477        commitText();
478        Keyboard kbd = getTypeChangeKeyboard(type);
479        if (kbd != null) {
480            mCurrentKeyboardType = type;
481            mPrefEditor.putBoolean("opt_enable_qwerty", type == KEYBOARD_QWERTY);
482            mPrefEditor.commit();
483            changeKeyboard(kbd);
484        }
485        if (type == KEYBOARD_12KEY) {
486            mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.CHANGE_MODE, OpenWnnJAJP.ENGINE_MODE_OPT_TYPE_12KEY));
487        } else {
488            mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.CHANGE_MODE, OpenWnnJAJP.ENGINE_MODE_OPT_TYPE_QWERTY));
489        }
490    }
491
492    /** @see jp.co.omronsoft.openwnn.DefaultSoftKeyboard#onKey */
493    @Override public void onKey(int primaryCode, int[] keyCodes) {
494
495        if (mDisableKeyInput) {
496            return;
497        }
498
499        switch (primaryCode) {
500        case KEYCODE_JP12_TOGGLE_MODE:
501        case KEYCODE_QWERTY_TOGGLE_MODE:
502            if (!mIsInputTypeNull) {
503                nextKeyMode();
504            }
505            break;
506
507        case DefaultSoftKeyboard.KEYCODE_QWERTY_BACKSPACE:
508        case KEYCODE_JP12_BACKSPACE:
509            mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.INPUT_SOFT_KEY,
510                                          new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL)));
511            break;
512
513        case DefaultSoftKeyboard.KEYCODE_QWERTY_SHIFT:
514            toggleShiftLock();
515            break;
516
517        case DefaultSoftKeyboard.KEYCODE_QWERTY_ALT:
518            processAltKey();
519            break;
520
521        case KEYCODE_QWERTY_ENTER:
522        case KEYCODE_JP12_ENTER:
523            mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.INPUT_SOFT_KEY,
524                                          new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER)));
525            break;
526
527        case KEYCODE_JP12_REVERSE:
528            if (!mNoInput && !mEnableHardware12Keyboard) {
529                mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.TOGGLE_REVERSE_CHAR, mCurrentCycleTable));
530            }
531            break;
532
533        case KEYCODE_QWERTY_KBD:
534            changeKeyboardType(KEYBOARD_12KEY);
535            break;
536
537        case KEYCODE_JP12_KBD:
538            changeKeyboardType(KEYBOARD_QWERTY);
539            break;
540
541        case KEYCODE_JP12_EMOJI:
542        case KEYCODE_QWERTY_EMOJI:
543                commitText();
544                mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.CHANGE_MODE, OpenWnnJAJP.ENGINE_MODE_SYMBOL));
545            break;
546
547        case KEYCODE_JP12_1:
548        case KEYCODE_JP12_2:
549        case KEYCODE_JP12_3:
550        case KEYCODE_JP12_4:
551        case KEYCODE_JP12_5:
552        case KEYCODE_JP12_6:
553        case KEYCODE_JP12_7:
554        case KEYCODE_JP12_8:
555        case KEYCODE_JP12_9:
556        case KEYCODE_JP12_0:
557        case KEYCODE_JP12_SHARP:
558            /* Processing to input by ten key */
559            if (mInputType == INPUT_TYPE_INSTANT) {
560                /* Send a input character directly if instant input type is selected */
561                commitText();
562                mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.INPUT_CHAR,
563                                              mCurrentInstantTable[getTableIndex(primaryCode)]));
564            } else {
565                if ((mPrevInputKeyCode != primaryCode)) {
566                    mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.TOUCH_OTHER_KEY));
567                    if ((mCurrentKeyMode == KEYMODE_JA_HALF_ALPHABET)
568                            && (primaryCode == KEYCODE_JP12_SHARP)) {
569                        /* Commit text by symbol character (',' '.') when alphabet input mode is selected */
570                        commitText();
571                    }
572                }
573
574                /* Convert the key code to the table index and send the toggle event with the table index */
575                String[][] cycleTable = getCycleTable();
576                if (cycleTable == null) {
577                    Log.e("OpenWnn", "not founds cycle table");
578                } else {
579                    int index = getTableIndex(primaryCode);
580                    mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.TOGGLE_CHAR, cycleTable[index]));
581                    mCurrentCycleTable = cycleTable[index];
582                }
583                mPrevInputKeyCode = primaryCode;
584            }
585            break;
586
587        case KEYCODE_JP12_ASTER:
588            if (mInputType == INPUT_TYPE_INSTANT) {
589                commitText();
590                mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.INPUT_CHAR,
591                                              mCurrentInstantTable[getTableIndex(primaryCode)]));
592            } else {
593                if (!mNoInput) {
594                    /* Processing to toggle Dakuten, Handakuten, and capital */
595                    HashMap replaceTable = getReplaceTable();
596                    if (replaceTable == null) {
597                        Log.e("OpenWnn", "not founds replace table");
598                    } else {
599                        mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.REPLACE_CHAR, replaceTable));
600                        mPrevInputKeyCode = primaryCode;
601                    }
602                }
603            }
604            break;
605
606        case KEYCODE_SWITCH_FULL_HIRAGANA:
607            /* Change mode to Full width hiragana */
608            changeKeyMode(KEYMODE_JA_FULL_HIRAGANA);
609            break;
610
611        case KEYCODE_SWITCH_FULL_KATAKANA:
612            /* Change mode to Full width katakana */
613            changeKeyMode(KEYMODE_JA_FULL_KATAKANA);
614            break;
615
616        case KEYCODE_SWITCH_FULL_ALPHABET:
617            /* Change mode to Full width alphabet */
618            changeKeyMode(KEYMODE_JA_FULL_ALPHABET);
619            break;
620
621        case KEYCODE_SWITCH_FULL_NUMBER:
622            /* Change mode to Full width numeric */
623            changeKeyMode(KEYMODE_JA_FULL_NUMBER);
624            break;
625
626        case KEYCODE_SWITCH_HALF_KATAKANA:
627            /* Change mode to Half width katakana */
628            changeKeyMode(KEYMODE_JA_HALF_KATAKANA);
629            break;
630
631        case KEYCODE_SWITCH_HALF_ALPHABET:
632            /* Change mode to Half width alphabet */
633            changeKeyMode(KEYMODE_JA_HALF_ALPHABET);
634            break;
635
636        case KEYCODE_SWITCH_HALF_NUMBER:
637            /* Change mode to Half width numeric */
638            changeKeyMode(KEYMODE_JA_HALF_NUMBER);
639            break;
640
641
642        case KEYCODE_SELECT_CASE:
643            int shifted = (mShiftOn == 0) ? 1 : 0;
644            Keyboard newKeyboard = getShiftChangeKeyboard(shifted);
645            if (newKeyboard != null) {
646                mShiftOn = shifted;
647                changeKeyboard(newKeyboard);
648            }
649            break;
650
651        case KEYCODE_JP12_SPACE:
652            if ((mCurrentKeyMode == KEYMODE_JA_FULL_HIRAGANA) && !mNoInput) {
653                mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.CONVERT));
654            } else {
655                mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.INPUT_CHAR, ' '));
656            }
657            break;
658
659        case KEYCODE_EISU_KANA:
660            mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.CHANGE_MODE, OpenWnnJAJP.ENGINE_MODE_EISU_KANA));
661            break;
662
663        case KEYCODE_JP12_CLOSE:
664            mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.INPUT_KEY,
665                                          new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK)));
666            break;
667
668        case KEYCODE_JP12_LEFT:
669            mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.INPUT_SOFT_KEY,
670                                          new KeyEvent(KeyEvent.ACTION_DOWN,
671                                                       KeyEvent.KEYCODE_DPAD_LEFT)));
672            break;
673
674        case KEYCODE_JP12_RIGHT:
675            mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.INPUT_SOFT_KEY,
676                                          new KeyEvent(KeyEvent.ACTION_DOWN,
677                                                       KeyEvent.KEYCODE_DPAD_RIGHT)));
678            break;
679        case KEYCODE_NOP:
680            break;
681
682        default:
683            if (primaryCode >= 0) {
684                if (mKeyboardView.isShifted()) {
685                    primaryCode = Character.toUpperCase(primaryCode);
686                }
687                mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.INPUT_CHAR, (char)primaryCode));
688            }
689            break;
690        }
691
692        /* update shift key's state */
693        if (!mCapsLock && (primaryCode != DefaultSoftKeyboard.KEYCODE_QWERTY_SHIFT)) {
694            setShiftByEditorInfo();
695        }
696    }
697
698    /** @see jp.co.omronsoft.openwnn.DefaultSoftKeyboard#setPreferences */
699    @Override public void setPreferences(SharedPreferences pref, EditorInfo editor) {
700        mPrefEditor = pref.edit();
701        boolean isQwerty;
702        if (OpenWnn.isXLarge()) {
703            isQwerty = pref.getBoolean("opt_enable_qwerty", true);
704        } else {
705            isQwerty = pref.getBoolean("opt_enable_qwerty", false);
706        }
707
708        if (isQwerty && (mCurrentKeyboardType == KEYBOARD_12KEY)) {
709            changeKeyboardType(KEYBOARD_QWERTY);
710        }
711
712        super.setPreferences(pref, editor);
713
714        int inputType = editor.inputType;
715        if (mHardKeyboardHidden) {
716            if (inputType == EditorInfo.TYPE_NULL) {
717                if (!mIsInputTypeNull) {
718                    mIsInputTypeNull = true;
719                    if (mChangeModeKey != null) {
720                        mPopupResId = mChangeModeKey.popupResId;
721                        mChangeModeKey.popupResId = 0;
722                    }
723                }
724                return;
725            }
726
727            if (mIsInputTypeNull) {
728                mIsInputTypeNull = false;
729                if (mChangeModeKey != null) {
730                    mChangeModeKey.popupResId = mPopupResId;
731                }
732            }
733        }
734
735        mEnableAutoCaps = pref.getBoolean("auto_caps", true);
736        mLimitedKeyMode = null;
737        mPreferenceKeyMode = INVALID_KEYMODE;
738        mNoInput = true;
739        mDisableKeyInput = false;
740        mCapsLock = false;
741
742        switch (inputType & EditorInfo.TYPE_MASK_CLASS) {
743
744        case EditorInfo.TYPE_CLASS_NUMBER:
745        case EditorInfo.TYPE_CLASS_DATETIME:
746            mPreferenceKeyMode = KEYMODE_JA_HALF_NUMBER;
747            break;
748
749        case EditorInfo.TYPE_CLASS_PHONE:
750            if (mHardKeyboardHidden) {
751                mLimitedKeyMode = new int[] {KEYMODE_JA_HALF_PHONE};
752            } else if (mEnableHardware12Keyboard) {
753                mLimitedKeyMode = new int[] {KEYMODE_JA_HALF_NUMBER};
754            } else {
755                mLimitedKeyMode = new int[] {KEYMODE_JA_HALF_ALPHABET};
756            }
757            break;
758
759        case EditorInfo.TYPE_CLASS_TEXT:
760            switch (inputType & EditorInfo.TYPE_MASK_VARIATION) {
761
762            case EditorInfo.TYPE_TEXT_VARIATION_PASSWORD:
763            case EditorInfo.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD:
764                mLimitedKeyMode = new int[] {KEYMODE_JA_HALF_ALPHABET, KEYMODE_JA_HALF_NUMBER};
765                break;
766
767            case EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS:
768            case EditorInfo.TYPE_TEXT_VARIATION_URI:
769                mPreferenceKeyMode = KEYMODE_JA_HALF_ALPHABET;
770                break;
771
772            default:
773                break;
774            }
775            break;
776
777        default:
778            break;
779        }
780
781        if (inputType != mLastInputType) {
782            setDefaultKeyboard();
783            mLastInputType = inputType;
784        }
785
786        setStatusIcon();
787        setShiftByEditorInfo();
788    }
789
790    /** @see jp.co.omronsoft.openwnn.DefaultSoftKeyboard#onUpdateState */
791    @Override public void onUpdateState(OpenWnn parent) {
792        super.onUpdateState(parent);
793        if (!mCapsLock) {
794            setShiftByEditorInfo();
795        }
796    }
797
798    /**
799     * Change the keyboard to default
800     */
801    public void setDefaultKeyboard() {
802        Locale locale = Locale.getDefault();
803        int keymode = KEYMODE_JA_FULL_HIRAGANA;
804
805        if (mPreferenceKeyMode != INVALID_KEYMODE) {
806            keymode = mPreferenceKeyMode;
807        } else if (mLimitedKeyMode != null) {
808            keymode = mLimitedKeyMode[0];
809        } else {
810            if (!locale.getLanguage().equals(Locale.JAPANESE.getLanguage())) {
811                keymode = KEYMODE_JA_HALF_ALPHABET;
812            }
813        }
814        changeKeyMode(keymode);
815    }
816
817
818    /**
819     * Change to the next input mode
820     */
821    public void nextKeyMode() {
822        /* Search the current mode in the toggle table */
823        boolean found = false;
824        int index;
825        for (index = 0; index < JP_MODE_CYCLE_TABLE.length; index++) {
826            if (JP_MODE_CYCLE_TABLE[index] == mCurrentKeyMode) {
827                found = true;
828                break;
829            }
830        }
831
832        if (!found) {
833            /* If the current mode not exists, set the default mode */
834            setDefaultKeyboard();
835        } else {
836            /* If the current mode exists, set the next input mode */
837            int size = JP_MODE_CYCLE_TABLE.length;
838            int keyMode = INVALID_KEYMODE;
839            for (int i = 0; i < size; i++) {
840                index = (++index) % size;
841
842                keyMode = filterKeyMode(JP_MODE_CYCLE_TABLE[index]);
843                if (keyMode != INVALID_KEYMODE) {
844                    break;
845                }
846            }
847
848            if (keyMode != INVALID_KEYMODE) {
849                changeKeyMode(keyMode);
850            }
851        }
852    }
853
854    /**
855     * Create the keyboard for portrait mode
856     * <br>
857     * @param parent  The context
858     */
859    private void createKeyboardsPortrait(OpenWnn parent) {
860        Keyboard[][] keyList;
861        if (OpenWnn.isXLarge()) {
862            /* qwerty shift_off (portrait) */
863            keyList = mKeyboard[LANG_JA][PORTRAIT][KEYBOARD_QWERTY][KEYBOARD_SHIFT_OFF];
864            keyList[KEYMODE_JA_FULL_HIRAGANA][0] = new Keyboard(parent, R.xml.keyboard_qwerty_jp);
865            keyList[KEYMODE_JA_FULL_NUMBER][0]   = new Keyboard(parent, R.xml.keyboard_qwerty_jp_full_symbols);
866            keyList[KEYMODE_JA_HALF_ALPHABET][0] = new Keyboard(parent, R.xml.keyboard_qwerty_jp_half_alphabet);
867            keyList[KEYMODE_JA_HALF_NUMBER][0]   = new Keyboard(parent, R.xml.keyboard_qwerty_jp_half_symbols);
868            keyList[KEYMODE_JA_HALF_PHONE][0]    = new Keyboard(parent, R.xml.keyboard_12key_phone);
869
870            /* qwerty shift_on (portrait) */
871            keyList = mKeyboard[LANG_JA][PORTRAIT][KEYBOARD_QWERTY][KEYBOARD_SHIFT_ON];
872            keyList[KEYMODE_JA_FULL_HIRAGANA][0] = new Keyboard(parent, R.xml.keyboard_qwerty_jp_shift);
873            keyList[KEYMODE_JA_FULL_NUMBER][0]   = new Keyboard(parent, R.xml.keyboard_qwerty_jp_full_symbols_shift);
874            keyList[KEYMODE_JA_HALF_ALPHABET][0] = new Keyboard(parent, R.xml.keyboard_qwerty_jp_half_alphabet_shift);
875            keyList[KEYMODE_JA_HALF_NUMBER][0]   = new Keyboard(parent, R.xml.keyboard_qwerty_jp_half_symbols_shift);
876            keyList[KEYMODE_JA_HALF_PHONE][0] =
877                mKeyboard[LANG_JA][PORTRAIT][KEYBOARD_QWERTY][KEYBOARD_SHIFT_OFF][KEYMODE_JA_HALF_PHONE][0];
878        } else {
879            /* qwerty shift_off (portrait) */
880            keyList = mKeyboard[LANG_JA][PORTRAIT][KEYBOARD_QWERTY][KEYBOARD_SHIFT_OFF];
881            keyList[KEYMODE_JA_FULL_HIRAGANA][0] = new Keyboard(parent, R.xml.keyboard_qwerty_jp);
882            keyList[KEYMODE_JA_FULL_ALPHABET][0] = new Keyboard(parent, R.xml.keyboard_qwerty_jp_full_alphabet);
883            keyList[KEYMODE_JA_FULL_NUMBER][0]   = new Keyboard(parent, R.xml.keyboard_qwerty_jp_full_symbols);
884            keyList[KEYMODE_JA_FULL_KATAKANA][0] = new Keyboard(parent, R.xml.keyboard_qwerty_jp_full_katakana);
885            keyList[KEYMODE_JA_HALF_ALPHABET][0] = new Keyboard(parent, R.xml.keyboard_qwerty_jp_half_alphabet);
886            keyList[KEYMODE_JA_HALF_NUMBER][0]   = new Keyboard(parent, R.xml.keyboard_qwerty_jp_half_symbols);
887            keyList[KEYMODE_JA_HALF_KATAKANA][0] = new Keyboard(parent, R.xml.keyboard_qwerty_jp_half_katakana);
888            keyList[KEYMODE_JA_HALF_PHONE][0]    = new Keyboard(parent, R.xml.keyboard_12key_phone);
889
890            /* qwerty shift_on (portrait) */
891            keyList = mKeyboard[LANG_JA][PORTRAIT][KEYBOARD_QWERTY][KEYBOARD_SHIFT_ON];
892            keyList[KEYMODE_JA_FULL_HIRAGANA][0] = new Keyboard(parent, R.xml.keyboard_qwerty_jp_shift);
893            keyList[KEYMODE_JA_FULL_ALPHABET][0] = new Keyboard(parent, R.xml.keyboard_qwerty_jp_full_alphabet_shift);
894            keyList[KEYMODE_JA_FULL_NUMBER][0]   = new Keyboard(parent, R.xml.keyboard_qwerty_jp_full_symbols_shift);
895            keyList[KEYMODE_JA_FULL_KATAKANA][0] = new Keyboard(parent, R.xml.keyboard_qwerty_jp_full_katakana_shift);
896            keyList[KEYMODE_JA_HALF_ALPHABET][0] = new Keyboard(parent, R.xml.keyboard_qwerty_jp_half_alphabet_shift);
897            keyList[KEYMODE_JA_HALF_NUMBER][0]   = new Keyboard(parent, R.xml.keyboard_qwerty_jp_half_symbols_shift);
898            keyList[KEYMODE_JA_HALF_KATAKANA][0] = new Keyboard(parent, R.xml.keyboard_qwerty_jp_half_katakana_shift);
899            keyList[KEYMODE_JA_HALF_PHONE][0] =
900                mKeyboard[LANG_JA][PORTRAIT][KEYBOARD_QWERTY][KEYBOARD_SHIFT_OFF][KEYMODE_JA_HALF_PHONE][0];
901
902
903            /* 12-keys shift_off (portrait) */
904            keyList = mKeyboard[LANG_JA][PORTRAIT][KEYBOARD_12KEY][KEYBOARD_SHIFT_OFF];
905            keyList[KEYMODE_JA_FULL_HIRAGANA][0] = new Keyboard(parent, R.xml.keyboard_12keyjp);
906            keyList[KEYMODE_JA_FULL_HIRAGANA][1] = new Keyboard(parent, R.xml.keyboard_12keyjp_input);
907            keyList[KEYMODE_JA_FULL_ALPHABET][0] = new Keyboard(parent, R.xml.keyboard_12key_full_alphabet);
908            keyList[KEYMODE_JA_FULL_ALPHABET][1] = new Keyboard(parent, R.xml.keyboard_12key_full_alphabet_input);
909            keyList[KEYMODE_JA_FULL_NUMBER][0]   = new Keyboard(parent, R.xml.keyboard_12key_full_num);
910            keyList[KEYMODE_JA_FULL_KATAKANA][0] = new Keyboard(parent, R.xml.keyboard_12key_full_katakana);
911            keyList[KEYMODE_JA_FULL_KATAKANA][1] = new Keyboard(parent, R.xml.keyboard_12key_full_katakana_input);
912            keyList[KEYMODE_JA_HALF_ALPHABET][0] = new Keyboard(parent, R.xml.keyboard_12key_half_alphabet);
913            keyList[KEYMODE_JA_HALF_ALPHABET][1] = new Keyboard(parent, R.xml.keyboard_12key_half_alphabet_input);
914            keyList[KEYMODE_JA_HALF_NUMBER][0]   = new Keyboard(parent, R.xml.keyboard_12key_half_num);
915            keyList[KEYMODE_JA_HALF_KATAKANA][0] = new Keyboard(parent, R.xml.keyboard_12key_half_katakana);
916            keyList[KEYMODE_JA_HALF_KATAKANA][1] = new Keyboard(parent, R.xml.keyboard_12key_half_katakana_input);
917            keyList[KEYMODE_JA_HALF_PHONE][0]    = new Keyboard(parent, R.xml.keyboard_12key_phone);
918
919            /* 12-keys shift_on (portrait) */
920            keyList = mKeyboard[LANG_JA][PORTRAIT][KEYBOARD_12KEY][KEYBOARD_SHIFT_ON];
921            keyList[KEYMODE_JA_FULL_HIRAGANA]
922                = mKeyboard[LANG_JA][PORTRAIT][KEYBOARD_12KEY][KEYBOARD_SHIFT_OFF][KEYMODE_JA_FULL_HIRAGANA];
923            keyList[KEYMODE_JA_FULL_ALPHABET]
924                = mKeyboard[LANG_JA][PORTRAIT][KEYBOARD_12KEY][KEYBOARD_SHIFT_OFF][KEYMODE_JA_FULL_ALPHABET];
925            keyList[KEYMODE_JA_FULL_NUMBER]
926                = mKeyboard[LANG_JA][PORTRAIT][KEYBOARD_12KEY][KEYBOARD_SHIFT_OFF][KEYMODE_JA_FULL_NUMBER];
927            keyList[KEYMODE_JA_FULL_KATAKANA]
928                = mKeyboard[LANG_JA][PORTRAIT][KEYBOARD_12KEY][KEYBOARD_SHIFT_OFF][KEYMODE_JA_FULL_KATAKANA];
929            keyList[KEYMODE_JA_HALF_ALPHABET]
930                = mKeyboard[LANG_JA][PORTRAIT][KEYBOARD_12KEY][KEYBOARD_SHIFT_OFF][KEYMODE_JA_HALF_ALPHABET];;
931            keyList[KEYMODE_JA_HALF_NUMBER]
932                = mKeyboard[LANG_JA][PORTRAIT][KEYBOARD_12KEY][KEYBOARD_SHIFT_OFF][KEYMODE_JA_HALF_NUMBER];
933            keyList[KEYMODE_JA_HALF_KATAKANA]
934                = mKeyboard[LANG_JA][PORTRAIT][KEYBOARD_12KEY][KEYBOARD_SHIFT_OFF][KEYMODE_JA_HALF_KATAKANA];
935            keyList[KEYMODE_JA_HALF_PHONE]
936                = mKeyboard[LANG_JA][PORTRAIT][KEYBOARD_12KEY][KEYBOARD_SHIFT_OFF][KEYMODE_JA_HALF_PHONE];
937        }
938    }
939
940    /**
941     * Create the keyboard for landscape mode
942     * <br>
943     * @param parent  The context
944     */
945    private void createKeyboardsLandscape(OpenWnn parent) {
946        Keyboard[][] keyList;
947        if (OpenWnn.isXLarge()) {
948            /* qwerty shift_off (landscape) */
949            keyList = mKeyboard[LANG_JA][LANDSCAPE][KEYBOARD_QWERTY][KEYBOARD_SHIFT_OFF];
950            keyList[KEYMODE_JA_FULL_HIRAGANA][0] = new Keyboard(parent, R.xml.keyboard_qwerty_jp);
951            keyList[KEYMODE_JA_FULL_NUMBER][0]   = new Keyboard(parent, R.xml.keyboard_qwerty_jp_full_symbols);
952            keyList[KEYMODE_JA_HALF_ALPHABET][0] = new Keyboard(parent, R.xml.keyboard_qwerty_jp_half_alphabet);
953            keyList[KEYMODE_JA_HALF_NUMBER][0]   = new Keyboard(parent, R.xml.keyboard_qwerty_jp_half_symbols);
954            keyList[KEYMODE_JA_HALF_PHONE][0]    = new Keyboard(parent, R.xml.keyboard_12key_phone);
955
956            /* qwerty shift_on (landscape) */
957            keyList = mKeyboard[LANG_JA][LANDSCAPE][KEYBOARD_QWERTY][KEYBOARD_SHIFT_ON];
958            keyList[KEYMODE_JA_FULL_HIRAGANA][0] = new Keyboard(parent, R.xml.keyboard_qwerty_jp_shift);
959            keyList[KEYMODE_JA_FULL_NUMBER][0]   = new Keyboard(parent, R.xml.keyboard_qwerty_jp_full_symbols_shift);
960            keyList[KEYMODE_JA_HALF_ALPHABET][0] = new Keyboard(parent, R.xml.keyboard_qwerty_jp_half_alphabet_shift);
961            keyList[KEYMODE_JA_HALF_NUMBER][0]   = new Keyboard(parent, R.xml.keyboard_qwerty_jp_half_symbols_shift);
962            keyList[KEYMODE_JA_HALF_PHONE][0] =
963                mKeyboard[LANG_JA][LANDSCAPE][KEYBOARD_QWERTY][KEYBOARD_SHIFT_OFF][KEYMODE_JA_HALF_PHONE][0];
964        } else {
965            /* qwerty shift_off (landscape) */
966            keyList = mKeyboard[LANG_JA][LANDSCAPE][KEYBOARD_QWERTY][KEYBOARD_SHIFT_OFF];
967            keyList[KEYMODE_JA_FULL_HIRAGANA][0] = new Keyboard(parent, R.xml.keyboard_qwerty_jp);
968            keyList[KEYMODE_JA_FULL_ALPHABET][0] = new Keyboard(parent, R.xml.keyboard_qwerty_jp_full_alphabet);
969            keyList[KEYMODE_JA_FULL_NUMBER][0]   = new Keyboard(parent, R.xml.keyboard_qwerty_jp_full_symbols);
970            keyList[KEYMODE_JA_FULL_KATAKANA][0] = new Keyboard(parent, R.xml.keyboard_qwerty_jp_full_katakana);
971            keyList[KEYMODE_JA_HALF_ALPHABET][0] = new Keyboard(parent, R.xml.keyboard_qwerty_jp_half_alphabet);
972            keyList[KEYMODE_JA_HALF_NUMBER][0]   = new Keyboard(parent, R.xml.keyboard_qwerty_jp_half_symbols);
973            keyList[KEYMODE_JA_HALF_KATAKANA][0] = new Keyboard(parent, R.xml.keyboard_qwerty_jp_half_katakana);
974            keyList[KEYMODE_JA_HALF_PHONE][0]    = new Keyboard(parent, R.xml.keyboard_12key_phone);
975
976            /* qwerty shift_on (landscape) */
977            keyList = mKeyboard[LANG_JA][LANDSCAPE][KEYBOARD_QWERTY][KEYBOARD_SHIFT_ON];
978            keyList[KEYMODE_JA_FULL_HIRAGANA][0] = new Keyboard(parent, R.xml.keyboard_qwerty_jp_shift);
979            keyList[KEYMODE_JA_FULL_ALPHABET][0] = new Keyboard(parent, R.xml.keyboard_qwerty_jp_full_alphabet_shift);
980            keyList[KEYMODE_JA_FULL_NUMBER][0]   = new Keyboard(parent, R.xml.keyboard_qwerty_jp_full_symbols_shift);
981            keyList[KEYMODE_JA_FULL_KATAKANA][0] = new Keyboard(parent, R.xml.keyboard_qwerty_jp_full_katakana_shift);
982            keyList[KEYMODE_JA_HALF_ALPHABET][0] = new Keyboard(parent, R.xml.keyboard_qwerty_jp_half_alphabet_shift);
983            keyList[KEYMODE_JA_HALF_NUMBER][0]   = new Keyboard(parent, R.xml.keyboard_qwerty_jp_half_symbols_shift);
984            keyList[KEYMODE_JA_HALF_KATAKANA][0] = new Keyboard(parent, R.xml.keyboard_qwerty_jp_half_katakana_shift);
985            keyList[KEYMODE_JA_HALF_PHONE][0] =
986                mKeyboard[LANG_JA][LANDSCAPE][KEYBOARD_QWERTY][KEYBOARD_SHIFT_OFF][KEYMODE_JA_HALF_PHONE][0];
987
988
989            /* 12-keys shift_off (landscape) */
990            keyList = mKeyboard[LANG_JA][LANDSCAPE][KEYBOARD_12KEY][KEYBOARD_SHIFT_OFF];
991            keyList[KEYMODE_JA_FULL_HIRAGANA][0] = new Keyboard(parent, R.xml.keyboard_12keyjp);
992            keyList[KEYMODE_JA_FULL_HIRAGANA][1] = new Keyboard(parent, R.xml.keyboard_12keyjp_input);
993            keyList[KEYMODE_JA_FULL_ALPHABET][0] = new Keyboard(parent, R.xml.keyboard_12key_full_alphabet);
994            keyList[KEYMODE_JA_FULL_ALPHABET][1] = new Keyboard(parent, R.xml.keyboard_12key_full_alphabet_input);
995            keyList[KEYMODE_JA_FULL_NUMBER][0]   = new Keyboard(parent, R.xml.keyboard_12key_full_num);
996            keyList[KEYMODE_JA_FULL_KATAKANA][0] = new Keyboard(parent, R.xml.keyboard_12key_full_katakana);
997            keyList[KEYMODE_JA_FULL_KATAKANA][1] = new Keyboard(parent, R.xml.keyboard_12key_full_katakana_input);
998            keyList[KEYMODE_JA_HALF_ALPHABET][0] = new Keyboard(parent, R.xml.keyboard_12key_half_alphabet);
999            keyList[KEYMODE_JA_HALF_ALPHABET][1] = new Keyboard(parent, R.xml.keyboard_12key_half_alphabet_input);
1000            keyList[KEYMODE_JA_HALF_NUMBER][0]   = new Keyboard(parent, R.xml.keyboard_12key_half_num);
1001            keyList[KEYMODE_JA_HALF_KATAKANA][0] = new Keyboard(parent, R.xml.keyboard_12key_half_katakana);
1002            keyList[KEYMODE_JA_HALF_KATAKANA][1] = new Keyboard(parent, R.xml.keyboard_12key_half_katakana_input);
1003            keyList[KEYMODE_JA_HALF_PHONE][0]    = new Keyboard(parent, R.xml.keyboard_12key_phone);
1004
1005            /* 12-keys shift_on (landscape) */
1006            keyList = mKeyboard[LANG_JA][LANDSCAPE][KEYBOARD_12KEY][KEYBOARD_SHIFT_ON];
1007            keyList[KEYMODE_JA_FULL_HIRAGANA]
1008                = mKeyboard[LANG_JA][LANDSCAPE][KEYBOARD_12KEY][KEYBOARD_SHIFT_OFF][KEYMODE_JA_FULL_HIRAGANA];
1009            keyList[KEYMODE_JA_FULL_ALPHABET]
1010                = mKeyboard[LANG_JA][LANDSCAPE][KEYBOARD_12KEY][KEYBOARD_SHIFT_OFF][KEYMODE_JA_FULL_ALPHABET];
1011            keyList[KEYMODE_JA_FULL_NUMBER]
1012                = mKeyboard[LANG_JA][LANDSCAPE][KEYBOARD_12KEY][KEYBOARD_SHIFT_OFF][KEYMODE_JA_FULL_NUMBER];
1013            keyList[KEYMODE_JA_FULL_KATAKANA]
1014                = mKeyboard[LANG_JA][LANDSCAPE][KEYBOARD_12KEY][KEYBOARD_SHIFT_OFF][KEYMODE_JA_FULL_KATAKANA];
1015            keyList[KEYMODE_JA_HALF_ALPHABET]
1016                = mKeyboard[LANG_JA][LANDSCAPE][KEYBOARD_12KEY][KEYBOARD_SHIFT_OFF][KEYMODE_JA_HALF_ALPHABET];;
1017            keyList[KEYMODE_JA_HALF_NUMBER]
1018                = mKeyboard[LANG_JA][LANDSCAPE][KEYBOARD_12KEY][KEYBOARD_SHIFT_OFF][KEYMODE_JA_HALF_NUMBER];
1019            keyList[KEYMODE_JA_HALF_KATAKANA]
1020                = mKeyboard[LANG_JA][LANDSCAPE][KEYBOARD_12KEY][KEYBOARD_SHIFT_OFF][KEYMODE_JA_HALF_KATAKANA];
1021            keyList[KEYMODE_JA_HALF_PHONE]
1022                = mKeyboard[LANG_JA][LANDSCAPE][KEYBOARD_12KEY][KEYBOARD_SHIFT_OFF][KEYMODE_JA_HALF_PHONE];
1023         }
1024    }
1025
1026    /**
1027     * Convert the key code to the index of table
1028     * <br>
1029     * @param index     The key code
1030     * @return          The index of the toggle table for input
1031     */
1032    private int getTableIndex(int keyCode) {
1033        int index =
1034            (keyCode == KEYCODE_JP12_1)     ?  0 :
1035            (keyCode == KEYCODE_JP12_2)     ?  1 :
1036            (keyCode == KEYCODE_JP12_3)     ?  2 :
1037            (keyCode == KEYCODE_JP12_4)     ?  3 :
1038            (keyCode == KEYCODE_JP12_5)     ?  4 :
1039            (keyCode == KEYCODE_JP12_6)     ?  5 :
1040            (keyCode == KEYCODE_JP12_7)     ?  6 :
1041            (keyCode == KEYCODE_JP12_8)     ?  7 :
1042            (keyCode == KEYCODE_JP12_9)     ?  8 :
1043            (keyCode == KEYCODE_JP12_0)     ?  9 :
1044            (keyCode == KEYCODE_JP12_SHARP) ? 10 :
1045            (keyCode == KEYCODE_JP12_ASTER) ? 11 :
1046            0;
1047
1048        return index;
1049    }
1050
1051    /**
1052     * Get the toggle table for input that is appropriate in current mode.
1053     *
1054     * @return      The toggle table for input
1055     */
1056    private String[][] getCycleTable() {
1057        String[][] cycleTable = null;
1058        switch (mCurrentKeyMode) {
1059        case KEYMODE_JA_FULL_HIRAGANA:
1060            cycleTable = JP_FULL_HIRAGANA_CYCLE_TABLE;
1061            break;
1062
1063        case KEYMODE_JA_FULL_KATAKANA:
1064            cycleTable = JP_FULL_KATAKANA_CYCLE_TABLE;
1065            break;
1066
1067        case KEYMODE_JA_FULL_ALPHABET:
1068            cycleTable = JP_FULL_ALPHABET_CYCLE_TABLE;
1069            break;
1070
1071        case KEYMODE_JA_FULL_NUMBER:
1072        case KEYMODE_JA_HALF_NUMBER:
1073            /* Because these modes belong to direct input group, No toggle table exists */
1074            break;
1075
1076        case KEYMODE_JA_HALF_ALPHABET:
1077            cycleTable = JP_HALF_ALPHABET_CYCLE_TABLE;
1078            break;
1079
1080        case KEYMODE_JA_HALF_KATAKANA:
1081            cycleTable = JP_HALF_KATAKANA_CYCLE_TABLE;
1082            break;
1083
1084        default:
1085            break;
1086        }
1087        return cycleTable;
1088    }
1089
1090    /**
1091     * Get the replace table that is appropriate in current mode.
1092     *
1093     * @return      The replace table
1094     */
1095    private HashMap getReplaceTable() {
1096        HashMap hashTable = null;
1097        switch (mCurrentKeyMode) {
1098        case KEYMODE_JA_FULL_HIRAGANA:
1099            hashTable = JP_FULL_HIRAGANA_REPLACE_TABLE;
1100            break;
1101        case KEYMODE_JA_FULL_KATAKANA:
1102            hashTable = JP_FULL_KATAKANA_REPLACE_TABLE;
1103            break;
1104
1105        case KEYMODE_JA_FULL_ALPHABET:
1106            hashTable = JP_FULL_ALPHABET_REPLACE_TABLE;
1107            break;
1108
1109        case KEYMODE_JA_FULL_NUMBER:
1110        case KEYMODE_JA_HALF_NUMBER:
1111            /* Because these modes belong to direct input group, No replacing table exists */
1112            break;
1113
1114        case KEYMODE_JA_HALF_ALPHABET:
1115            hashTable = JP_HALF_ALPHABET_REPLACE_TABLE;
1116            break;
1117
1118        case KEYMODE_JA_HALF_KATAKANA:
1119            hashTable = JP_HALF_KATAKANA_REPLACE_TABLE;
1120            break;
1121
1122        default:
1123            break;
1124        }
1125        return hashTable;
1126    }
1127
1128    /**
1129     * Set the status icon that is appropriate in current mode
1130     */
1131    private void setStatusIcon() {
1132        int icon = 0;
1133
1134        switch (mCurrentKeyMode) {
1135        case KEYMODE_JA_FULL_HIRAGANA:
1136            icon = R.drawable.immodeic_hiragana;
1137            break;
1138        case KEYMODE_JA_FULL_KATAKANA:
1139            icon = R.drawable.immodeic_full_kana;
1140            break;
1141        case KEYMODE_JA_FULL_ALPHABET:
1142            icon = R.drawable.immodeic_full_alphabet;
1143            break;
1144        case KEYMODE_JA_FULL_NUMBER:
1145            icon = R.drawable.immodeic_full_number;
1146            break;
1147        case KEYMODE_JA_HALF_KATAKANA:
1148            icon = R.drawable.immodeic_half_kana;
1149            break;
1150        case KEYMODE_JA_HALF_ALPHABET:
1151            icon = R.drawable.immodeic_half_alphabet;
1152            break;
1153        case KEYMODE_JA_HALF_NUMBER:
1154        case KEYMODE_JA_HALF_PHONE:
1155            icon = R.drawable.immodeic_half_number;
1156            break;
1157        default:
1158            break;
1159        }
1160
1161        mWnn.showStatusIcon(icon);
1162    }
1163
1164    /**
1165     * Get the shift key state from the editor.
1166     * <br>
1167     * @param editor    The editor information
1168     * @return          The state id of the shift key (0:off, 1:on)
1169     */
1170    protected int getShiftKeyState(EditorInfo editor) {
1171        InputConnection connection = mWnn.getCurrentInputConnection();
1172        if (connection != null) {
1173            int caps = connection.getCursorCapsMode(editor.inputType);
1174            return (caps == 0) ? 0 : 1;
1175        } else {
1176            return 0;
1177        }
1178    }
1179
1180    /**
1181     * Set the shift key state from {@link EditorInfo}.
1182     */
1183    private void setShiftByEditorInfo() {
1184        if (mEnableAutoCaps && (mCurrentKeyMode == KEYMODE_JA_HALF_ALPHABET)) {
1185            int shift = getShiftKeyState(mWnn.getCurrentInputEditorInfo());
1186
1187            mShiftOn = shift;
1188            changeKeyboard(getShiftChangeKeyboard(shift));
1189        }
1190    }
1191
1192    /** @see jp.co.omronsoft.openwnn.DefaultSoftKeyboard#setHardKeyboardHidden */
1193    @Override public void setHardKeyboardHidden(boolean hidden) {
1194        if (mWnn != null) {
1195            if (!hidden) {
1196                if (mEnableHardware12Keyboard) {
1197                    mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.CHANGE_MODE,
1198                                                  OpenWnnJAJP.ENGINE_MODE_OPT_TYPE_12KEY));
1199                } else {
1200                    mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.CHANGE_MODE,
1201                                                  OpenWnnJAJP.ENGINE_MODE_OPT_TYPE_QWERTY));
1202                }
1203            }
1204
1205            if (mHardKeyboardHidden != hidden) {
1206                if ((mLimitedKeyMode != null)
1207                    || (!mEnableHardware12Keyboard
1208                        && (mCurrentKeyMode != KEYMODE_JA_FULL_HIRAGANA)
1209                        && (mCurrentKeyMode != KEYMODE_JA_HALF_ALPHABET))) {
1210
1211                    mLastInputType = EditorInfo.TYPE_NULL;
1212                    if (mWnn.isInputViewShown()) {
1213                        setDefaultKeyboard();
1214                    }
1215                }
1216            }
1217        }
1218        super.setHardKeyboardHidden(hidden);
1219    }
1220
1221    /** @see jp.co.omronsoft.openwnn.DefaultSoftKeyboard#setHardware12Keyboard */
1222    @Override public void setHardware12Keyboard(boolean type12Key) {
1223        if (mWnn != null) {
1224            if (mEnableHardware12Keyboard != type12Key) {
1225                if (type12Key) {
1226                    mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.CHANGE_MODE,
1227                                                  OpenWnnJAJP.ENGINE_MODE_OPT_TYPE_12KEY));
1228                } else {
1229                    mWnn.onEvent(new OpenWnnEvent(OpenWnnEvent.CHANGE_MODE,
1230                                                  OpenWnnJAJP.ENGINE_MODE_OPT_TYPE_QWERTY));
1231                }
1232            }
1233        }
1234        super.setHardware12Keyboard(type12Key);
1235    }
1236
1237    /**
1238     * Change the key-mode to the allowed one which is restricted
1239     *  by the text input field or the type of the keyboard.
1240     * @param keyMode The key-mode
1241     * @return the key-mode allowed
1242     */
1243    private int filterKeyMode(int keyMode) {
1244        int targetMode = keyMode;
1245        int[] limits = mLimitedKeyMode;
1246
1247        if (!mHardKeyboardHidden) { /* for hardware keyboard */
1248            if (!mEnableHardware12Keyboard && (targetMode != KEYMODE_JA_FULL_HIRAGANA)
1249                && (targetMode != KEYMODE_JA_HALF_ALPHABET)) {
1250
1251                Locale locale = Locale.getDefault();
1252                int keymode = KEYMODE_JA_HALF_ALPHABET;
1253                if (locale.getLanguage().equals(Locale.JAPANESE.getLanguage())) {
1254                    switch (targetMode) {
1255                    case KEYMODE_JA_FULL_HIRAGANA:
1256                    case KEYMODE_JA_FULL_KATAKANA:
1257                    case KEYMODE_JA_HALF_KATAKANA:
1258                        keymode = KEYMODE_JA_FULL_HIRAGANA;
1259                        break;
1260                    default:
1261                        /* half-alphabet */
1262                        break;
1263                    }
1264                }
1265                targetMode = keymode;
1266            }
1267        }
1268
1269        /* restrict by the type of the text field */
1270        if (limits != null) {
1271            boolean hasAccepted = false;
1272            boolean hasRequiredChange = true;
1273            int size = limits.length;
1274            int nowMode = mCurrentKeyMode;
1275
1276            for (int i = 0; i < size; i++) {
1277                if (targetMode == limits[i]) {
1278                    hasAccepted = true;
1279                    break;
1280                }
1281                if (nowMode == limits[i]) {
1282                    hasRequiredChange = false;
1283                }
1284            }
1285
1286            if (!hasAccepted) {
1287                if (hasRequiredChange) {
1288                    targetMode = mLimitedKeyMode[0];
1289                } else {
1290                    targetMode = INVALID_KEYMODE;
1291                }
1292            }
1293        }
1294
1295        return targetMode;
1296    }
1297
1298    /**
1299     * Shows input mode choosing dialog.
1300     *
1301     * @return boolean
1302     */
1303    public boolean showInputModeSwitchDialog() {
1304        BaseInputView baseInputView = (BaseInputView)getCurrentView();
1305        AlertDialog.Builder builder = new AlertDialog.Builder(baseInputView.getContext());
1306        builder.setCancelable(true);
1307        builder.setNegativeButton(R.string.dialog_button_cancel, null);
1308
1309        Resources r = baseInputView.getResources();
1310        CharSequence itemFullHirakana = r.getString(R.string.ti_input_mode_full_hirakana_title_txt);
1311        CharSequence itemFullKatakana = r.getString(R.string.ti_input_mode_full_katakana_title_txt);
1312        CharSequence itemHalfKatakana = r.getString(R.string.ti_input_mode_half_katakana_title_txt);
1313        CharSequence itemFullAlphabet = r.getString(R.string.ti_input_mode_full_alphabet_title_txt);
1314        CharSequence itemHalfAlphabet = r.getString(R.string.ti_input_mode_half_alphabet_title_txt);
1315        CharSequence itemFullNumber = r.getString(R.string.ti_input_mode_full_number_title_txt);
1316        CharSequence itemHalfNumber = r.getString(R.string.ti_input_mode_half_number_title_txt);
1317        final CharSequence[] itemTitles;
1318        final int[] itemValues;
1319        if (OpenWnn.isXLarge()) {
1320            itemTitles = new CharSequence[] {itemFullHirakana, itemHalfAlphabet,
1321                                                itemFullNumber, itemHalfNumber};
1322            itemValues = new int[] {KEYMODE_JA_FULL_HIRAGANA, KEYMODE_JA_HALF_ALPHABET,
1323                                        KEYMODE_JA_FULL_NUMBER, KEYMODE_JA_HALF_NUMBER};
1324        } else {
1325            itemTitles = new CharSequence[] {itemFullHirakana, itemFullKatakana, itemHalfKatakana,
1326                                               itemFullAlphabet, itemHalfAlphabet, itemFullNumber,
1327                                               itemHalfNumber};
1328            itemValues = new int[] {KEYMODE_JA_FULL_HIRAGANA, KEYMODE_JA_FULL_KATAKANA, KEYMODE_JA_HALF_KATAKANA,
1329                    KEYMODE_JA_FULL_ALPHABET, KEYMODE_JA_HALF_ALPHABET, KEYMODE_JA_FULL_NUMBER, KEYMODE_JA_HALF_NUMBER};
1330        }
1331
1332        builder.setSingleChoiceItems(itemTitles, findIndexOfValue(itemValues,
1333                mCurrentKeyMode), new DialogInterface.OnClickListener() {
1334            public void onClick(DialogInterface inputModeSwitchDialog, int position) {
1335                switch(position){
1336                    case 0:
1337                        changeKeyMode(itemValues[0]);
1338                        break;
1339
1340                    case 1:
1341                        changeKeyMode(itemValues[1]);
1342                        break;
1343
1344                    case 2:
1345                        changeKeyMode(itemValues[2]);
1346                        break;
1347
1348                    case 3:
1349                        changeKeyMode(itemValues[3]);
1350                        break;
1351
1352                    case 4:
1353                        changeKeyMode(itemValues[4]);
1354                        break;
1355
1356                    case 5:
1357                        changeKeyMode(itemValues[5]);
1358                        break;
1359
1360                    case 6:
1361                        changeKeyMode(itemValues[6]);
1362                        break;
1363
1364                    default:
1365                        break;
1366                }
1367                inputModeSwitchDialog.dismiss();
1368            }
1369        });
1370
1371        builder.setTitle(r.getString(R.string.ti_long_press_dialog_input_mode_txt));
1372        baseInputView.showDialog(builder);
1373        return true;
1374    }
1375
1376    /**
1377     * Finds the index of a value in a int[].
1378     *
1379     * @param value   the int[] to search in,
1380     * @param mode    the value need to find index,
1381     * @return the index of the value.
1382     */
1383    private int findIndexOfValue(int[] value, int mode) {
1384        for (int i = 0; i < value.length; i++) {
1385            if (value[i] == mode) {
1386                return i;
1387            }
1388        }
1389        return -1;
1390    }
1391}
1392