1/*
2 * Copyright (C) 2013 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
17package com.android.inputmethod.event;
18
19import android.text.TextUtils;
20import android.view.KeyCharacterMap;
21
22import com.android.inputmethod.latin.Constants;
23
24/**
25 * A combiner that handles dead keys.
26 */
27public class DeadKeyCombiner implements Combiner {
28    final StringBuilder mDeadSequence = new StringBuilder();
29
30    @Override
31    public Event combine(final Event event) {
32        if (null == event) return null; // Just in case some combiner is broken
33        if (TextUtils.isEmpty(mDeadSequence)) {
34            if (event.isDead()) {
35                mDeadSequence.appendCodePoint(event.mCodePoint);
36            }
37            return event;
38        } else {
39            // TODO: Allow combining for several dead chars rather than only the first one.
40            // The framework doesn't know how to do this now.
41            final int deadCodePoint = mDeadSequence.codePointAt(0);
42            mDeadSequence.setLength(0);
43            final int resultingCodePoint =
44                    KeyCharacterMap.getDeadChar(deadCodePoint, event.mCodePoint);
45            if (0 == resultingCodePoint) {
46                // We can't combine both characters. We need to commit the dead key as a committable
47                // character, and the next char too unless it's a space (because as a special case,
48                // dead key + space should result in only the dead key being committed - that's
49                // how dead keys work).
50                // If the event is a space, we should commit the dead char alone, but if it's
51                // not, we need to commit both.
52                return Event.createCommittableEvent(deadCodePoint,
53                        Constants.CODE_SPACE == event.mCodePoint ? null : event /* next */);
54            } else {
55                // We could combine the characters.
56                return Event.createCommittableEvent(resultingCodePoint, null /* next */);
57            }
58        }
59    }
60
61}
62