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