• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 The Android Open Source Project
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 
17 package com.android.inputmethod.pinyin;
18 
19 import com.android.inputmethod.pinyin.SoftKeyboard.KeyRow;
20 
21 import android.content.res.Resources;
22 import android.view.inputmethod.EditorInfo;
23 
24 /**
25  * Switcher used to switching input mode between Chinese, English, symbol,etc.
26  */
27 public class InputModeSwitcher {
28     /**
29      * User defined key code, used by soft keyboard.
30      */
31     private static final int USERDEF_KEYCODE_SHIFT_1 = -1;
32 
33     /**
34      * User defined key code, used by soft keyboard.
35      */
36     private static final int USERDEF_KEYCODE_LANG_2 = -2;
37 
38     /**
39      * User defined key code, used by soft keyboard.
40      */
41     private static final int USERDEF_KEYCODE_SYM_3 = -3;
42 
43     /**
44      * User defined key code, used by soft keyboard.
45      */
46     public static final int USERDEF_KEYCODE_PHONE_SYM_4 = -4;
47 
48     /**
49      * User defined key code, used by soft keyboard.
50      */
51     private static final int USERDEF_KEYCODE_MORE_SYM_5 = -5;
52 
53     /**
54      * User defined key code, used by soft keyboard.
55      */
56     private static final int USERDEF_KEYCODE_SMILEY_6 = -6;
57 
58 
59     /**
60      * Bits used to indicate soft keyboard layout. If none bit is set, the
61      * current input mode does not require a soft keyboard.
62      **/
63     private static final int MASK_SKB_LAYOUT = 0xf0000000;
64 
65     /**
66      * A kind of soft keyboard layout. An input mode should be anded with
67      * {@link #MASK_SKB_LAYOUT} to get its soft keyboard layout.
68      */
69     private static final int MASK_SKB_LAYOUT_QWERTY = 0x10000000;
70 
71     /**
72      * A kind of soft keyboard layout. An input mode should be anded with
73      * {@link #MASK_SKB_LAYOUT} to get its soft keyboard layout.
74      */
75     private static final int MASK_SKB_LAYOUT_SYMBOL1 = 0x20000000;
76 
77     /**
78      * A kind of soft keyboard layout. An input mode should be anded with
79      * {@link #MASK_SKB_LAYOUT} to get its soft keyboard layout.
80      */
81     private static final int MASK_SKB_LAYOUT_SYMBOL2 = 0x30000000;
82 
83     /**
84      * A kind of soft keyboard layout. An input mode should be anded with
85      * {@link #MASK_SKB_LAYOUT} to get its soft keyboard layout.
86      */
87     private static final int MASK_SKB_LAYOUT_SMILEY = 0x40000000;
88 
89     /**
90      * A kind of soft keyboard layout. An input mode should be anded with
91      * {@link #MASK_SKB_LAYOUT} to get its soft keyboard layout.
92      */
93     private static final int MASK_SKB_LAYOUT_PHONE = 0x50000000;
94 
95     /**
96      * Used to indicate which language the current input mode is in. If the
97      * current input mode works with a none-QWERTY soft keyboard, these bits are
98      * also used to get language information. For example, a Chinese symbol soft
99      * keyboard and an English one are different in an icon which is used to
100      * tell user the language information. BTW, the smiley soft keyboard mode
101      * should be set with {@link #MASK_LANGUAGE_CN} because it can only be
102      * launched from Chinese QWERTY soft keyboard, and it has Chinese icon on
103      * soft keyboard.
104      */
105     private static final int MASK_LANGUAGE = 0x0f000000;
106 
107     /**
108      * Used to indicate the current language. An input mode should be anded with
109      * {@link #MASK_LANGUAGE} to get this information.
110      */
111     private static final int MASK_LANGUAGE_CN = 0x01000000;
112 
113     /**
114      * Used to indicate the current language. An input mode should be anded with
115      * {@link #MASK_LANGUAGE} to get this information.
116      */
117     private static final int MASK_LANGUAGE_EN = 0x02000000;
118 
119     /**
120      * Used to indicate which case the current input mode is in. For example,
121      * English QWERTY has lowercase and uppercase. For the Chinese QWERTY, these
122      * bits are ignored. For phone keyboard layout, these bits can be
123      * {@link #MASK_CASE_UPPER} to request symbol page for phone soft keyboard.
124      */
125     private static final int MASK_CASE = 0x00f00000;
126 
127     /**
128      * Used to indicate the current case information. An input mode should be
129      * anded with {@link #MASK_CASE} to get this information.
130      */
131     private static final int MASK_CASE_LOWER = 0x00100000;
132 
133     /**
134      * Used to indicate the current case information. An input mode should be
135      * anded with {@link #MASK_CASE} to get this information.
136      */
137     private static final int MASK_CASE_UPPER = 0x00200000;
138 
139     /**
140      * Mode for inputing Chinese with soft keyboard.
141      */
142     public static final int MODE_SKB_CHINESE = (MASK_SKB_LAYOUT_QWERTY | MASK_LANGUAGE_CN);
143 
144     /**
145      * Mode for inputing basic symbols for Chinese mode with soft keyboard.
146      */
147     public static final int MODE_SKB_SYMBOL1_CN = (MASK_SKB_LAYOUT_SYMBOL1 | MASK_LANGUAGE_CN);
148 
149     /**
150      * Mode for inputing more symbols for Chinese mode with soft keyboard.
151      */
152     public static final int MODE_SKB_SYMBOL2_CN = (MASK_SKB_LAYOUT_SYMBOL2 | MASK_LANGUAGE_CN);
153 
154     /**
155      * Mode for inputing English lower characters with soft keyboard.
156      */
157     public static final int MODE_SKB_ENGLISH_LOWER = (MASK_SKB_LAYOUT_QWERTY
158             | MASK_LANGUAGE_EN | MASK_CASE_LOWER);
159 
160     /**
161      * Mode for inputing English upper characters with soft keyboard.
162      */
163     public static final int MODE_SKB_ENGLISH_UPPER = (MASK_SKB_LAYOUT_QWERTY
164             | MASK_LANGUAGE_EN | MASK_CASE_UPPER);
165 
166     /**
167      * Mode for inputing basic symbols for English mode with soft keyboard.
168      */
169     public static final int MODE_SKB_SYMBOL1_EN = (MASK_SKB_LAYOUT_SYMBOL1 | MASK_LANGUAGE_EN);
170 
171     /**
172      * Mode for inputing more symbols for English mode with soft keyboard.
173      */
174     public static final int MODE_SKB_SYMBOL2_EN = (MASK_SKB_LAYOUT_SYMBOL2 | MASK_LANGUAGE_EN);
175 
176     /**
177      * Mode for inputing smileys with soft keyboard.
178      */
179     public static final int MODE_SKB_SMILEY = (MASK_SKB_LAYOUT_SMILEY | MASK_LANGUAGE_CN);
180 
181     /**
182      * Mode for inputing phone numbers.
183      */
184     public static final int MODE_SKB_PHONE_NUM = (MASK_SKB_LAYOUT_PHONE);
185 
186     /**
187      * Mode for inputing phone numbers.
188      */
189     public static final int MODE_SKB_PHONE_SYM = (MASK_SKB_LAYOUT_PHONE | MASK_CASE_UPPER);
190 
191     /**
192      * Mode for inputing Chinese with a hardware keyboard.
193      */
194     public static final int MODE_HKB_CHINESE = (MASK_LANGUAGE_CN);
195 
196     /**
197      * Mode for inputing English with a hardware keyboard
198      */
199     public static final int MODE_HKB_ENGLISH = (MASK_LANGUAGE_EN);
200 
201     /**
202      * Unset mode.
203      */
204     public static final int MODE_UNSET = 0;
205 
206     /**
207      * Maximum toggle states for a soft keyboard.
208      */
209     public static final int MAX_TOGGLE_STATES = 4;
210 
211     /**
212      * The input mode for the current edit box.
213      */
214     private int mInputMode = MODE_UNSET;
215 
216     /**
217      * Used to remember previous input mode. When user enters an edit field, the
218      * previous input mode will be tried. If the previous mode can not be used
219      * for the current situation (For example, previous mode is a soft keyboard
220      * mode to input symbols, and we have a hardware keyboard for the current
221      * situation), {@link #mRecentLauageInputMode} will be tried.
222      **/
223     private int mPreviousInputMode = MODE_SKB_CHINESE;
224 
225     /**
226      * Used to remember recent mode to input language.
227      */
228     private int mRecentLauageInputMode = MODE_SKB_CHINESE;
229 
230     /**
231      * Editor information of the current edit box.
232      */
233     private EditorInfo mEditorInfo;
234 
235     /**
236      * Used to indicate required toggling operations.
237      */
238     private ToggleStates mToggleStates = new ToggleStates();
239 
240     /**
241      * The current field is a short message field?
242      */
243     private boolean mShortMessageField;
244 
245     /**
246      * Is return key in normal state?
247      */
248     private boolean mEnterKeyNormal = true;
249 
250     /**
251      * Current icon. 0 for none icon.
252      */
253     int mInputIcon = R.drawable.ime_pinyin;
254 
255     /**
256      * IME service.
257      */
258     private PinyinIME mImeService;
259 
260     /**
261      * Key toggling state for Chinese mode.
262      */
263     private int mToggleStateCn;
264 
265     /**
266      * Key toggling state for Chinese mode with candidates.
267      */
268     private int mToggleStateCnCand;
269 
270     /**
271      * Key toggling state for English lowwercase mode.
272      */
273     private int mToggleStateEnLower;
274 
275     /**
276      * Key toggling state for English upppercase mode.
277      */
278     private int mToggleStateEnUpper;
279 
280     /**
281      * Key toggling state for English symbol mode for the first page.
282      */
283     private int mToggleStateEnSym1;
284 
285     /**
286      * Key toggling state for English symbol mode for the second page.
287      */
288     private int mToggleStateEnSym2;
289 
290     /**
291      * Key toggling state for smiley mode.
292      */
293     private int mToggleStateSmiley;
294 
295     /**
296      * Key toggling state for phone symbol mode.
297      */
298     private int mToggleStatePhoneSym;
299 
300     /**
301      * Key toggling state for GO action of ENTER key.
302      */
303     private int mToggleStateGo;
304 
305     /**
306      * Key toggling state for SEARCH action of ENTER key.
307      */
308     private int mToggleStateSearch;
309 
310     /**
311      * Key toggling state for SEND action of ENTER key.
312      */
313     private int mToggleStateSend;
314 
315     /**
316      * Key toggling state for NEXT action of ENTER key.
317      */
318     private int mToggleStateNext;
319 
320     /**
321      * Key toggling state for SEND action of ENTER key.
322      */
323     private int mToggleStateDone;
324 
325     /**
326      * QWERTY row toggling state for Chinese input.
327      */
328     private int mToggleRowCn;
329 
330     /**
331      * QWERTY row toggling state for English input.
332      */
333     private int mToggleRowEn;
334 
335     /**
336      * QWERTY row toggling state for URI input.
337      */
338     private int mToggleRowUri;
339 
340     /**
341      * QWERTY row toggling state for email address input.
342      */
343     private int mToggleRowEmailAddress;
344 
345     class ToggleStates {
346         /**
347          * If it is true, this soft keyboard is a QWERTY one.
348          */
349         boolean mQwerty;
350 
351         /**
352          * If {@link #mQwerty} is true, this variable is used to decide the
353          * letter case of the QWERTY keyboard.
354          */
355         boolean mQwertyUpperCase;
356 
357         /**
358          * The id of enabled row in the soft keyboard. Refer to
359          * {@link com.android.inputmethod.pinyin.SoftKeyboard.KeyRow} for
360          * details.
361          */
362         public int mRowIdToEnable;
363 
364         /**
365          * Used to store all other toggle states for the current input mode.
366          */
367         public int mKeyStates[] = new int[MAX_TOGGLE_STATES];
368 
369         /**
370          * Number of states to toggle.
371          */
372         public int mKeyStatesNum;
373     }
374 
InputModeSwitcher(PinyinIME imeService)375     public InputModeSwitcher(PinyinIME imeService) {
376         mImeService = imeService;
377         Resources r = mImeService.getResources();
378         mToggleStateCn = Integer.parseInt(r.getString(R.string.toggle_cn));
379         mToggleStateCnCand = Integer.parseInt(r
380                 .getString(R.string.toggle_cn_cand));
381         mToggleStateEnLower = Integer.parseInt(r
382                 .getString(R.string.toggle_en_lower));
383         mToggleStateEnUpper = Integer.parseInt(r
384                 .getString(R.string.toggle_en_upper));
385         mToggleStateEnSym1 = Integer.parseInt(r
386                 .getString(R.string.toggle_en_sym1));
387         mToggleStateEnSym2 = Integer.parseInt(r
388                 .getString(R.string.toggle_en_sym2));
389         mToggleStateSmiley = Integer.parseInt(r
390                 .getString(R.string.toggle_smiley));
391         mToggleStatePhoneSym = Integer.parseInt(r
392                 .getString(R.string.toggle_phone_sym));
393 
394         mToggleStateGo = Integer
395                 .parseInt(r.getString(R.string.toggle_enter_go));
396         mToggleStateSearch = Integer.parseInt(r
397                 .getString(R.string.toggle_enter_search));
398         mToggleStateSend = Integer.parseInt(r
399                 .getString(R.string.toggle_enter_send));
400         mToggleStateNext = Integer.parseInt(r
401                 .getString(R.string.toggle_enter_next));
402         mToggleStateDone = Integer.parseInt(r
403                 .getString(R.string.toggle_enter_done));
404 
405         mToggleRowCn = Integer.parseInt(r.getString(R.string.toggle_row_cn));
406         mToggleRowEn = Integer.parseInt(r.getString(R.string.toggle_row_en));
407         mToggleRowUri = Integer.parseInt(r.getString(R.string.toggle_row_uri));
408         mToggleRowEmailAddress = Integer.parseInt(r
409                 .getString(R.string.toggle_row_emailaddress));
410     }
411 
getInputMode()412     public int getInputMode() {
413         return mInputMode;
414     }
415 
getToggleStates()416     public ToggleStates getToggleStates() {
417         return mToggleStates;
418     }
419 
getSkbLayout()420     public int getSkbLayout() {
421         int layout = (mInputMode & MASK_SKB_LAYOUT);
422 
423         switch (layout) {
424         case MASK_SKB_LAYOUT_QWERTY:
425             return R.xml.skb_qwerty;
426         case MASK_SKB_LAYOUT_SYMBOL1:
427             return R.xml.skb_sym1;
428         case MASK_SKB_LAYOUT_SYMBOL2:
429             return R.xml.skb_sym2;
430         case MASK_SKB_LAYOUT_SMILEY:
431             return R.xml.skb_smiley;
432         case MASK_SKB_LAYOUT_PHONE:
433             return R.xml.skb_phone;
434         }
435         return 0;
436     }
437 
438     // Return the icon to update.
switchLanguageWithHkb()439     public int switchLanguageWithHkb() {
440         int newInputMode = MODE_HKB_CHINESE;
441         mInputIcon = R.drawable.ime_pinyin;
442 
443         if (MODE_HKB_CHINESE == mInputMode) {
444             newInputMode = MODE_HKB_ENGLISH;
445             mInputIcon = R.drawable.ime_en;
446         }
447 
448         saveInputMode(newInputMode);
449         return mInputIcon;
450     }
451 
452     // Return the icon to update.
switchModeForUserKey(int userKey)453     public int switchModeForUserKey(int userKey) {
454         int newInputMode = MODE_UNSET;
455 
456         if (USERDEF_KEYCODE_LANG_2 == userKey) {
457             if (MODE_SKB_CHINESE == mInputMode) {
458                 newInputMode = MODE_SKB_ENGLISH_LOWER;
459             } else if (MODE_SKB_ENGLISH_LOWER == mInputMode
460                     || MODE_SKB_ENGLISH_UPPER == mInputMode) {
461                 newInputMode = MODE_SKB_CHINESE;
462             } else if (MODE_SKB_SYMBOL1_CN == mInputMode) {
463                 newInputMode = MODE_SKB_SYMBOL1_EN;
464             } else if (MODE_SKB_SYMBOL1_EN == mInputMode) {
465                 newInputMode = MODE_SKB_SYMBOL1_CN;
466             } else if (MODE_SKB_SYMBOL2_CN == mInputMode) {
467                 newInputMode = MODE_SKB_SYMBOL2_EN;
468             } else if (MODE_SKB_SYMBOL2_EN == mInputMode) {
469                 newInputMode = MODE_SKB_SYMBOL2_CN;
470             } else if (MODE_SKB_SMILEY == mInputMode) {
471                 newInputMode = MODE_SKB_CHINESE;
472             }
473         } else if (USERDEF_KEYCODE_SYM_3 == userKey) {
474             if (MODE_SKB_CHINESE == mInputMode) {
475                 newInputMode = MODE_SKB_SYMBOL1_CN;
476             } else if (MODE_SKB_ENGLISH_UPPER == mInputMode
477                     || MODE_SKB_ENGLISH_LOWER == mInputMode) {
478                 newInputMode = MODE_SKB_SYMBOL1_EN;
479             } else if (MODE_SKB_SYMBOL1_EN == mInputMode
480                     || MODE_SKB_SYMBOL2_EN == mInputMode) {
481                 newInputMode = MODE_SKB_ENGLISH_LOWER;
482             } else if (MODE_SKB_SYMBOL1_CN == mInputMode
483                     || MODE_SKB_SYMBOL2_CN == mInputMode) {
484                 newInputMode = MODE_SKB_CHINESE;
485             } else if (MODE_SKB_SMILEY == mInputMode) {
486                 newInputMode = MODE_SKB_SYMBOL1_CN;
487             }
488         } else if (USERDEF_KEYCODE_SHIFT_1 == userKey) {
489             if (MODE_SKB_ENGLISH_LOWER == mInputMode) {
490                 newInputMode = MODE_SKB_ENGLISH_UPPER;
491             } else if (MODE_SKB_ENGLISH_UPPER == mInputMode) {
492                 newInputMode = MODE_SKB_ENGLISH_LOWER;
493             }
494         } else if (USERDEF_KEYCODE_MORE_SYM_5 == userKey) {
495             int sym = (MASK_SKB_LAYOUT & mInputMode);
496             if (MASK_SKB_LAYOUT_SYMBOL1 == sym) {
497                 sym = MASK_SKB_LAYOUT_SYMBOL2;
498             } else {
499                 sym = MASK_SKB_LAYOUT_SYMBOL1;
500             }
501             newInputMode = ((mInputMode & (~MASK_SKB_LAYOUT)) | sym);
502         } else if (USERDEF_KEYCODE_SMILEY_6 == userKey) {
503             if (MODE_SKB_CHINESE == mInputMode) {
504                 newInputMode = MODE_SKB_SMILEY;
505             } else {
506                 newInputMode = MODE_SKB_CHINESE;
507             }
508         } else if (USERDEF_KEYCODE_PHONE_SYM_4 == userKey) {
509             if (MODE_SKB_PHONE_NUM == mInputMode) {
510                 newInputMode = MODE_SKB_PHONE_SYM;
511             } else {
512                 newInputMode = MODE_SKB_PHONE_NUM;
513             }
514         }
515 
516         if (newInputMode == mInputMode || MODE_UNSET == newInputMode) {
517             return mInputIcon;
518         }
519 
520         saveInputMode(newInputMode);
521         prepareToggleStates(true);
522         return mInputIcon;
523     }
524 
525     // Return the icon to update.
requestInputWithHkb(EditorInfo editorInfo)526     public int requestInputWithHkb(EditorInfo editorInfo) {
527         mShortMessageField = false;
528         boolean english = false;
529         int newInputMode = MODE_HKB_CHINESE;
530 
531         switch (editorInfo.inputType & EditorInfo.TYPE_MASK_CLASS) {
532         case EditorInfo.TYPE_CLASS_NUMBER:
533         case EditorInfo.TYPE_CLASS_PHONE:
534         case EditorInfo.TYPE_CLASS_DATETIME:
535             english = true;
536             break;
537         case EditorInfo.TYPE_CLASS_TEXT:
538             int v = editorInfo.inputType & EditorInfo.TYPE_MASK_VARIATION;
539             if (v == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
540                     || v == EditorInfo.TYPE_TEXT_VARIATION_PASSWORD
541                     || v == EditorInfo.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
542                     || v == EditorInfo.TYPE_TEXT_VARIATION_URI) {
543                 english = true;
544             } else if (v == EditorInfo.TYPE_TEXT_VARIATION_SHORT_MESSAGE) {
545                 mShortMessageField = true;
546             }
547             break;
548         default:
549         }
550 
551         if (english) {
552             // If the application request English mode, we switch to it.
553             newInputMode = MODE_HKB_ENGLISH;
554         } else {
555             // If the application do not request English mode, we will
556             // try to keep the previous mode to input language text.
557             // Because there is not soft keyboard, we need discard all
558             // soft keyboard related information from the previous language
559             // mode.
560             if ((mRecentLauageInputMode & MASK_LANGUAGE) == MASK_LANGUAGE_CN) {
561                 newInputMode = MODE_HKB_CHINESE;
562             } else {
563                 newInputMode = MODE_HKB_ENGLISH;
564             }
565         }
566         mEditorInfo = editorInfo;
567         saveInputMode(newInputMode);
568         prepareToggleStates(false);
569         return mInputIcon;
570     }
571 
572     // Return the icon to update.
requestInputWithSkb(EditorInfo editorInfo)573     public int requestInputWithSkb(EditorInfo editorInfo) {
574         mShortMessageField = false;
575 
576         int newInputMode = MODE_SKB_CHINESE;
577 
578         switch (editorInfo.inputType & EditorInfo.TYPE_MASK_CLASS) {
579         case EditorInfo.TYPE_CLASS_NUMBER:
580         case EditorInfo.TYPE_CLASS_DATETIME:
581             newInputMode = MODE_SKB_SYMBOL1_EN;
582             break;
583         case EditorInfo.TYPE_CLASS_PHONE:
584             newInputMode = MODE_SKB_PHONE_NUM;
585             break;
586         case EditorInfo.TYPE_CLASS_TEXT:
587             int v = editorInfo.inputType & EditorInfo.TYPE_MASK_VARIATION;
588             if (v == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
589                     || v == EditorInfo.TYPE_TEXT_VARIATION_PASSWORD
590                     || v == EditorInfo.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
591                     || v == EditorInfo.TYPE_TEXT_VARIATION_URI) {
592                 // If the application request English mode, we switch to it.
593                 newInputMode = MODE_SKB_ENGLISH_LOWER;
594             } else {
595                 if (v == EditorInfo.TYPE_TEXT_VARIATION_SHORT_MESSAGE) {
596                     mShortMessageField = true;
597                 }
598                 // If the application do not request English mode, we will
599                 // try to keep the previous mode.
600                 int skbLayout = (mInputMode & MASK_SKB_LAYOUT);
601                 newInputMode = mInputMode;
602                 if (0 == skbLayout) {
603                     if ((mInputMode & MASK_LANGUAGE) == MASK_LANGUAGE_CN) {
604                         newInputMode = MODE_SKB_CHINESE;
605                     } else {
606                         newInputMode = MODE_SKB_ENGLISH_LOWER;
607                     }
608                 }
609             }
610             break;
611         default:
612             // Try to keep the previous mode.
613             int skbLayout = (mInputMode & MASK_SKB_LAYOUT);
614             newInputMode = mInputMode;
615             if (0 == skbLayout) {
616                 if ((mInputMode & MASK_LANGUAGE) == MASK_LANGUAGE_CN) {
617                     newInputMode = MODE_SKB_CHINESE;
618                 } else {
619                     newInputMode = MODE_SKB_ENGLISH_LOWER;
620                 }
621             }
622             break;
623         }
624 
625         mEditorInfo = editorInfo;
626         saveInputMode(newInputMode);
627         prepareToggleStates(true);
628         return mInputIcon;
629     }
630 
631     // Return the icon to update.
requestBackToPreviousSkb()632     public int requestBackToPreviousSkb() {
633         int layout = (mInputMode & MASK_SKB_LAYOUT);
634         int lastLayout = (mPreviousInputMode & MASK_SKB_LAYOUT);
635         if (0 != layout && 0 != lastLayout) {
636             mInputMode = mPreviousInputMode;
637             saveInputMode(mInputMode);
638             prepareToggleStates(true);
639             return mInputIcon;
640         }
641         return 0;
642     }
643 
getTooggleStateForCnCand()644     public int getTooggleStateForCnCand() {
645         return mToggleStateCnCand;
646     }
647 
isEnglishWithHkb()648     public boolean isEnglishWithHkb() {
649         return MODE_HKB_ENGLISH == mInputMode;
650     }
651 
isEnglishWithSkb()652     public boolean isEnglishWithSkb() {
653         return MODE_SKB_ENGLISH_LOWER == mInputMode
654                 || MODE_SKB_ENGLISH_UPPER == mInputMode;
655     }
656 
isEnglishUpperCaseWithSkb()657     public boolean isEnglishUpperCaseWithSkb() {
658         return MODE_SKB_ENGLISH_UPPER == mInputMode;
659     }
660 
isChineseText()661     public boolean isChineseText() {
662         int skbLayout = (mInputMode & MASK_SKB_LAYOUT);
663         if (MASK_SKB_LAYOUT_QWERTY == skbLayout || 0 == skbLayout) {
664             int language = (mInputMode & MASK_LANGUAGE);
665             if (MASK_LANGUAGE_CN == language) return true;
666         }
667         return false;
668     }
669 
isChineseTextWithHkb()670     public boolean isChineseTextWithHkb() {
671         int skbLayout = (mInputMode & MASK_SKB_LAYOUT);
672         if (0 == skbLayout) {
673             int language = (mInputMode & MASK_LANGUAGE);
674             if (MASK_LANGUAGE_CN == language) return true;
675         }
676         return false;
677     }
678 
isChineseTextWithSkb()679     public boolean isChineseTextWithSkb() {
680         int skbLayout = (mInputMode & MASK_SKB_LAYOUT);
681         if (MASK_SKB_LAYOUT_QWERTY == skbLayout) {
682             int language = (mInputMode & MASK_LANGUAGE);
683             if (MASK_LANGUAGE_CN == language) return true;
684         }
685         return false;
686     }
687 
isSymbolWithSkb()688     public boolean isSymbolWithSkb() {
689         int skbLayout = (mInputMode & MASK_SKB_LAYOUT);
690         if (MASK_SKB_LAYOUT_SYMBOL1 == skbLayout
691                 || MASK_SKB_LAYOUT_SYMBOL2 == skbLayout) {
692             return true;
693         }
694         return false;
695     }
696 
isEnterNoramlState()697     public boolean isEnterNoramlState() {
698         return mEnterKeyNormal;
699     }
700 
tryHandleLongPressSwitch(int keyCode)701     public boolean tryHandleLongPressSwitch(int keyCode) {
702         if (USERDEF_KEYCODE_LANG_2 == keyCode
703                 || USERDEF_KEYCODE_PHONE_SYM_4 == keyCode) {
704             mImeService.showOptionsMenu();
705             return true;
706         }
707         return false;
708     }
709 
saveInputMode(int newInputMode)710     private void saveInputMode(int newInputMode) {
711         mPreviousInputMode = mInputMode;
712         mInputMode = newInputMode;
713 
714         int skbLayout = (mInputMode & MASK_SKB_LAYOUT);
715         if (MASK_SKB_LAYOUT_QWERTY == skbLayout || 0 == skbLayout) {
716             mRecentLauageInputMode = mInputMode;
717         }
718 
719         mInputIcon = R.drawable.ime_pinyin;
720         if (isEnglishWithHkb()) {
721             mInputIcon = R.drawable.ime_en;
722         } else if (isChineseTextWithHkb()) {
723             mInputIcon = R.drawable.ime_pinyin;
724         }
725 
726         if (!Environment.getInstance().hasHardKeyboard()) {
727             mInputIcon = 0;
728         }
729     }
730 
prepareToggleStates(boolean needSkb)731     private void prepareToggleStates(boolean needSkb) {
732         mEnterKeyNormal = true;
733         if (!needSkb) return;
734 
735         mToggleStates.mQwerty = false;
736         mToggleStates.mKeyStatesNum = 0;
737 
738         int states[] = mToggleStates.mKeyStates;
739         int statesNum = 0;
740         // Toggle state for language.
741         int language = (mInputMode & MASK_LANGUAGE);
742         int layout = (mInputMode & MASK_SKB_LAYOUT);
743         int charcase = (mInputMode & MASK_CASE);
744         int variation = mEditorInfo.inputType & EditorInfo.TYPE_MASK_VARIATION;
745 
746         if (MASK_SKB_LAYOUT_PHONE != layout) {
747             if (MASK_LANGUAGE_CN == language) {
748                 // Chinese and Chinese symbol are always the default states,
749                 // do not add a toggling operation.
750                 if (MASK_SKB_LAYOUT_QWERTY == layout) {
751                     mToggleStates.mQwerty = true;
752                     mToggleStates.mQwertyUpperCase = true;
753                     if (mShortMessageField) {
754                         states[statesNum] = mToggleStateSmiley;
755                         statesNum++;
756                     }
757                 }
758             } else if (MASK_LANGUAGE_EN == language) {
759                 if (MASK_SKB_LAYOUT_QWERTY == layout) {
760                     mToggleStates.mQwerty = true;
761                     mToggleStates.mQwertyUpperCase = false;
762                     states[statesNum] = mToggleStateEnLower;
763                     if (MASK_CASE_UPPER == charcase) {
764                         mToggleStates.mQwertyUpperCase = true;
765                         states[statesNum] = mToggleStateEnUpper;
766                     }
767                     statesNum++;
768                 } else if (MASK_SKB_LAYOUT_SYMBOL1 == layout) {
769                     states[statesNum] = mToggleStateEnSym1;
770                     statesNum++;
771                 } else if (MASK_SKB_LAYOUT_SYMBOL2 == layout) {
772                     states[statesNum] = mToggleStateEnSym2;
773                     statesNum++;
774                 }
775             }
776 
777             // Toggle rows for QWERTY.
778             mToggleStates.mRowIdToEnable = KeyRow.DEFAULT_ROW_ID;
779             if (variation == EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS) {
780                 mToggleStates.mRowIdToEnable = mToggleRowEmailAddress;
781             } else if (variation == EditorInfo.TYPE_TEXT_VARIATION_URI) {
782                 mToggleStates.mRowIdToEnable = mToggleRowUri;
783             } else if (MASK_LANGUAGE_CN == language) {
784                 mToggleStates.mRowIdToEnable = mToggleRowCn;
785             } else if (MASK_LANGUAGE_EN == language) {
786                 mToggleStates.mRowIdToEnable = mToggleRowEn;
787             }
788         } else {
789             if (MASK_CASE_UPPER == charcase) {
790                 states[statesNum] = mToggleStatePhoneSym;
791                 statesNum++;
792             }
793         }
794 
795         // Toggle state for enter key.
796         int action = mEditorInfo.imeOptions
797                 & (EditorInfo.IME_MASK_ACTION | EditorInfo.IME_FLAG_NO_ENTER_ACTION);
798 
799         if (action == EditorInfo.IME_ACTION_GO) {
800             states[statesNum] = mToggleStateGo;
801             statesNum++;
802             mEnterKeyNormal = false;
803         } else if (action == EditorInfo.IME_ACTION_SEARCH) {
804             states[statesNum] = mToggleStateSearch;
805             statesNum++;
806             mEnterKeyNormal = false;
807         } else if (action == EditorInfo.IME_ACTION_SEND) {
808             states[statesNum] = mToggleStateSend;
809             statesNum++;
810             mEnterKeyNormal = false;
811         } else if (action == EditorInfo.IME_ACTION_NEXT) {
812             int f = mEditorInfo.inputType & EditorInfo.TYPE_MASK_FLAGS;
813             if (f != EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE) {
814                 states[statesNum] = mToggleStateNext;
815                 statesNum++;
816                 mEnterKeyNormal = false;
817             }
818         } else if (action == EditorInfo.IME_ACTION_DONE) {
819             states[statesNum] = mToggleStateDone;
820             statesNum++;
821             mEnterKeyNormal = false;
822         }
823         mToggleStates.mKeyStatesNum = statesNum;
824     }
825 }
826