/**
  * Apply a processed input event.
  *
  * <p>All input events should be supported, including software/hardware events, characters as well
  * as deletions, multiple inputs and gestures.
  *
  * @param event the event to apply. Must not be null.
  */
 public void applyProcessedEvent(final Event event) {
   mCombinerChain.applyProcessedEvent(event);
   final int primaryCode = event.mCodePoint;
   final int keyX = event.mX;
   final int keyY = event.mY;
   final int newIndex = size();
   refreshTypedWordCache();
   mCursorPositionWithinWord = mCodePointSize;
   // We may have deleted the last one.
   if (0 == mCodePointSize) {
     mIsOnlyFirstCharCapitalized = false;
   }
   if (Constants.CODE_DELETE != event.mKeyCode) {
     if (newIndex < MAX_WORD_LENGTH) {
       // In the batch input mode, the {@code mInputPointers} holds batch input points and
       // shouldn't be overridden by the "typed key" coordinates
       // (See {@link #setBatchInputWord}).
       if (!mIsBatchMode) {
         // TODO: Set correct pointer id and time
         mInputPointers.addPointerAt(newIndex, keyX, keyY, 0, 0);
       }
     }
     if (0 == newIndex) {
       mIsOnlyFirstCharCapitalized = Character.isUpperCase(primaryCode);
     } else {
       mIsOnlyFirstCharCapitalized =
           mIsOnlyFirstCharCapitalized && !Character.isUpperCase(primaryCode);
     }
     if (Character.isUpperCase(primaryCode)) mCapsCount++;
     if (Character.isDigit(primaryCode)) mDigitsCount++;
   }
   mAutoCorrection = null;
 }
 public void resumeSuggestionOnLastComposedWord(final LastComposedWord lastComposedWord) {
   mEvents.clear();
   Collections.copy(mEvents, lastComposedWord.mEvents);
   mInputPointers.set(lastComposedWord.mInputPointers);
   mCombinerChain.reset();
   refreshTypedWordCache();
   mCapitalizedMode = lastComposedWord.mCapitalizedMode;
   mAutoCorrection = null; // This will be filled by the next call to updateSuggestion.
   mCursorPositionWithinWord = mCodePointSize;
   mRejectedBatchModeSuggestion = null;
   mIsResumed = true;
 }
 // `type' should be one of the LastComposedWord.COMMIT_TYPE_* constants above.
 // committedWord should contain suggestion spans if applicable.
 public LastComposedWord commitWord(
     final int type,
     final CharSequence committedWord,
     final String separatorString,
     final NgramContext ngramContext) {
   // Note: currently, we come here whenever we commit a word. If it's a MANUAL_PICK
   // or a DECIDED_WORD we may cancel the commit later; otherwise, we should deactivate
   // the last composed word to ensure this does not happen.
   final LastComposedWord lastComposedWord =
       new LastComposedWord(
           mEvents,
           mInputPointers,
           mTypedWordCache.toString(),
           committedWord,
           separatorString,
           ngramContext,
           mCapitalizedMode);
   mInputPointers.reset();
   if (type != LastComposedWord.COMMIT_TYPE_DECIDED_WORD
       && type != LastComposedWord.COMMIT_TYPE_MANUAL_PICK) {
     lastComposedWord.deactivate();
   }
   mCapsCount = 0;
   mDigitsCount = 0;
   mIsBatchMode = false;
   mCombinerChain.reset();
   mEvents.clear();
   mCodePointSize = 0;
   mIsOnlyFirstCharCapitalized = false;
   mCapitalizedMode = CAPS_MODE_OFF;
   refreshTypedWordCache();
   mAutoCorrection = null;
   mCursorPositionWithinWord = 0;
   mIsResumed = false;
   mRejectedBatchModeSuggestion = null;
   return lastComposedWord;
 }
 void addInputPointerForTest(int index, int keyX, int keyY) {
   mInputPointers.addPointerAt(index, keyX, keyY, 0, 0);
 }
 public void setBatchInputPointers(final InputPointers batchPointers) {
   mInputPointers.set(batchPointers);
   mIsBatchMode = true;
 }