WordComposer.java revision f7d6517d6b1a1dd88e2142e1a15703bb839be01b
1923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project/* 2443c360d0afdbab091994244f045f4756feaf2b4Jean-Baptiste Queru * Copyright (C) 2008 The Android Open Source Project 3923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * 4923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * use this file except in compliance with the License. You may obtain a copy of 6923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * the License at 7923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * 8923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * 10923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * License for the specific language governing permissions and limitations under 14923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * the License. 15923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 16923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 17923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectpackage com.android.inputmethod.latin; 18923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 19c83359f9746ca6f0269a1a7017b585c1a5cab9b8Jean Chalardimport com.android.inputmethod.keyboard.Keyboard; 206b1f500da451de56932a8b2a99c63857994ece85Jean Chalardimport com.android.inputmethod.keyboard.Key; 21887f11ee43ad621aa6ad93d535ab7f48dec73fc7Tadashi G. Takaokaimport com.android.inputmethod.keyboard.KeyDetector; 226b1f500da451de56932a8b2a99c63857994ece85Jean Chalardimport com.android.inputmethod.keyboard.LatinKeyboard; 23887f11ee43ad621aa6ad93d535ab7f48dec73fc7Tadashi G. Takaoka 24923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectimport java.util.ArrayList; 25c83359f9746ca6f0269a1a7017b585c1a5cab9b8Jean Chalardimport java.util.Arrays; 26923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 27923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project/** 28923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * A place to store the currently composing word with information such as adjacent key codes as well 29923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 30923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Projectpublic class WordComposer { 318fbd55229243cb66c03d5ea1f79dfb39f596590dsatok 32887f11ee43ad621aa6ad93d535ab7f48dec73fc7Tadashi G. Takaoka public static final int NOT_A_CODE = KeyDetector.NOT_A_CODE; 338fbd55229243cb66c03d5ea1f79dfb39f596590dsatok public static final int NOT_A_COORDINATE = -1; 34887f11ee43ad621aa6ad93d535ab7f48dec73fc7Tadashi G. Takaoka 35923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project /** 36923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * The list of unicode values for each keystroke (including surrounding keys) 37923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 389fbfd5877305ed19a20663630b498b6b3fdae942satok private ArrayList<int[]> mCodes; 398fbd55229243cb66c03d5ea1f79dfb39f596590dsatok 409fbfd5877305ed19a20663630b498b6b3fdae942satok private int[] mXCoordinates; 419fbfd5877305ed19a20663630b498b6b3fdae942satok private int[] mYCoordinates; 428fbd55229243cb66c03d5ea1f79dfb39f596590dsatok 439fbfd5877305ed19a20663630b498b6b3fdae942satok private StringBuilder mTypedWord; 44117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard // An auto-correction for this word out of the dictionary. 45117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard private CharSequence mAutoCorrection; 464a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani 474a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani private int mCapsCount; 481c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani 491c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani private boolean mAutoCapitalized; 50c83359f9746ca6f0269a1a7017b585c1a5cab9b8Jean Chalard // Cache this value for performance 51117fc18ed46496c81596f8207bba30a09c7317d1Jean Chalard private int mTrailingSingleQuotesCount; 52c83359f9746ca6f0269a1a7017b585c1a5cab9b8Jean Chalard 53923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project /** 540b4ae1f578e768eec4ada90aeb81d11acb10eb2eKen Wakasa * Whether the user chose to capitalize the first char of the word. 55923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 560b4ae1f578e768eec4ada90aeb81d11acb10eb2eKen Wakasa private boolean mIsFirstCharCapitalized; 57923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 58979f8690967ff5409fe18f5085858ccdb8e0ccf1satok public WordComposer() { 598fbd55229243cb66c03d5ea1f79dfb39f596590dsatok final int N = BinaryDictionary.MAX_WORD_LENGTH; 608fbd55229243cb66c03d5ea1f79dfb39f596590dsatok mCodes = new ArrayList<int[]>(N); 618fbd55229243cb66c03d5ea1f79dfb39f596590dsatok mTypedWord = new StringBuilder(N); 628fbd55229243cb66c03d5ea1f79dfb39f596590dsatok mXCoordinates = new int[N]; 638fbd55229243cb66c03d5ea1f79dfb39f596590dsatok mYCoordinates = new int[N]; 64117fc18ed46496c81596f8207bba30a09c7317d1Jean Chalard mTrailingSingleQuotesCount = 0; 65117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard mAutoCorrection = null; 66923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 67923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 68f733074aaecdfd6e89cfee2daff8a9c1233b60f1satok public WordComposer(WordComposer source) { 699fbfd5877305ed19a20663630b498b6b3fdae942satok init(source); 709fbfd5877305ed19a20663630b498b6b3fdae942satok } 719fbfd5877305ed19a20663630b498b6b3fdae942satok 729fbfd5877305ed19a20663630b498b6b3fdae942satok public void init(WordComposer source) { 738fbd55229243cb66c03d5ea1f79dfb39f596590dsatok mCodes = new ArrayList<int[]>(source.mCodes); 748fbd55229243cb66c03d5ea1f79dfb39f596590dsatok mTypedWord = new StringBuilder(source.mTypedWord); 75c83359f9746ca6f0269a1a7017b585c1a5cab9b8Jean Chalard mXCoordinates = Arrays.copyOf(source.mXCoordinates, source.mXCoordinates.length); 76c83359f9746ca6f0269a1a7017b585c1a5cab9b8Jean Chalard mYCoordinates = Arrays.copyOf(source.mYCoordinates, source.mYCoordinates.length); 77ea843f2a2404f4bc04fda494e475520162cfca27Tadashi G. Takaoka mCapsCount = source.mCapsCount; 78ea843f2a2404f4bc04fda494e475520162cfca27Tadashi G. Takaoka mIsFirstCharCapitalized = source.mIsFirstCharCapitalized; 79ea843f2a2404f4bc04fda494e475520162cfca27Tadashi G. Takaoka mAutoCapitalized = source.mAutoCapitalized; 80117fc18ed46496c81596f8207bba30a09c7317d1Jean Chalard mTrailingSingleQuotesCount = source.mTrailingSingleQuotesCount; 81117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard mAutoCorrection = null; 82979f8690967ff5409fe18f5085858ccdb8e0ccf1satok } 83979f8690967ff5409fe18f5085858ccdb8e0ccf1satok 84923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project /** 85923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Clear out the keys registered so far. 86923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 87923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void reset() { 88923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCodes.clear(); 89923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mTypedWord.setLength(0); 904a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani mCapsCount = 0; 91ea843f2a2404f4bc04fda494e475520162cfca27Tadashi G. Takaoka mIsFirstCharCapitalized = false; 92117fc18ed46496c81596f8207bba30a09c7317d1Jean Chalard mTrailingSingleQuotesCount = 0; 93117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard mAutoCorrection = null; 94923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 95923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 96923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project /** 97923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Number of keystrokes in the composing word. 98923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * @return the number of keystrokes 99923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 100ea843f2a2404f4bc04fda494e475520162cfca27Tadashi G. Takaoka public final int size() { 101ea843f2a2404f4bc04fda494e475520162cfca27Tadashi G. Takaoka return mTypedWord.length(); 102923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 103923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 104923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project /** 105923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Returns the codes at a particular position in the word. 106923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * @param index the position in the word 107923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * @return the unicode for the pressed and surrounding keys 108923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 109923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public int[] getCodesAt(int index) { 110923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project return mCodes.get(index); 111923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 112923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 1138fbd55229243cb66c03d5ea1f79dfb39f596590dsatok public int[] getXCoordinates() { 1148fbd55229243cb66c03d5ea1f79dfb39f596590dsatok return mXCoordinates; 1158fbd55229243cb66c03d5ea1f79dfb39f596590dsatok } 1168fbd55229243cb66c03d5ea1f79dfb39f596590dsatok 1178fbd55229243cb66c03d5ea1f79dfb39f596590dsatok public int[] getYCoordinates() { 1188fbd55229243cb66c03d5ea1f79dfb39f596590dsatok return mYCoordinates; 1198fbd55229243cb66c03d5ea1f79dfb39f596590dsatok } 1208fbd55229243cb66c03d5ea1f79dfb39f596590dsatok 121ea843f2a2404f4bc04fda494e475520162cfca27Tadashi G. Takaoka private static boolean isFirstCharCapitalized(int index, int codePoint, boolean previous) { 122ea843f2a2404f4bc04fda494e475520162cfca27Tadashi G. Takaoka if (index == 0) return Character.isUpperCase(codePoint); 123436a645ea837d36f7e0f81948d343fa6e166f33aTadashi G. Takaoka return previous && !Character.isUpperCase(codePoint); 124ea843f2a2404f4bc04fda494e475520162cfca27Tadashi G. Takaoka } 125ea843f2a2404f4bc04fda494e475520162cfca27Tadashi G. Takaoka 126923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project /** 127923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Add a new keystroke, with codes[0] containing the pressed key's unicode and the rest of 128923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * the array containing unicode for adjacent keys, sorted by reducing probability/proximity. 129923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * @param codes the array of unicode values 130923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 1318fbd55229243cb66c03d5ea1f79dfb39f596590dsatok public void add(int primaryCode, int[] codes, int x, int y) { 132ea843f2a2404f4bc04fda494e475520162cfca27Tadashi G. Takaoka final int newIndex = size(); 133923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mTypedWord.append((char) primaryCode); 134231cacd08075e88a2bcdf25f025206de524e880bAmith Yamasani correctPrimaryJuxtapos(primaryCode, codes); 135923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project mCodes.add(codes); 136ea843f2a2404f4bc04fda494e475520162cfca27Tadashi G. Takaoka if (newIndex < BinaryDictionary.MAX_WORD_LENGTH) { 137ea843f2a2404f4bc04fda494e475520162cfca27Tadashi G. Takaoka mXCoordinates[newIndex] = x; 138ea843f2a2404f4bc04fda494e475520162cfca27Tadashi G. Takaoka mYCoordinates[newIndex] = y; 1398fbd55229243cb66c03d5ea1f79dfb39f596590dsatok } 140ea843f2a2404f4bc04fda494e475520162cfca27Tadashi G. Takaoka mIsFirstCharCapitalized = isFirstCharCapitalized( 141ea843f2a2404f4bc04fda494e475520162cfca27Tadashi G. Takaoka newIndex, primaryCode, mIsFirstCharCapitalized); 142ea843f2a2404f4bc04fda494e475520162cfca27Tadashi G. Takaoka if (Character.isUpperCase(primaryCode)) mCapsCount++; 143117fc18ed46496c81596f8207bba30a09c7317d1Jean Chalard if (Keyboard.CODE_SINGLE_QUOTE == primaryCode) { 144117fc18ed46496c81596f8207bba30a09c7317d1Jean Chalard ++mTrailingSingleQuotesCount; 145117fc18ed46496c81596f8207bba30a09c7317d1Jean Chalard } else { 146117fc18ed46496c81596f8207bba30a09c7317d1Jean Chalard mTrailingSingleQuotesCount = 0; 147117fc18ed46496c81596f8207bba30a09c7317d1Jean Chalard } 148117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard mAutoCorrection = null; 149923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 150923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 151923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project /** 1526b1f500da451de56932a8b2a99c63857994ece85Jean Chalard * Internal method to retrieve reasonable proximity info for a character. 1536b1f500da451de56932a8b2a99c63857994ece85Jean Chalard */ 1546b1f500da451de56932a8b2a99c63857994ece85Jean Chalard private void addKeyInfo(final int codePoint, final LatinKeyboard keyboard, 1556b1f500da451de56932a8b2a99c63857994ece85Jean Chalard final KeyDetector keyDetector) { 1566b1f500da451de56932a8b2a99c63857994ece85Jean Chalard for (final Key key : keyboard.mKeys) { 1576b1f500da451de56932a8b2a99c63857994ece85Jean Chalard if (key.mCode == codePoint) { 1586b1f500da451de56932a8b2a99c63857994ece85Jean Chalard final int x = key.mX + key.mWidth / 2; 1596b1f500da451de56932a8b2a99c63857994ece85Jean Chalard final int y = key.mY + key.mHeight / 2; 1606b1f500da451de56932a8b2a99c63857994ece85Jean Chalard final int[] codes = keyDetector.newCodeArray(); 161e22baaadd314c80f835e2e96fb0dfc73838ac2cdTadashi G. Takaoka keyDetector.getKeyAndNearbyCodes(x, y, codes); 1626b1f500da451de56932a8b2a99c63857994ece85Jean Chalard add(codePoint, codes, x, y); 1636b1f500da451de56932a8b2a99c63857994ece85Jean Chalard return; 1646b1f500da451de56932a8b2a99c63857994ece85Jean Chalard } 1656b1f500da451de56932a8b2a99c63857994ece85Jean Chalard } 1666b1f500da451de56932a8b2a99c63857994ece85Jean Chalard add(codePoint, new int[] { codePoint }, 1676b1f500da451de56932a8b2a99c63857994ece85Jean Chalard WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE); 1686b1f500da451de56932a8b2a99c63857994ece85Jean Chalard } 1696b1f500da451de56932a8b2a99c63857994ece85Jean Chalard 1706b1f500da451de56932a8b2a99c63857994ece85Jean Chalard /** 1716b1f500da451de56932a8b2a99c63857994ece85Jean Chalard * Set the currently composing word to the one passed as an argument. 1726b1f500da451de56932a8b2a99c63857994ece85Jean Chalard * This will register NOT_A_COORDINATE for X and Ys, and use the passed keyboard for proximity. 1736b1f500da451de56932a8b2a99c63857994ece85Jean Chalard */ 1746b1f500da451de56932a8b2a99c63857994ece85Jean Chalard public void setComposingWord(final CharSequence word, final LatinKeyboard keyboard, 1756b1f500da451de56932a8b2a99c63857994ece85Jean Chalard final KeyDetector keyDetector) { 1766b1f500da451de56932a8b2a99c63857994ece85Jean Chalard reset(); 1776b1f500da451de56932a8b2a99c63857994ece85Jean Chalard final int length = word.length(); 1786b1f500da451de56932a8b2a99c63857994ece85Jean Chalard for (int i = 0; i < length; ++i) { 1796b1f500da451de56932a8b2a99c63857994ece85Jean Chalard int codePoint = word.charAt(i); 1806b1f500da451de56932a8b2a99c63857994ece85Jean Chalard addKeyInfo(codePoint, keyboard, keyDetector); 1816b1f500da451de56932a8b2a99c63857994ece85Jean Chalard } 182117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard mAutoCorrection = null; 1836b1f500da451de56932a8b2a99c63857994ece85Jean Chalard } 1846b1f500da451de56932a8b2a99c63857994ece85Jean Chalard 1856b1f500da451de56932a8b2a99c63857994ece85Jean Chalard /** 1866b1f500da451de56932a8b2a99c63857994ece85Jean Chalard * Shortcut for the above method, this will create a new KeyDetector for the passed keyboard. 1876b1f500da451de56932a8b2a99c63857994ece85Jean Chalard */ 1886b1f500da451de56932a8b2a99c63857994ece85Jean Chalard public void setComposingWord(final CharSequence word, final LatinKeyboard keyboard) { 1896b1f500da451de56932a8b2a99c63857994ece85Jean Chalard final KeyDetector keyDetector = new KeyDetector(0); 1906b1f500da451de56932a8b2a99c63857994ece85Jean Chalard keyDetector.setKeyboard(keyboard, 0, 0); 1916b1f500da451de56932a8b2a99c63857994ece85Jean Chalard keyDetector.setProximityCorrectionEnabled(true); 1926b1f500da451de56932a8b2a99c63857994ece85Jean Chalard keyDetector.setProximityThreshold(keyboard.mMostCommonKeyWidth); 1936b1f500da451de56932a8b2a99c63857994ece85Jean Chalard setComposingWord(word, keyboard, keyDetector); 1946b1f500da451de56932a8b2a99c63857994ece85Jean Chalard } 1956b1f500da451de56932a8b2a99c63857994ece85Jean Chalard 1966b1f500da451de56932a8b2a99c63857994ece85Jean Chalard /** 197231cacd08075e88a2bcdf25f025206de524e880bAmith Yamasani * Swaps the first and second values in the codes array if the primary code is not the first 198231cacd08075e88a2bcdf25f025206de524e880bAmith Yamasani * value in the array but the second. This happens when the preferred key is not the key that 199231cacd08075e88a2bcdf25f025206de524e880bAmith Yamasani * the user released the finger on. 200231cacd08075e88a2bcdf25f025206de524e880bAmith Yamasani * @param primaryCode the preferred character 201231cacd08075e88a2bcdf25f025206de524e880bAmith Yamasani * @param codes array of codes based on distance from touch point 202231cacd08075e88a2bcdf25f025206de524e880bAmith Yamasani */ 2038fbf29e2d54027a17993cd0d4ad486e3454b56f6Tadashi G. Takaoka private static void correctPrimaryJuxtapos(int primaryCode, int[] codes) { 204231cacd08075e88a2bcdf25f025206de524e880bAmith Yamasani if (codes.length < 2) return; 205231cacd08075e88a2bcdf25f025206de524e880bAmith Yamasani if (codes[0] > 0 && codes[1] > 0 && codes[0] != primaryCode && codes[1] == primaryCode) { 206231cacd08075e88a2bcdf25f025206de524e880bAmith Yamasani codes[1] = codes[0]; 207231cacd08075e88a2bcdf25f025206de524e880bAmith Yamasani codes[0] = primaryCode; 208231cacd08075e88a2bcdf25f025206de524e880bAmith Yamasani } 209231cacd08075e88a2bcdf25f025206de524e880bAmith Yamasani } 210231cacd08075e88a2bcdf25f025206de524e880bAmith Yamasani 211231cacd08075e88a2bcdf25f025206de524e880bAmith Yamasani /** 212923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Delete the last keystroke as a result of hitting backspace. 213923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 214923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project public void deleteLast() { 215ea843f2a2404f4bc04fda494e475520162cfca27Tadashi G. Takaoka final int size = size(); 216ea843f2a2404f4bc04fda494e475520162cfca27Tadashi G. Takaoka if (size > 0) { 217ea843f2a2404f4bc04fda494e475520162cfca27Tadashi G. Takaoka final int lastPos = size - 1; 218ea843f2a2404f4bc04fda494e475520162cfca27Tadashi G. Takaoka char lastChar = mTypedWord.charAt(lastPos); 219ea843f2a2404f4bc04fda494e475520162cfca27Tadashi G. Takaoka mCodes.remove(lastPos); 220d1a8e3088bb6267a31e3351d304796d1507e3af6Tadashi G. Takaoka mTypedWord.deleteCharAt(lastPos); 221ea843f2a2404f4bc04fda494e475520162cfca27Tadashi G. Takaoka if (Character.isUpperCase(lastChar)) mCapsCount--; 222d1a8e3088bb6267a31e3351d304796d1507e3af6Tadashi G. Takaoka } 223ea843f2a2404f4bc04fda494e475520162cfca27Tadashi G. Takaoka if (size() == 0) { 224ea843f2a2404f4bc04fda494e475520162cfca27Tadashi G. Takaoka mIsFirstCharCapitalized = false; 225117fc18ed46496c81596f8207bba30a09c7317d1Jean Chalard } 226117fc18ed46496c81596f8207bba30a09c7317d1Jean Chalard if (mTrailingSingleQuotesCount > 0) { 227117fc18ed46496c81596f8207bba30a09c7317d1Jean Chalard --mTrailingSingleQuotesCount; 228c83359f9746ca6f0269a1a7017b585c1a5cab9b8Jean Chalard } else { 229117fc18ed46496c81596f8207bba30a09c7317d1Jean Chalard for (int i = mTypedWord.length() - 1; i >= 0; --i) { 230117fc18ed46496c81596f8207bba30a09c7317d1Jean Chalard if (Keyboard.CODE_SINGLE_QUOTE != mTypedWord.codePointAt(i)) break; 231117fc18ed46496c81596f8207bba30a09c7317d1Jean Chalard ++mTrailingSingleQuotesCount; 232117fc18ed46496c81596f8207bba30a09c7317d1Jean Chalard } 2338fbd55229243cb66c03d5ea1f79dfb39f596590dsatok } 234117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard mAutoCorrection = null; 235923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 236923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 237923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project /** 238923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Returns the word as it was typed, without any correction applied. 239117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard * @return the word that was typed so far. Never returns null. 240923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 2415c08151c227d98031abe27c3f0a8f43a7126ae9dJean Chalard public String getTypedWord() { 2425c08151c227d98031abe27c3f0a8f43a7126ae9dJean Chalard return mTypedWord.toString(); 243923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 244923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project 245923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project /** 246923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * Whether or not the user typed a capital letter as the first letter in the word 247923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project * @return capitalization preference 248923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project */ 2490b4ae1f578e768eec4ada90aeb81d11acb10eb2eKen Wakasa public boolean isFirstCharCapitalized() { 2500b4ae1f578e768eec4ada90aeb81d11acb10eb2eKen Wakasa return mIsFirstCharCapitalized; 251923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project } 2520b4ae1f578e768eec4ada90aeb81d11acb10eb2eKen Wakasa 253117fc18ed46496c81596f8207bba30a09c7317d1Jean Chalard public int trailingSingleQuotesCount() { 254117fc18ed46496c81596f8207bba30a09c7317d1Jean Chalard return mTrailingSingleQuotesCount; 255c83359f9746ca6f0269a1a7017b585c1a5cab9b8Jean Chalard } 256c83359f9746ca6f0269a1a7017b585c1a5cab9b8Jean Chalard 2570b4ae1f578e768eec4ada90aeb81d11acb10eb2eKen Wakasa /** 2580b4ae1f578e768eec4ada90aeb81d11acb10eb2eKen Wakasa * Whether or not all of the user typed chars are upper case 2590b4ae1f578e768eec4ada90aeb81d11acb10eb2eKen Wakasa * @return true if all user typed chars are upper case, false otherwise 2600b4ae1f578e768eec4ada90aeb81d11acb10eb2eKen Wakasa */ 2610b4ae1f578e768eec4ada90aeb81d11acb10eb2eKen Wakasa public boolean isAllUpperCase() { 2620b4ae1f578e768eec4ada90aeb81d11acb10eb2eKen Wakasa return (mCapsCount > 0) && (mCapsCount == size()); 2630b4ae1f578e768eec4ada90aeb81d11acb10eb2eKen Wakasa } 2640b4ae1f578e768eec4ada90aeb81d11acb10eb2eKen Wakasa 265923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project /** 2664a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani * Returns true if more than one character is upper case, otherwise returns false. 2674a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani */ 2684a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani public boolean isMostlyCaps() { 2694a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani return mCapsCount > 1; 2704a7ff90d513f8b6cbf39688c08be0828a57e311bAmith Yamasani } 2711c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani 2721c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani /** 2731c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani * Saves the reason why the word is capitalized - whether it was automatic or 2741c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani * due to the user hitting shift in the middle of a sentence. 2751c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani * @param auto whether it was an automatic capitalization due to start of sentence 2761c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani */ 2771c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani public void setAutoCapitalized(boolean auto) { 2781c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani mAutoCapitalized = auto; 2791c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 2801c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani 2811c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani /** 2821c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani * Returns whether the word was automatically capitalized. 2831c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani * @return whether the word was automatically capitalized 2841c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani */ 2851c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani public boolean isAutoCapitalized() { 2861c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani return mAutoCapitalized; 2871c551251106e506c70fad7ba0cb8b1e2a7dff3a9Amith Yamasani } 288117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard 289117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard /** 290117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard * Sets the auto-correction for this word. 291117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard */ 292117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard public void setAutoCorrection(final CharSequence correction) { 293117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard mAutoCorrection = correction; 294117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard } 295117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard 296117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard /** 297117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard * Remove any auto-correction that may have been set. 298117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard */ 299117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard public void deleteAutoCorrection() { 300117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard mAutoCorrection = null; 301117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard } 302117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard 303117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard /** 304f7d6517d6b1a1dd88e2142e1a15703bb839be01bJean Chalard * @return the auto-correction for this word, or null if none. 305117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard */ 306117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard public CharSequence getAutoCorrectionOrNull() { 307117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard return mAutoCorrection; 308117fc93f373cb86d4120c1261f9d0562c6529fecJean Chalard } 309923bf41f853a544fd0d71fbf7dc90359ec35981The Android Open Source Project} 310