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