RecapitalizeStatus.java revision 2a81943d162383cc6e9d9429bf3f7949c994a8ba
12995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard/* 22995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard * Copyright (C) 2013 The Android Open Source Project 32995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard * 42995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard * Licensed under the Apache License, Version 2.0 (the "License"); you may not 52995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard * use this file except in compliance with the License. You may obtain a copy of 62995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard * the License at 72995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard * 82995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard * http://www.apache.org/licenses/LICENSE-2.0 92995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard * 102995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard * Unless required by applicable law or agreed to in writing, software 112995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 122995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 132995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard * License for the specific language governing permissions and limitations under 142995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard * the License. 152995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard */ 162995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard 172995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalardpackage com.android.inputmethod.latin; 182995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard 192995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalardimport com.android.inputmethod.latin.StringUtils; 202995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard 212995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalardimport java.util.Locale; 222995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard 232995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard/** 242995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard * The status of the current recapitalize process. 252995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard */ 262995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalardpublic class RecapitalizeStatus { 278094bf45d73a5f7257076afc97d91d6708ee03c4Jean Chalard public static final int NOT_A_RECAPITALIZE_MODE = -1; 282995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard public static final int CAPS_MODE_ORIGINAL_MIXED_CASE = 0; 292995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard public static final int CAPS_MODE_ALL_LOWER = 1; 302995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard public static final int CAPS_MODE_FIRST_WORD_UPPER = 2; 312995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard public static final int CAPS_MODE_ALL_UPPER = 3; 322995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard // When adding a new mode, don't forget to update the CAPS_MODE_LAST constant. 332995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard public static final int CAPS_MODE_LAST = CAPS_MODE_ALL_UPPER; 342995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard 352995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard private static final int[] ROTATION_STYLE = { 362995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard CAPS_MODE_ORIGINAL_MIXED_CASE, 372995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard CAPS_MODE_ALL_LOWER, 382995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard CAPS_MODE_FIRST_WORD_UPPER, 392995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard CAPS_MODE_ALL_UPPER 402995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard }; 41b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard 422995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard private static final int getStringMode(final String string, final String separators) { 432995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard if (StringUtils.isIdenticalAfterUpcase(string)) { 442995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard return CAPS_MODE_ALL_UPPER; 452995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard } else if (StringUtils.isIdenticalAfterDowncase(string)) { 462995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard return CAPS_MODE_ALL_LOWER; 472995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard } else if (StringUtils.isIdenticalAfterCapitalizeEachWord(string, separators)) { 482995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard return CAPS_MODE_FIRST_WORD_UPPER; 492995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard } else { 502995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard return CAPS_MODE_ORIGINAL_MIXED_CASE; 512995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard } 522995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard } 532995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard 542995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard /** 55b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard * We store the location of the cursor and the string that was there before the recapitalize 562995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard * action was done, and the location of the cursor and the string that was there after. 572995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard */ 582995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard private int mCursorStartBefore; 592995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard private String mStringBefore; 602995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard private int mCursorStartAfter; 612995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard private int mCursorEndAfter; 622995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard private int mRotationStyleCurrentIndex; 63b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard private boolean mSkipOriginalMixedCaseMode; 64b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard private Locale mLocale; 65b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard private String mSeparators; 662995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard private String mStringAfter; 67b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard private boolean mIsActive; 68b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard 69b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard public RecapitalizeStatus() { 70b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard // By default, initialize with dummy values that won't match any real recapitalize. 71b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard initialize(-1, -1, "", Locale.getDefault(), ""); 72b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard deactivate(); 73b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard } 742995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard 75b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard public void initialize(final int cursorStart, final int cursorEnd, final String string, 762995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard final Locale locale, final String separators) { 772995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard mCursorStartBefore = cursorStart; 782995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard mStringBefore = string; 792995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard mCursorStartAfter = cursorStart; 802995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard mCursorEndAfter = cursorEnd; 812995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard mStringAfter = string; 822995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard final int initialMode = getStringMode(mStringBefore, separators); 832995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard mLocale = locale; 842995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard mSeparators = separators; 852995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard if (CAPS_MODE_ORIGINAL_MIXED_CASE == initialMode) { 862995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard mRotationStyleCurrentIndex = 0; 872995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard mSkipOriginalMixedCaseMode = false; 882995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard } else { 892995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard // Find the current mode in the array. 902995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard int currentMode; 912995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard for (currentMode = ROTATION_STYLE.length - 1; currentMode > 0; --currentMode) { 922995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard if (ROTATION_STYLE[currentMode] == initialMode) { 932995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard break; 942995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard } 952995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard } 962995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard mRotationStyleCurrentIndex = currentMode; 972995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard mSkipOriginalMixedCaseMode = true; 982995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard } 99b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard mIsActive = true; 100b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard } 101b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard 102b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard public void deactivate() { 103b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard mIsActive = false; 104b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard } 105b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard 106b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard public boolean isActive() { 107b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard return mIsActive; 1082995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard } 1092995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard 1102995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard public boolean isSetAt(final int cursorStart, final int cursorEnd) { 1112995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard return cursorStart == mCursorStartAfter && cursorEnd == mCursorEndAfter; 1122995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard } 1132995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard 1142995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard /** 1152995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard * Rotate through the different possible capitalization modes. 1162995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard */ 1172995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard public void rotate() { 1182995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard final String oldResult = mStringAfter; 1192995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard int count = 0; // Protection against infinite loop. 1202995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard do { 1212995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard mRotationStyleCurrentIndex = (mRotationStyleCurrentIndex + 1) % ROTATION_STYLE.length; 1222995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard if (CAPS_MODE_ORIGINAL_MIXED_CASE == ROTATION_STYLE[mRotationStyleCurrentIndex] 1232995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard && mSkipOriginalMixedCaseMode) { 1242995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard mRotationStyleCurrentIndex = 1252995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard (mRotationStyleCurrentIndex + 1) % ROTATION_STYLE.length; 1262995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard } 1272995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard ++count; 1282995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard switch (ROTATION_STYLE[mRotationStyleCurrentIndex]) { 129b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard case CAPS_MODE_ORIGINAL_MIXED_CASE: 130b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard mStringAfter = mStringBefore; 131b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard break; 132b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard case CAPS_MODE_ALL_LOWER: 133b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard mStringAfter = mStringBefore.toLowerCase(mLocale); 134b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard break; 135b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard case CAPS_MODE_FIRST_WORD_UPPER: 136b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard mStringAfter = StringUtils.capitalizeEachWord(mStringBefore, mSeparators, 137b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard mLocale); 138b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard break; 139b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard case CAPS_MODE_ALL_UPPER: 140b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard mStringAfter = mStringBefore.toUpperCase(mLocale); 141b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard break; 142b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard default: 143b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard mStringAfter = mStringBefore; 1442995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard } 145b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard } while (mStringAfter.equals(oldResult) && count < ROTATION_STYLE.length + 1); 1462995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard mCursorEndAfter = mCursorStartAfter + mStringAfter.length(); 1472995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard } 1482995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard 1492995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard /** 1502995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard * Remove leading/trailing whitespace from the considered string. 1512995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard */ 1522995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard public void trim() { 1532995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard final int len = mStringBefore.length(); 1542995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard int nonWhitespaceStart = 0; 1552995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard for (; nonWhitespaceStart < len; 1562995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard nonWhitespaceStart = mStringBefore.offsetByCodePoints(nonWhitespaceStart, 1)) { 1572995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard final int codePoint = mStringBefore.codePointAt(nonWhitespaceStart); 1582995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard if (!Character.isWhitespace(codePoint)) break; 1592995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard } 1602995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard int nonWhitespaceEnd = len; 1612995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard for (; nonWhitespaceEnd > 0; 1622995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard nonWhitespaceEnd = mStringBefore.offsetByCodePoints(nonWhitespaceEnd, -1)) { 1632995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard final int codePoint = mStringBefore.codePointBefore(nonWhitespaceEnd); 1642995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard if (!Character.isWhitespace(codePoint)) break; 1652995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard } 1662a81943d162383cc6e9d9429bf3f7949c994a8baJean Chalard // If nonWhitespaceStart >= nonWhitespaceEnd, that means the selection contained only 1672a81943d162383cc6e9d9429bf3f7949c994a8baJean Chalard // whitespace, so we leave it as is. 1682a81943d162383cc6e9d9429bf3f7949c994a8baJean Chalard if ((0 != nonWhitespaceStart || len != nonWhitespaceEnd) 1692a81943d162383cc6e9d9429bf3f7949c994a8baJean Chalard && nonWhitespaceStart < nonWhitespaceEnd) { 170b794e904a3586ac5f2d31fb24d5a1a8f9aa964b8Jean Chalard mCursorEndAfter = mCursorStartBefore + nonWhitespaceEnd; 1712995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard mCursorStartBefore = mCursorStartAfter = mCursorStartBefore + nonWhitespaceStart; 1722995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard mStringAfter = mStringBefore = 1732995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard mStringBefore.substring(nonWhitespaceStart, nonWhitespaceEnd); 1742995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard } 1752995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard } 1762995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard 1772995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard public String getRecapitalizedString() { 1782995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard return mStringAfter; 1792995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard } 1802995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard 1812995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard public int getNewCursorStart() { 1822995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard return mCursorStartAfter; 1832995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard } 1842995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard 1852995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard public int getNewCursorEnd() { 1862995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard return mCursorEndAfter; 1872995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard } 1888094bf45d73a5f7257076afc97d91d6708ee03c4Jean Chalard 1898094bf45d73a5f7257076afc97d91d6708ee03c4Jean Chalard public int getCurrentMode() { 1908094bf45d73a5f7257076afc97d91d6708ee03c4Jean Chalard return ROTATION_STYLE[mRotationStyleCurrentIndex]; 1918094bf45d73a5f7257076afc97d91d6708ee03c4Jean Chalard } 1922995abe7aadd483aa57a9b088740d46ac07bbe46Jean Chalard} 193