mirror of
https://github.com/Helium314/HeliBoard.git
synced 2025-06-23 17:40:54 +00:00
Merge pull request #90 from alexandrius/master
Fix Georgian automatic uppercase since Georgian script doesn't have uppercase
This commit is contained in:
commit
363e27dc5e
5 changed files with 234 additions and 200 deletions
|
@ -36,6 +36,7 @@ import org.dslul.openboard.inputmethod.keyboard.internal.UniqueKeysCache;
|
||||||
import org.dslul.openboard.inputmethod.latin.InputAttributes;
|
import org.dslul.openboard.inputmethod.latin.InputAttributes;
|
||||||
import org.dslul.openboard.inputmethod.latin.R;
|
import org.dslul.openboard.inputmethod.latin.R;
|
||||||
import org.dslul.openboard.inputmethod.latin.RichInputMethodSubtype;
|
import org.dslul.openboard.inputmethod.latin.RichInputMethodSubtype;
|
||||||
|
import org.dslul.openboard.inputmethod.latin.common.StringUtils;
|
||||||
import org.dslul.openboard.inputmethod.latin.utils.InputTypeUtils;
|
import org.dslul.openboard.inputmethod.latin.utils.InputTypeUtils;
|
||||||
import org.dslul.openboard.inputmethod.latin.utils.ScriptUtils;
|
import org.dslul.openboard.inputmethod.latin.utils.ScriptUtils;
|
||||||
import org.dslul.openboard.inputmethod.latin.utils.SubtypeLocaleUtils;
|
import org.dslul.openboard.inputmethod.latin.utils.SubtypeLocaleUtils;
|
||||||
|
@ -104,7 +105,9 @@ public final class KeyboardLayoutSet {
|
||||||
boolean mProximityCharsCorrectionEnabled;
|
boolean mProximityCharsCorrectionEnabled;
|
||||||
boolean mSupportsSplitLayout;
|
boolean mSupportsSplitLayout;
|
||||||
boolean mAllowRedundantMoreKeys;
|
boolean mAllowRedundantMoreKeys;
|
||||||
public ElementParams() {}
|
|
||||||
|
public ElementParams() {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class Params {
|
public static final class Params {
|
||||||
|
@ -147,7 +150,7 @@ public final class KeyboardLayoutSet {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getScriptId(final Resources resources,
|
public static int getScriptId(final Resources resources,
|
||||||
@Nonnull final InputMethodSubtype subtype) {
|
@Nonnull final InputMethodSubtype subtype) {
|
||||||
final Integer value = sScriptIdsForSubtypes.get(subtype);
|
final Integer value = sScriptIdsForSubtypes.get(subtype);
|
||||||
if (null == value) {
|
if (null == value) {
|
||||||
final int scriptId = Builder.readScriptId(resources, subtype);
|
final int scriptId = Builder.readScriptId(resources, subtype);
|
||||||
|
@ -162,26 +165,28 @@ public final class KeyboardLayoutSet {
|
||||||
mParams = params;
|
mParams = params;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final String LOCALE_GEORGIAN = "ka";
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public Keyboard getKeyboard(final int baseKeyboardLayoutSetElementId) {
|
public Keyboard getKeyboard(final int baseKeyboardLayoutSetElementId) {
|
||||||
final int keyboardLayoutSetElementId;
|
final int keyboardLayoutSetElementId;
|
||||||
switch (mParams.mMode) {
|
switch (mParams.mMode) {
|
||||||
case KeyboardId.MODE_PHONE:
|
case KeyboardId.MODE_PHONE:
|
||||||
if (baseKeyboardLayoutSetElementId == KeyboardId.ELEMENT_SYMBOLS) {
|
if (baseKeyboardLayoutSetElementId == KeyboardId.ELEMENT_SYMBOLS) {
|
||||||
keyboardLayoutSetElementId = KeyboardId.ELEMENT_PHONE_SYMBOLS;
|
keyboardLayoutSetElementId = KeyboardId.ELEMENT_PHONE_SYMBOLS;
|
||||||
} else {
|
} else {
|
||||||
keyboardLayoutSetElementId = KeyboardId.ELEMENT_PHONE;
|
keyboardLayoutSetElementId = KeyboardId.ELEMENT_PHONE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case KeyboardId.MODE_NUMBER:
|
case KeyboardId.MODE_NUMBER:
|
||||||
case KeyboardId.MODE_DATE:
|
case KeyboardId.MODE_DATE:
|
||||||
case KeyboardId.MODE_TIME:
|
case KeyboardId.MODE_TIME:
|
||||||
case KeyboardId.MODE_DATETIME:
|
case KeyboardId.MODE_DATETIME:
|
||||||
keyboardLayoutSetElementId = KeyboardId.ELEMENT_NUMBER;
|
keyboardLayoutSetElementId = KeyboardId.ELEMENT_NUMBER;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
keyboardLayoutSetElementId = baseKeyboardLayoutSetElementId;
|
keyboardLayoutSetElementId = baseKeyboardLayoutSetElementId;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ElementParams elementParams = mParams.mKeyboardLayoutSetElementIdToParamsMap.get(
|
ElementParams elementParams = mParams.mKeyboardLayoutSetElementIdToParamsMap.get(
|
||||||
|
@ -197,6 +202,7 @@ public final class KeyboardLayoutSet {
|
||||||
|
|
||||||
mParams.mIsSplitLayoutEnabled = mParams.mIsSplitLayoutEnabledByUser
|
mParams.mIsSplitLayoutEnabled = mParams.mIsSplitLayoutEnabledByUser
|
||||||
&& elementParams.mSupportsSplitLayout;
|
&& elementParams.mSupportsSplitLayout;
|
||||||
|
|
||||||
final KeyboardId id = new KeyboardId(keyboardLayoutSetElementId, mParams);
|
final KeyboardId id = new KeyboardId(keyboardLayoutSetElementId, mParams);
|
||||||
try {
|
try {
|
||||||
return getKeyboard(elementParams, id);
|
return getKeyboard(elementParams, id);
|
||||||
|
@ -279,8 +285,7 @@ public final class KeyboardLayoutSet {
|
||||||
// be locked down.
|
// be locked down.
|
||||||
// TODO: Switch to {@code UserManagerCompat.isUserUnlocked()} in the support-v4 library
|
// TODO: Switch to {@code UserManagerCompat.isUserUnlocked()} in the support-v4 library
|
||||||
// when it becomes publicly available.
|
// when it becomes publicly available.
|
||||||
@UserManagerCompatUtils.LockState
|
@UserManagerCompatUtils.LockState final int lockState = UserManagerCompatUtils.getUserLockState(context);
|
||||||
final int lockState = UserManagerCompatUtils.getUserLockState(context);
|
|
||||||
if (lockState == UserManagerCompatUtils.LOCK_STATE_LOCKED) {
|
if (lockState == UserManagerCompatUtils.LOCK_STATE_LOCKED) {
|
||||||
params.mNoSettingsKey = true;
|
params.mNoSettingsKey = true;
|
||||||
}
|
}
|
||||||
|
@ -295,8 +300,7 @@ public final class KeyboardLayoutSet {
|
||||||
public Builder setSubtype(@Nonnull final RichInputMethodSubtype subtype) {
|
public Builder setSubtype(@Nonnull final RichInputMethodSubtype subtype) {
|
||||||
final boolean asciiCapable = subtype.getmSubtype().isAsciiCapable();
|
final boolean asciiCapable = subtype.getmSubtype().isAsciiCapable();
|
||||||
// TODO: Consolidate with {@link InputAttributes}.
|
// TODO: Consolidate with {@link InputAttributes}.
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation") final boolean deprecatedForceAscii = InputAttributes.inPrivateImeOptions(
|
||||||
final boolean deprecatedForceAscii = InputAttributes.inPrivateImeOptions(
|
|
||||||
mPackageName, FORCE_ASCII, mParams.mEditorInfo);
|
mPackageName, FORCE_ASCII, mParams.mEditorInfo);
|
||||||
final boolean forceAscii = EditorInfoCompatUtils.hasFlagForceAscii(
|
final boolean forceAscii = EditorInfoCompatUtils.hasFlagForceAscii(
|
||||||
mParams.mEditorInfo.imeOptions)
|
mParams.mEditorInfo.imeOptions)
|
||||||
|
@ -361,7 +365,7 @@ public final class KeyboardLayoutSet {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int readScriptIdFromTagFeature(final Resources resources,
|
private static int readScriptIdFromTagFeature(final Resources resources,
|
||||||
final XmlPullParser parser) throws IOException, XmlPullParserException {
|
final XmlPullParser parser) throws IOException, XmlPullParserException {
|
||||||
final TypedArray featureAttr = resources.obtainAttributes(Xml.asAttributeSet(parser),
|
final TypedArray featureAttr = resources.obtainAttributes(Xml.asAttributeSet(parser),
|
||||||
R.styleable.KeyboardLayoutSet_Feature);
|
R.styleable.KeyboardLayoutSet_Feature);
|
||||||
try {
|
try {
|
||||||
|
@ -473,33 +477,33 @@ public final class KeyboardLayoutSet {
|
||||||
final int variation = inputType & InputType.TYPE_MASK_VARIATION;
|
final int variation = inputType & InputType.TYPE_MASK_VARIATION;
|
||||||
|
|
||||||
switch (inputType & InputType.TYPE_MASK_CLASS) {
|
switch (inputType & InputType.TYPE_MASK_CLASS) {
|
||||||
case InputType.TYPE_CLASS_NUMBER:
|
case InputType.TYPE_CLASS_NUMBER:
|
||||||
return KeyboardId.MODE_NUMBER;
|
return KeyboardId.MODE_NUMBER;
|
||||||
case InputType.TYPE_CLASS_DATETIME:
|
case InputType.TYPE_CLASS_DATETIME:
|
||||||
switch (variation) {
|
switch (variation) {
|
||||||
case InputType.TYPE_DATETIME_VARIATION_DATE:
|
case InputType.TYPE_DATETIME_VARIATION_DATE:
|
||||||
return KeyboardId.MODE_DATE;
|
return KeyboardId.MODE_DATE;
|
||||||
case InputType.TYPE_DATETIME_VARIATION_TIME:
|
case InputType.TYPE_DATETIME_VARIATION_TIME:
|
||||||
return KeyboardId.MODE_TIME;
|
return KeyboardId.MODE_TIME;
|
||||||
default: // InputType.TYPE_DATETIME_VARIATION_NORMAL
|
default: // InputType.TYPE_DATETIME_VARIATION_NORMAL
|
||||||
return KeyboardId.MODE_DATETIME;
|
return KeyboardId.MODE_DATETIME;
|
||||||
}
|
}
|
||||||
case InputType.TYPE_CLASS_PHONE:
|
case InputType.TYPE_CLASS_PHONE:
|
||||||
return KeyboardId.MODE_PHONE;
|
return KeyboardId.MODE_PHONE;
|
||||||
case InputType.TYPE_CLASS_TEXT:
|
case InputType.TYPE_CLASS_TEXT:
|
||||||
if (InputTypeUtils.isEmailVariation(variation)) {
|
if (InputTypeUtils.isEmailVariation(variation)) {
|
||||||
return KeyboardId.MODE_EMAIL;
|
return KeyboardId.MODE_EMAIL;
|
||||||
} else if (variation == InputType.TYPE_TEXT_VARIATION_URI) {
|
} else if (variation == InputType.TYPE_TEXT_VARIATION_URI) {
|
||||||
return KeyboardId.MODE_URL;
|
return KeyboardId.MODE_URL;
|
||||||
} else if (variation == InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE) {
|
} else if (variation == InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE) {
|
||||||
return KeyboardId.MODE_IM;
|
return KeyboardId.MODE_IM;
|
||||||
} else if (variation == InputType.TYPE_TEXT_VARIATION_FILTER) {
|
} else if (variation == InputType.TYPE_TEXT_VARIATION_FILTER) {
|
||||||
|
return KeyboardId.MODE_TEXT;
|
||||||
|
} else {
|
||||||
|
return KeyboardId.MODE_TEXT;
|
||||||
|
}
|
||||||
|
default:
|
||||||
return KeyboardId.MODE_TEXT;
|
return KeyboardId.MODE_TEXT;
|
||||||
} else {
|
|
||||||
return KeyboardId.MODE_TEXT;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return KeyboardId.MODE_TEXT;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,10 @@
|
||||||
|
|
||||||
package org.dslul.openboard.inputmethod.latin.common;
|
package org.dslul.openboard.inputmethod.latin.common;
|
||||||
|
|
||||||
|
import android.renderscript.Script;
|
||||||
|
|
||||||
import org.dslul.openboard.inputmethod.annotations.UsedForTesting;
|
import org.dslul.openboard.inputmethod.annotations.UsedForTesting;
|
||||||
|
import org.dslul.openboard.inputmethod.latin.utils.ScriptUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -26,6 +29,7 @@ import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public final class StringUtils {
|
public final class StringUtils {
|
||||||
|
|
||||||
public static final int CAPITALIZE_NONE = 0; // No caps, or mixed case
|
public static final int CAPITALIZE_NONE = 0; // No caps, or mixed case
|
||||||
public static final int CAPITALIZE_FIRST = 1; // First only
|
public static final int CAPITALIZE_FIRST = 1; // First only
|
||||||
public static final int CAPITALIZE_ALL = 2; // All caps
|
public static final int CAPITALIZE_ALL = 2; // All caps
|
||||||
|
@ -47,8 +51,10 @@ public final class StringUtils {
|
||||||
|
|
||||||
// Taken from android.text.TextUtils. We are extensively using this method in many places,
|
// Taken from android.text.TextUtils. We are extensively using this method in many places,
|
||||||
// some of which don't have the android libraries available.
|
// some of which don't have the android libraries available.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the string is null or 0-length.
|
* Returns true if the string is null or 0-length.
|
||||||
|
*
|
||||||
* @param str the string to be examined
|
* @param str the string to be examined
|
||||||
* @return true if str is null or zero length
|
* @return true if str is null or zero length
|
||||||
*/
|
*/
|
||||||
|
@ -57,18 +63,20 @@ public final class StringUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Taken from android.text.TextUtils to cut the dependency to the Android framework.
|
// Taken from android.text.TextUtils to cut the dependency to the Android framework.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a string containing the tokens joined by delimiters.
|
* Returns a string containing the tokens joined by delimiters.
|
||||||
|
*
|
||||||
* @param delimiter the delimiter
|
* @param delimiter the delimiter
|
||||||
* @param tokens an array objects to be joined. Strings will be formed from
|
* @param tokens an array objects to be joined. Strings will be formed from
|
||||||
* the objects by calling object.toString().
|
* the objects by calling object.toString().
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public static String join(@Nonnull final CharSequence delimiter,
|
public static String join(@Nonnull final CharSequence delimiter,
|
||||||
@Nonnull final Iterable<?> tokens) {
|
@Nonnull final Iterable<?> tokens) {
|
||||||
final StringBuilder sb = new StringBuilder();
|
final StringBuilder sb = new StringBuilder();
|
||||||
boolean firstTime = true;
|
boolean firstTime = true;
|
||||||
for (final Object token: tokens) {
|
for (final Object token : tokens) {
|
||||||
if (firstTime) {
|
if (firstTime) {
|
||||||
firstTime = false;
|
firstTime = false;
|
||||||
} else {
|
} else {
|
||||||
|
@ -80,10 +88,12 @@ public final class StringUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Taken from android.text.TextUtils to cut the dependency to the Android framework.
|
// Taken from android.text.TextUtils to cut the dependency to the Android framework.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if a and b are equal, including if they are both null.
|
* Returns true if a and b are equal, including if they are both null.
|
||||||
* <p><i>Note: In platform versions 1.1 and earlier, this method only worked well if
|
* <p><i>Note: In platform versions 1.1 and earlier, this method only worked well if
|
||||||
* both the arguments were instances of String.</i></p>
|
* both the arguments were instances of String.</i></p>
|
||||||
|
*
|
||||||
* @param a first CharSequence to check
|
* @param a first CharSequence to check
|
||||||
* @param b second CharSequence to check
|
* @param b second CharSequence to check
|
||||||
* @return true if a and b are equal
|
* @return true if a and b are equal
|
||||||
|
@ -126,7 +136,7 @@ public final class StringUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean containsInArray(@Nonnull final String text,
|
public static boolean containsInArray(@Nonnull final String text,
|
||||||
@Nonnull final String[] array) {
|
@Nonnull final String[] array) {
|
||||||
for (final String element : array) {
|
for (final String element : array) {
|
||||||
if (text.equals(element)) {
|
if (text.equals(element)) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -144,7 +154,7 @@ public final class StringUtils {
|
||||||
private static final String SEPARATOR_FOR_COMMA_SPLITTABLE_TEXT = ",";
|
private static final String SEPARATOR_FOR_COMMA_SPLITTABLE_TEXT = ",";
|
||||||
|
|
||||||
public static boolean containsInCommaSplittableText(@Nonnull final String text,
|
public static boolean containsInCommaSplittableText(@Nonnull final String text,
|
||||||
@Nullable final String extraValues) {
|
@Nullable final String extraValues) {
|
||||||
if (isEmpty(extraValues)) {
|
if (isEmpty(extraValues)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -153,7 +163,7 @@ public final class StringUtils {
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public static String removeFromCommaSplittableTextIfExists(@Nonnull final String text,
|
public static String removeFromCommaSplittableTextIfExists(@Nonnull final String text,
|
||||||
@Nullable final String extraValues) {
|
@Nullable final String extraValues) {
|
||||||
if (isEmpty(extraValues)) {
|
if (isEmpty(extraValues)) {
|
||||||
return EMPTY_STRING;
|
return EMPTY_STRING;
|
||||||
}
|
}
|
||||||
|
@ -172,7 +182,7 @@ public final class StringUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove duplicates from an array of strings.
|
* Remove duplicates from an array of strings.
|
||||||
*
|
* <p>
|
||||||
* This method will always keep the first occurrence of all strings at their position
|
* This method will always keep the first occurrence of all strings at their position
|
||||||
* in the array, removing the subsequent ones.
|
* in the array, removing the subsequent ones.
|
||||||
*/
|
*/
|
||||||
|
@ -199,7 +209,7 @@ public final class StringUtils {
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public static String capitalizeFirstCodePoint(@Nonnull final String s,
|
public static String capitalizeFirstCodePoint(@Nonnull final String s,
|
||||||
@Nonnull final Locale locale) {
|
@Nonnull final Locale locale) {
|
||||||
if (s.length() <= 1) {
|
if (s.length() <= 1) {
|
||||||
return s.toUpperCase(getLocaleUsedForToTitleCase(locale));
|
return s.toUpperCase(getLocaleUsedForToTitleCase(locale));
|
||||||
}
|
}
|
||||||
|
@ -212,7 +222,7 @@ public final class StringUtils {
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public static String capitalizeFirstAndDowncaseRest(@Nonnull final String s,
|
public static String capitalizeFirstAndDowncaseRest(@Nonnull final String s,
|
||||||
@Nonnull final Locale locale) {
|
@Nonnull final Locale locale) {
|
||||||
if (s.length() <= 1) {
|
if (s.length() <= 1) {
|
||||||
return s.toUpperCase(getLocaleUsedForToTitleCase(locale));
|
return s.toUpperCase(getLocaleUsedForToTitleCase(locale));
|
||||||
}
|
}
|
||||||
|
@ -238,14 +248,15 @@ public final class StringUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a range of a string to an array of code points.
|
* Converts a range of a string to an array of code points.
|
||||||
|
*
|
||||||
* @param charSequence the source string.
|
* @param charSequence the source string.
|
||||||
* @param startIndex the start index inside the string in java chars, inclusive.
|
* @param startIndex the start index inside the string in java chars, inclusive.
|
||||||
* @param endIndex the end index inside the string in java chars, exclusive.
|
* @param endIndex the end index inside the string in java chars, exclusive.
|
||||||
* @return a new array of code points. At most endIndex - startIndex, but possibly less.
|
* @return a new array of code points. At most endIndex - startIndex, but possibly less.
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public static int[] toCodePointArray(@Nonnull final CharSequence charSequence,
|
public static int[] toCodePointArray(@Nonnull final CharSequence charSequence,
|
||||||
final int startIndex, final int endIndex) {
|
final int startIndex, final int endIndex) {
|
||||||
final int length = charSequence.length();
|
final int length = charSequence.length();
|
||||||
if (length <= 0) {
|
if (length <= 0) {
|
||||||
return EMPTY_CODEPOINTS;
|
return EMPTY_CODEPOINTS;
|
||||||
|
@ -259,7 +270,7 @@ public final class StringUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copies the codepoints in a CharSequence to an int array.
|
* Copies the codepoints in a CharSequence to an int array.
|
||||||
*
|
* <p>
|
||||||
* This method assumes there is enough space in the array to store the code points. The size
|
* This method assumes there is enough space in the array to store the code points. The size
|
||||||
* can be measured with Character#codePointCount(CharSequence, int, int) before passing to this
|
* can be measured with Character#codePointCount(CharSequence, int, int) before passing to this
|
||||||
* method. If the int array is too small, an ArrayIndexOutOfBoundsException will be thrown.
|
* method. If the int array is too small, an ArrayIndexOutOfBoundsException will be thrown.
|
||||||
|
@ -268,19 +279,19 @@ public final class StringUtils {
|
||||||
* This method can optionally downcase code points before copying them, but it pays no attention
|
* This method can optionally downcase code points before copying them, but it pays no attention
|
||||||
* to locale while doing so.
|
* to locale while doing so.
|
||||||
*
|
*
|
||||||
* @param destination the int array.
|
* @param destination the int array.
|
||||||
* @param charSequence the CharSequence.
|
* @param charSequence the CharSequence.
|
||||||
* @param startIndex the start index inside the string in java chars, inclusive.
|
* @param startIndex the start index inside the string in java chars, inclusive.
|
||||||
* @param endIndex the end index inside the string in java chars, exclusive.
|
* @param endIndex the end index inside the string in java chars, exclusive.
|
||||||
* @param downCase if this is true, code points will be downcased before being copied.
|
* @param downCase if this is true, code points will be downcased before being copied.
|
||||||
* @return the number of copied code points.
|
* @return the number of copied code points.
|
||||||
*/
|
*/
|
||||||
public static int copyCodePointsAndReturnCodePointCount(@Nonnull final int[] destination,
|
public static int copyCodePointsAndReturnCodePointCount(@Nonnull final int[] destination,
|
||||||
@Nonnull final CharSequence charSequence, final int startIndex, final int endIndex,
|
@Nonnull final CharSequence charSequence, final int startIndex, final int endIndex,
|
||||||
final boolean downCase) {
|
final boolean downCase) {
|
||||||
int destIndex = 0;
|
int destIndex = 0;
|
||||||
for (int index = startIndex; index < endIndex;
|
for (int index = startIndex; index < endIndex;
|
||||||
index = Character.offsetByCodePoints(charSequence, index, 1)) {
|
index = Character.offsetByCodePoints(charSequence, index, 1)) {
|
||||||
final int codePoint = Character.codePointAt(charSequence, index);
|
final int codePoint = Character.codePointAt(charSequence, index);
|
||||||
// TODO: stop using this, as it's not aware of the locale and does not always do
|
// TODO: stop using this, as it's not aware of the locale and does not always do
|
||||||
// the right thing.
|
// the right thing.
|
||||||
|
@ -301,7 +312,7 @@ public final class StringUtils {
|
||||||
* Construct a String from a code point array
|
* Construct a String from a code point array
|
||||||
*
|
*
|
||||||
* @param codePoints a code point array that is null terminated when its logical length is
|
* @param codePoints a code point array that is null terminated when its logical length is
|
||||||
* shorter than the array length.
|
* shorter than the array length.
|
||||||
* @return a string constructed from the code point array.
|
* @return a string constructed from the code point array.
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
|
@ -335,7 +346,7 @@ public final class StringUtils {
|
||||||
int capsCount = 1;
|
int capsCount = 1;
|
||||||
int letterCount = 1;
|
int letterCount = 1;
|
||||||
for (index = text.offsetByCodePoints(index, 1); index < len;
|
for (index = text.offsetByCodePoints(index, 1); index < len;
|
||||||
index = text.offsetByCodePoints(index, 1)) {
|
index = text.offsetByCodePoints(index, 1)) {
|
||||||
if (1 != capsCount && letterCount != capsCount) break;
|
if (1 != capsCount && letterCount != capsCount) break;
|
||||||
final int codePoint = text.codePointAt(index);
|
final int codePoint = text.codePointAt(index);
|
||||||
if (Character.isUpperCase(codePoint)) {
|
if (Character.isUpperCase(codePoint)) {
|
||||||
|
@ -381,7 +392,7 @@ public final class StringUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isIdenticalAfterCapitalizeEachWord(@Nonnull final String text,
|
public static boolean isIdenticalAfterCapitalizeEachWord(@Nonnull final String text,
|
||||||
@Nonnull final int[] sortedSeparators) {
|
@Nonnull final int[] sortedSeparators) {
|
||||||
boolean needsCapsNext = true;
|
boolean needsCapsNext = true;
|
||||||
final int len = text.length();
|
final int len = text.length();
|
||||||
for (int i = 0; i < len; i = text.offsetByCodePoints(i, 1)) {
|
for (int i = 0; i < len; i = text.offsetByCodePoints(i, 1)) {
|
||||||
|
@ -402,7 +413,7 @@ public final class StringUtils {
|
||||||
// which should be capitalized together in *some* cases.
|
// which should be capitalized together in *some* cases.
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public static String capitalizeEachWord(@Nonnull final String text,
|
public static String capitalizeEachWord(@Nonnull final String text,
|
||||||
@Nonnull final int[] sortedSeparators, @Nonnull final Locale locale) {
|
@Nonnull final int[] sortedSeparators, @Nonnull final Locale locale) {
|
||||||
final StringBuilder builder = new StringBuilder();
|
final StringBuilder builder = new StringBuilder();
|
||||||
boolean needsCapsNext = true;
|
boolean needsCapsNext = true;
|
||||||
final int len = text.length();
|
final int len = text.length();
|
||||||
|
@ -421,7 +432,7 @@ public final class StringUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Approximates whether the text before the cursor looks like a URL.
|
* Approximates whether the text before the cursor looks like a URL.
|
||||||
*
|
* <p>
|
||||||
* This is not foolproof, but it should work well in the practice.
|
* This is not foolproof, but it should work well in the practice.
|
||||||
* Essentially it walks backward from the cursor until it finds something that's not a letter,
|
* Essentially it walks backward from the cursor until it finds something that's not a letter,
|
||||||
* digit, or common URL symbol like underscore. If it hasn't found a period yet, then it
|
* digit, or common URL symbol like underscore. If it hasn't found a period yet, then it
|
||||||
|
@ -430,9 +441,9 @@ public final class StringUtils {
|
||||||
* - starts with www and contains a period
|
* - starts with www and contains a period
|
||||||
* - starts with a slash preceded by either a slash, whitespace, or start-of-string
|
* - starts with a slash preceded by either a slash, whitespace, or start-of-string
|
||||||
* Then it looks like a URL and we return true. Otherwise, we return false.
|
* Then it looks like a URL and we return true. Otherwise, we return false.
|
||||||
*
|
* <p>
|
||||||
* Note: this method is called quite often, and should be fast.
|
* Note: this method is called quite often, and should be fast.
|
||||||
*
|
* <p>
|
||||||
* TODO: This will return that "abc./def" and ".abc/def" look like URLs to keep down the
|
* TODO: This will return that "abc./def" and ".abc/def" look like URLs to keep down the
|
||||||
* code complexity, but ideally it should not. It's acceptable for now.
|
* code complexity, but ideally it should not. It's acceptable for now.
|
||||||
*/
|
*/
|
||||||
|
@ -491,7 +502,7 @@ public final class StringUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Examines the string and returns whether we're inside a double quote.
|
* Examines the string and returns whether we're inside a double quote.
|
||||||
*
|
* <p>
|
||||||
* This is used to decide whether we should put an automatic space before or after a double
|
* This is used to decide whether we should put an automatic space before or after a double
|
||||||
* quote character. If we're inside a quotation, then we want to close it, so we want a space
|
* quote character. If we're inside a quotation, then we want to close it, so we want a space
|
||||||
* after and not before. Otherwise, we want to open the quotation, so we want a space before
|
* after and not before. Otherwise, we want to open the quotation, so we want a space before
|
||||||
|
@ -596,10 +607,11 @@ public final class StringUtils {
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static String toTitleCaseOfKeyLabel(@Nullable final String label,
|
public static String toTitleCaseOfKeyLabel(@Nullable final String label,
|
||||||
@Nonnull final Locale locale) {
|
@Nonnull final Locale locale) {
|
||||||
if (label == null) {
|
if (label == null || !ScriptUtils.scriptSupportsUppercase(locale.getLanguage())) {
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
return label.toUpperCase(getLocaleUsedForToTitleCase(locale));
|
return label.toUpperCase(getLocaleUsedForToTitleCase(locale));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -661,7 +673,7 @@ public final class StringUtils {
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
protected String joinStringArray(@Nonnull final String[] stringArray,
|
protected String joinStringArray(@Nonnull final String[] stringArray,
|
||||||
@Nullable final String delimiter) {
|
@Nullable final String delimiter) {
|
||||||
if (delimiter == null) {
|
if (delimiter == null) {
|
||||||
return Arrays.toString(stringArray);
|
return Arrays.toString(stringArray);
|
||||||
}
|
}
|
||||||
|
@ -676,6 +688,7 @@ public final class StringUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the last composed word contains line-breaking character (e.g. CR or LF).
|
* Returns whether the last composed word contains line-breaking character (e.g. CR or LF).
|
||||||
|
*
|
||||||
* @param text the text to be examined.
|
* @param text the text to be examined.
|
||||||
* @return {@code true} if the last composed word contains line-breaking separator.
|
* @return {@code true} if the last composed word contains line-breaking separator.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -172,7 +172,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadSettings(final Context context, final Locale locale,
|
public void loadSettings(final Context context, final Locale locale,
|
||||||
@Nonnull final InputAttributes inputAttributes) {
|
@Nonnull final InputAttributes inputAttributes) {
|
||||||
mSettingsValuesLock.lock();
|
mSettingsValuesLock.lock();
|
||||||
mContext = context;
|
mContext = context;
|
||||||
try {
|
try {
|
||||||
|
@ -204,20 +204,20 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
|
||||||
|
|
||||||
// Accessed from the settings interface, hence public
|
// Accessed from the settings interface, hence public
|
||||||
public static boolean readKeypressSoundEnabled(final SharedPreferences prefs,
|
public static boolean readKeypressSoundEnabled(final SharedPreferences prefs,
|
||||||
final Resources res) {
|
final Resources res) {
|
||||||
return prefs.getBoolean(PREF_SOUND_ON,
|
return prefs.getBoolean(PREF_SOUND_ON,
|
||||||
res.getBoolean(R.bool.config_default_sound_enabled));
|
res.getBoolean(R.bool.config_default_sound_enabled));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean readVibrationEnabled(final SharedPreferences prefs,
|
public static boolean readVibrationEnabled(final SharedPreferences prefs,
|
||||||
final Resources res) {
|
final Resources res) {
|
||||||
final boolean hasVibrator = AudioAndHapticFeedbackManager.getInstance().hasVibrator();
|
final boolean hasVibrator = AudioAndHapticFeedbackManager.getInstance().hasVibrator();
|
||||||
return hasVibrator && prefs.getBoolean(PREF_VIBRATE_ON,
|
return hasVibrator && prefs.getBoolean(PREF_VIBRATE_ON,
|
||||||
res.getBoolean(R.bool.config_default_vibration_enabled));
|
res.getBoolean(R.bool.config_default_vibration_enabled));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean readAutoCorrectEnabled(final SharedPreferences prefs,
|
public static boolean readAutoCorrectEnabled(final SharedPreferences prefs,
|
||||||
final Resources res) {
|
final Resources res) {
|
||||||
return prefs.getBoolean(PREF_AUTO_CORRECTION, true);
|
return prefs.getBoolean(PREF_AUTO_CORRECTION, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,7 +226,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean readBlockPotentiallyOffensive(final SharedPreferences prefs,
|
public static boolean readBlockPotentiallyOffensive(final SharedPreferences prefs,
|
||||||
final Resources res) {
|
final Resources res) {
|
||||||
return prefs.getBoolean(PREF_BLOCK_POTENTIALLY_OFFENSIVE,
|
return prefs.getBoolean(PREF_BLOCK_POTENTIALLY_OFFENSIVE,
|
||||||
res.getBoolean(R.bool.config_block_potentially_offensive));
|
res.getBoolean(R.bool.config_block_potentially_offensive));
|
||||||
}
|
}
|
||||||
|
@ -239,7 +239,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean readGestureInputEnabled(final SharedPreferences prefs,
|
public static boolean readGestureInputEnabled(final SharedPreferences prefs,
|
||||||
final Resources res) {
|
final Resources res) {
|
||||||
return readFromBuildConfigIfGestureInputEnabled(res)
|
return readFromBuildConfigIfGestureInputEnabled(res)
|
||||||
&& prefs.getBoolean(PREF_GESTURE_INPUT, true);
|
&& prefs.getBoolean(PREF_GESTURE_INPUT, true);
|
||||||
}
|
}
|
||||||
|
@ -249,7 +249,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean readKeyPreviewPopupEnabled(final SharedPreferences prefs,
|
public static boolean readKeyPreviewPopupEnabled(final SharedPreferences prefs,
|
||||||
final Resources res) {
|
final Resources res) {
|
||||||
final boolean defaultKeyPreviewPopup = res.getBoolean(
|
final boolean defaultKeyPreviewPopup = res.getBoolean(
|
||||||
R.bool.config_default_key_preview_popup);
|
R.bool.config_default_key_preview_popup);
|
||||||
if (!readFromBuildConfigIfToShowKeyPreviewPopupOption(res)) {
|
if (!readFromBuildConfigIfToShowKeyPreviewPopupOption(res)) {
|
||||||
|
@ -259,26 +259,26 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int readKeyPreviewPopupDismissDelay(final SharedPreferences prefs,
|
public static int readKeyPreviewPopupDismissDelay(final SharedPreferences prefs,
|
||||||
final Resources res) {
|
final Resources res) {
|
||||||
return Integer.parseInt(prefs.getString(PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY,
|
return Integer.parseInt(prefs.getString(PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY,
|
||||||
Integer.toString(res.getInteger(
|
Integer.toString(res.getInteger(
|
||||||
R.integer.config_key_preview_linger_timeout))));
|
R.integer.config_key_preview_linger_timeout))));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String readPrefAdditionalSubtypes(final SharedPreferences prefs,
|
public static String readPrefAdditionalSubtypes(final SharedPreferences prefs,
|
||||||
final Resources res) {
|
final Resources res) {
|
||||||
final String predefinedPrefSubtypes = AdditionalSubtypeUtils.createPrefSubtypes(
|
final String predefinedPrefSubtypes = AdditionalSubtypeUtils.createPrefSubtypes(
|
||||||
res.getStringArray(R.array.predefined_subtypes));
|
res.getStringArray(R.array.predefined_subtypes));
|
||||||
return prefs.getString(PREF_CUSTOM_INPUT_STYLES, predefinedPrefSubtypes);
|
return prefs.getString(PREF_CUSTOM_INPUT_STYLES, predefinedPrefSubtypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void writePrefAdditionalSubtypes(final SharedPreferences prefs,
|
public static void writePrefAdditionalSubtypes(final SharedPreferences prefs,
|
||||||
final String prefSubtypes) {
|
final String prefSubtypes) {
|
||||||
prefs.edit().putString(PREF_CUSTOM_INPUT_STYLES, prefSubtypes).apply();
|
prefs.edit().putString(PREF_CUSTOM_INPUT_STYLES, prefSubtypes).apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float readKeypressSoundVolume(final SharedPreferences prefs,
|
public static float readKeypressSoundVolume(final SharedPreferences prefs,
|
||||||
final Resources res) {
|
final Resources res) {
|
||||||
final float volume = prefs.getFloat(
|
final float volume = prefs.getFloat(
|
||||||
PREF_KEYPRESS_SOUND_VOLUME, UNDEFINED_PREFERENCE_VALUE_FLOAT);
|
PREF_KEYPRESS_SOUND_VOLUME, UNDEFINED_PREFERENCE_VALUE_FLOAT);
|
||||||
return (volume != UNDEFINED_PREFERENCE_VALUE_FLOAT) ? volume
|
return (volume != UNDEFINED_PREFERENCE_VALUE_FLOAT) ? volume
|
||||||
|
@ -295,7 +295,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int readKeyLongpressTimeout(final SharedPreferences prefs,
|
public static int readKeyLongpressTimeout(final SharedPreferences prefs,
|
||||||
final Resources res) {
|
final Resources res) {
|
||||||
final int milliseconds = prefs.getInt(
|
final int milliseconds = prefs.getInt(
|
||||||
PREF_KEY_LONGPRESS_TIMEOUT, UNDEFINED_PREFERENCE_VALUE_INT);
|
PREF_KEY_LONGPRESS_TIMEOUT, UNDEFINED_PREFERENCE_VALUE_INT);
|
||||||
return (milliseconds != UNDEFINED_PREFERENCE_VALUE_INT) ? milliseconds
|
return (milliseconds != UNDEFINED_PREFERENCE_VALUE_INT) ? milliseconds
|
||||||
|
@ -307,7 +307,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int readKeypressVibrationDuration(final SharedPreferences prefs,
|
public static int readKeypressVibrationDuration(final SharedPreferences prefs,
|
||||||
final Resources res) {
|
final Resources res) {
|
||||||
final int milliseconds = prefs.getInt(
|
final int milliseconds = prefs.getInt(
|
||||||
PREF_VIBRATION_DURATION_SETTINGS, UNDEFINED_PREFERENCE_VALUE_INT);
|
PREF_VIBRATION_DURATION_SETTINGS, UNDEFINED_PREFERENCE_VALUE_INT);
|
||||||
return (milliseconds != UNDEFINED_PREFERENCE_VALUE_INT) ? milliseconds
|
return (milliseconds != UNDEFINED_PREFERENCE_VALUE_INT) ? milliseconds
|
||||||
|
@ -324,19 +324,19 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float readKeyPreviewAnimationScale(final SharedPreferences prefs,
|
public static float readKeyPreviewAnimationScale(final SharedPreferences prefs,
|
||||||
final String prefKey, final float defaultValue) {
|
final String prefKey, final float defaultValue) {
|
||||||
final float fraction = prefs.getFloat(prefKey, UNDEFINED_PREFERENCE_VALUE_FLOAT);
|
final float fraction = prefs.getFloat(prefKey, UNDEFINED_PREFERENCE_VALUE_FLOAT);
|
||||||
return (fraction != UNDEFINED_PREFERENCE_VALUE_FLOAT) ? fraction : defaultValue;
|
return (fraction != UNDEFINED_PREFERENCE_VALUE_FLOAT) ? fraction : defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int readKeyPreviewAnimationDuration(final SharedPreferences prefs,
|
public static int readKeyPreviewAnimationDuration(final SharedPreferences prefs,
|
||||||
final String prefKey, final int defaultValue) {
|
final String prefKey, final int defaultValue) {
|
||||||
final int milliseconds = prefs.getInt(prefKey, UNDEFINED_PREFERENCE_VALUE_INT);
|
final int milliseconds = prefs.getInt(prefKey, UNDEFINED_PREFERENCE_VALUE_INT);
|
||||||
return (milliseconds != UNDEFINED_PREFERENCE_VALUE_INT) ? milliseconds : defaultValue;
|
return (milliseconds != UNDEFINED_PREFERENCE_VALUE_INT) ? milliseconds : defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float readKeyboardHeight(final SharedPreferences prefs,
|
public static float readKeyboardHeight(final SharedPreferences prefs,
|
||||||
final float defaultValue) {
|
final float defaultValue) {
|
||||||
final float percentage = prefs.getFloat(
|
final float percentage = prefs.getFloat(
|
||||||
Settings.PREF_KEYBOARD_HEIGHT_SCALE, UNDEFINED_PREFERENCE_VALUE_FLOAT);
|
Settings.PREF_KEYBOARD_HEIGHT_SCALE, UNDEFINED_PREFERENCE_VALUE_FLOAT);
|
||||||
return (percentage != UNDEFINED_PREFERENCE_VALUE_FLOAT) ? percentage : defaultValue;
|
return (percentage != UNDEFINED_PREFERENCE_VALUE_FLOAT) ? percentage : defaultValue;
|
||||||
|
@ -355,7 +355,7 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean readShowSetupWizardIcon(final SharedPreferences prefs,
|
public static boolean readShowSetupWizardIcon(final SharedPreferences prefs,
|
||||||
final Context context) {
|
final Context context) {
|
||||||
if (!prefs.contains(PREF_SHOW_SETUP_WIZARD_ICON)) {
|
if (!prefs.contains(PREF_SHOW_SETUP_WIZARD_ICON)) {
|
||||||
final ApplicationInfo appInfo = context.getApplicationInfo();
|
final ApplicationInfo appInfo = context.getApplicationInfo();
|
||||||
final boolean isApplicationInSystemImage =
|
final boolean isApplicationInSystemImage =
|
||||||
|
|
|
@ -28,8 +28,10 @@ import org.dslul.openboard.inputmethod.compat.AppWorkaroundsUtils;
|
||||||
import org.dslul.openboard.inputmethod.latin.InputAttributes;
|
import org.dslul.openboard.inputmethod.latin.InputAttributes;
|
||||||
import org.dslul.openboard.inputmethod.latin.R;
|
import org.dslul.openboard.inputmethod.latin.R;
|
||||||
import org.dslul.openboard.inputmethod.latin.RichInputMethodManager;
|
import org.dslul.openboard.inputmethod.latin.RichInputMethodManager;
|
||||||
|
import org.dslul.openboard.inputmethod.latin.common.StringUtils;
|
||||||
import org.dslul.openboard.inputmethod.latin.utils.AsyncResultHolder;
|
import org.dslul.openboard.inputmethod.latin.utils.AsyncResultHolder;
|
||||||
import org.dslul.openboard.inputmethod.latin.utils.ResourceUtils;
|
import org.dslul.openboard.inputmethod.latin.utils.ResourceUtils;
|
||||||
|
import org.dslul.openboard.inputmethod.latin.utils.ScriptUtils;
|
||||||
import org.dslul.openboard.inputmethod.latin.utils.TargetPackageInfoGetterTask;
|
import org.dslul.openboard.inputmethod.latin.utils.TargetPackageInfoGetterTask;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -118,10 +120,11 @@ public class SettingsValues {
|
||||||
public final float mKeyPreviewDismissEndXScale;
|
public final float mKeyPreviewDismissEndXScale;
|
||||||
public final float mKeyPreviewDismissEndYScale;
|
public final float mKeyPreviewDismissEndYScale;
|
||||||
|
|
||||||
@Nullable public final String mAccount;
|
@Nullable
|
||||||
|
public final String mAccount;
|
||||||
|
|
||||||
public SettingsValues(final Context context, final SharedPreferences prefs, final Resources res,
|
public SettingsValues(final Context context, final SharedPreferences prefs, final Resources res,
|
||||||
@Nonnull final InputAttributes inputAttributes) {
|
@Nonnull final InputAttributes inputAttributes) {
|
||||||
mLocale = res.getConfiguration().locale;
|
mLocale = res.getConfiguration().locale;
|
||||||
// Get the resources
|
// Get the resources
|
||||||
mDelayInMillisecondsToUpdateOldSuggestions =
|
mDelayInMillisecondsToUpdateOldSuggestions =
|
||||||
|
@ -132,7 +135,7 @@ public class SettingsValues {
|
||||||
mInputAttributes = inputAttributes;
|
mInputAttributes = inputAttributes;
|
||||||
|
|
||||||
// Get the settings preferences
|
// Get the settings preferences
|
||||||
mAutoCap = prefs.getBoolean(Settings.PREF_AUTO_CAP, true);
|
mAutoCap = prefs.getBoolean(Settings.PREF_AUTO_CAP, true) && ScriptUtils.scriptSupportsUppercase(mLocale.getLanguage());
|
||||||
mVibrateOn = Settings.readVibrationEnabled(prefs, res);
|
mVibrateOn = Settings.readVibrationEnabled(prefs, res);
|
||||||
mSoundOn = Settings.readKeypressSoundEnabled(prefs, res);
|
mSoundOn = Settings.readKeypressSoundEnabled(prefs, res);
|
||||||
mKeyPreviewPopupOn = Settings.readKeyPreviewPopupEnabled(prefs, res);
|
mKeyPreviewPopupOn = Settings.readKeyPreviewPopupEnabled(prefs, res);
|
||||||
|
@ -303,13 +306,13 @@ public class SettingsValues {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean readBigramPredictionEnabled(final SharedPreferences prefs,
|
private static boolean readBigramPredictionEnabled(final SharedPreferences prefs,
|
||||||
final Resources res) {
|
final Resources res) {
|
||||||
return prefs.getBoolean(Settings.PREF_BIGRAM_PREDICTIONS, res.getBoolean(
|
return prefs.getBoolean(Settings.PREF_BIGRAM_PREDICTIONS, res.getBoolean(
|
||||||
R.bool.config_default_next_word_prediction));
|
R.bool.config_default_next_word_prediction));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float readAutoCorrectionThreshold(final Resources res,
|
private static float readAutoCorrectionThreshold(final Resources res,
|
||||||
final String currentAutoCorrectionSetting) {
|
final String currentAutoCorrectionSetting) {
|
||||||
final String[] autoCorrectionThresholdValues = res.getStringArray(
|
final String[] autoCorrectionThresholdValues = res.getStringArray(
|
||||||
R.array.auto_correction_threshold_values);
|
R.array.auto_correction_threshold_values);
|
||||||
// When autoCorrectionThreshold is greater than 1.0, it's like auto correction is off.
|
// When autoCorrectionThreshold is greater than 1.0, it's like auto correction is off.
|
||||||
|
@ -340,7 +343,7 @@ public class SettingsValues {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean needsToShowVoiceInputKey(final SharedPreferences prefs,
|
private static boolean needsToShowVoiceInputKey(final SharedPreferences prefs,
|
||||||
final Resources res) {
|
final Resources res) {
|
||||||
// Migrate preference from {@link Settings#PREF_VOICE_MODE_OBSOLETE} to
|
// Migrate preference from {@link Settings#PREF_VOICE_MODE_OBSOLETE} to
|
||||||
// {@link Settings#PREF_VOICE_INPUT_KEY}.
|
// {@link Settings#PREF_VOICE_INPUT_KEY}.
|
||||||
if (prefs.contains(Settings.PREF_VOICE_MODE_OBSOLETE)) {
|
if (prefs.contains(Settings.PREF_VOICE_MODE_OBSOLETE)) {
|
||||||
|
|
|
@ -16,6 +16,9 @@
|
||||||
|
|
||||||
package org.dslul.openboard.inputmethod.latin.utils;
|
package org.dslul.openboard.inputmethod.latin.utils;
|
||||||
|
|
||||||
|
|
||||||
|
import androidx.collection.ArraySet;
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
@ -47,7 +50,11 @@ public class ScriptUtils {
|
||||||
public static final int SCRIPT_THAI = 17;
|
public static final int SCRIPT_THAI = 17;
|
||||||
public static final int SCRIPT_BULGARIAN = 18;
|
public static final int SCRIPT_BULGARIAN = 18;
|
||||||
|
|
||||||
|
public static final String LANGUAGE_GEORGIAN = "ka";
|
||||||
|
|
||||||
private static final TreeMap<String, Integer> mLanguageCodeToScriptCode;
|
private static final TreeMap<String, Integer> mLanguageCodeToScriptCode;
|
||||||
|
private final static ArraySet<String> NON_UPPERCASE_SCRIPTS = new ArraySet<>();
|
||||||
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
mLanguageCodeToScriptCode = new TreeMap<>();
|
mLanguageCodeToScriptCode = new TreeMap<>();
|
||||||
|
@ -70,6 +77,13 @@ public class ScriptUtils {
|
||||||
mLanguageCodeToScriptCode.put("te", SCRIPT_TELUGU);
|
mLanguageCodeToScriptCode.put("te", SCRIPT_TELUGU);
|
||||||
mLanguageCodeToScriptCode.put("th", SCRIPT_THAI);
|
mLanguageCodeToScriptCode.put("th", SCRIPT_THAI);
|
||||||
mLanguageCodeToScriptCode.put("uk", SCRIPT_CYRILLIC);
|
mLanguageCodeToScriptCode.put("uk", SCRIPT_CYRILLIC);
|
||||||
|
|
||||||
|
NON_UPPERCASE_SCRIPTS.add(LANGUAGE_GEORGIAN);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean scriptSupportsUppercase(String language) {
|
||||||
|
return !NON_UPPERCASE_SCRIPTS.contains(language);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -82,102 +96,102 @@ public class ScriptUtils {
|
||||||
*/
|
*/
|
||||||
public static boolean isLetterPartOfScript(final int codePoint, final int scriptId) {
|
public static boolean isLetterPartOfScript(final int codePoint, final int scriptId) {
|
||||||
switch (scriptId) {
|
switch (scriptId) {
|
||||||
case SCRIPT_ARABIC:
|
case SCRIPT_ARABIC:
|
||||||
// Arabic letters can be in any of the following blocks:
|
// Arabic letters can be in any of the following blocks:
|
||||||
// Arabic U+0600..U+06FF
|
// Arabic U+0600..U+06FF
|
||||||
// Arabic Supplement, Thaana U+0750..U+077F, U+0780..U+07BF
|
// Arabic Supplement, Thaana U+0750..U+077F, U+0780..U+07BF
|
||||||
// Arabic Extended-A U+08A0..U+08FF
|
// Arabic Extended-A U+08A0..U+08FF
|
||||||
// Arabic Presentation Forms-A U+FB50..U+FDFF
|
// Arabic Presentation Forms-A U+FB50..U+FDFF
|
||||||
// Arabic Presentation Forms-B U+FE70..U+FEFF
|
// Arabic Presentation Forms-B U+FE70..U+FEFF
|
||||||
return (codePoint >= 0x600 && codePoint <= 0x6FF)
|
return (codePoint >= 0x600 && codePoint <= 0x6FF)
|
||||||
|| (codePoint >= 0x750 && codePoint <= 0x7BF)
|
|| (codePoint >= 0x750 && codePoint <= 0x7BF)
|
||||||
|| (codePoint >= 0x8A0 && codePoint <= 0x8FF)
|
|| (codePoint >= 0x8A0 && codePoint <= 0x8FF)
|
||||||
|| (codePoint >= 0xFB50 && codePoint <= 0xFDFF)
|
|| (codePoint >= 0xFB50 && codePoint <= 0xFDFF)
|
||||||
|| (codePoint >= 0xFE70 && codePoint <= 0xFEFF);
|
|| (codePoint >= 0xFE70 && codePoint <= 0xFEFF);
|
||||||
case SCRIPT_ARMENIAN:
|
case SCRIPT_ARMENIAN:
|
||||||
// Armenian letters are in the Armenian unicode block, U+0530..U+058F and
|
// Armenian letters are in the Armenian unicode block, U+0530..U+058F and
|
||||||
// Alphabetic Presentation Forms block, U+FB00..U+FB4F, but only in the Armenian part
|
// Alphabetic Presentation Forms block, U+FB00..U+FB4F, but only in the Armenian part
|
||||||
// of that block, which is U+FB13..U+FB17.
|
// of that block, which is U+FB13..U+FB17.
|
||||||
return (codePoint >= 0x530 && codePoint <= 0x58F
|
return (codePoint >= 0x530 && codePoint <= 0x58F
|
||||||
|| codePoint >= 0xFB13 && codePoint <= 0xFB17);
|
|| codePoint >= 0xFB13 && codePoint <= 0xFB17);
|
||||||
case SCRIPT_BENGALI:
|
case SCRIPT_BENGALI:
|
||||||
// Bengali unicode block is U+0980..U+09FF
|
// Bengali unicode block is U+0980..U+09FF
|
||||||
return (codePoint >= 0x980 && codePoint <= 0x9FF);
|
return (codePoint >= 0x980 && codePoint <= 0x9FF);
|
||||||
case SCRIPT_BULGARIAN:
|
case SCRIPT_BULGARIAN:
|
||||||
case SCRIPT_CYRILLIC:
|
case SCRIPT_CYRILLIC:
|
||||||
// All Cyrillic characters are in the 400~52F block. There are some in the upper
|
// All Cyrillic characters are in the 400~52F block. There are some in the upper
|
||||||
// Unicode range, but they are archaic characters that are not used in modern
|
// Unicode range, but they are archaic characters that are not used in modern
|
||||||
// Russian and are not used by our dictionary.
|
// Russian and are not used by our dictionary.
|
||||||
return codePoint >= 0x400 && codePoint <= 0x52F && Character.isLetter(codePoint);
|
return codePoint >= 0x400 && codePoint <= 0x52F && Character.isLetter(codePoint);
|
||||||
case SCRIPT_DEVANAGARI:
|
case SCRIPT_DEVANAGARI:
|
||||||
// Devanagari unicode block is +0900..U+097F
|
// Devanagari unicode block is +0900..U+097F
|
||||||
return (codePoint >= 0x900 && codePoint <= 0x97F);
|
return (codePoint >= 0x900 && codePoint <= 0x97F);
|
||||||
case SCRIPT_GEORGIAN:
|
case SCRIPT_GEORGIAN:
|
||||||
// Georgian letters are in the Georgian unicode block, U+10A0..U+10FF,
|
// Georgian letters are in the Georgian unicode block, U+10A0..U+10FF,
|
||||||
// or Georgian supplement block, U+2D00..U+2D2F
|
// or Georgian supplement block, U+2D00..U+2D2F
|
||||||
return (codePoint >= 0x10A0 && codePoint <= 0x10FF
|
return (codePoint >= 0x10A0 && codePoint <= 0x10FF
|
||||||
|| codePoint >= 0x2D00 && codePoint <= 0x2D2F);
|
|| codePoint >= 0x2D00 && codePoint <= 0x2D2F);
|
||||||
case SCRIPT_GREEK:
|
case SCRIPT_GREEK:
|
||||||
// Greek letters are either in the 370~3FF range (Greek & Coptic), or in the
|
// Greek letters are either in the 370~3FF range (Greek & Coptic), or in the
|
||||||
// 1F00~1FFF range (Greek extended). Our dictionary contains both sort of characters.
|
// 1F00~1FFF range (Greek extended). Our dictionary contains both sort of characters.
|
||||||
// Our dictionary also contains a few words with 0xF2; it would be best to check
|
// Our dictionary also contains a few words with 0xF2; it would be best to check
|
||||||
// if that's correct, but a web search does return results for these words so
|
// if that's correct, but a web search does return results for these words so
|
||||||
// they are probably okay.
|
// they are probably okay.
|
||||||
return (codePoint >= 0x370 && codePoint <= 0x3FF)
|
return (codePoint >= 0x370 && codePoint <= 0x3FF)
|
||||||
|| (codePoint >= 0x1F00 && codePoint <= 0x1FFF)
|
|| (codePoint >= 0x1F00 && codePoint <= 0x1FFF)
|
||||||
|| codePoint == 0xF2;
|
|| codePoint == 0xF2;
|
||||||
case SCRIPT_HEBREW:
|
case SCRIPT_HEBREW:
|
||||||
// Hebrew letters are in the Hebrew unicode block, which spans from U+0590 to U+05FF,
|
// Hebrew letters are in the Hebrew unicode block, which spans from U+0590 to U+05FF,
|
||||||
// or in the Alphabetic Presentation Forms block, U+FB00..U+FB4F, but only in the
|
// or in the Alphabetic Presentation Forms block, U+FB00..U+FB4F, but only in the
|
||||||
// Hebrew part of that block, which is U+FB1D..U+FB4F.
|
// Hebrew part of that block, which is U+FB1D..U+FB4F.
|
||||||
return (codePoint >= 0x590 && codePoint <= 0x5FF
|
return (codePoint >= 0x590 && codePoint <= 0x5FF
|
||||||
|| codePoint >= 0xFB1D && codePoint <= 0xFB4F);
|
|| codePoint >= 0xFB1D && codePoint <= 0xFB4F);
|
||||||
case SCRIPT_KANNADA:
|
case SCRIPT_KANNADA:
|
||||||
// Kannada unicode block is U+0C80..U+0CFF
|
// Kannada unicode block is U+0C80..U+0CFF
|
||||||
return (codePoint >= 0xC80 && codePoint <= 0xCFF);
|
return (codePoint >= 0xC80 && codePoint <= 0xCFF);
|
||||||
case SCRIPT_KHMER:
|
case SCRIPT_KHMER:
|
||||||
// Khmer letters are in unicode block U+1780..U+17FF, and the Khmer symbols block
|
// Khmer letters are in unicode block U+1780..U+17FF, and the Khmer symbols block
|
||||||
// is U+19E0..U+19FF
|
// is U+19E0..U+19FF
|
||||||
return (codePoint >= 0x1780 && codePoint <= 0x17FF
|
return (codePoint >= 0x1780 && codePoint <= 0x17FF
|
||||||
|| codePoint >= 0x19E0 && codePoint <= 0x19FF);
|
|| codePoint >= 0x19E0 && codePoint <= 0x19FF);
|
||||||
case SCRIPT_LAO:
|
case SCRIPT_LAO:
|
||||||
// The Lao block is U+0E80..U+0EFF
|
// The Lao block is U+0E80..U+0EFF
|
||||||
return (codePoint >= 0xE80 && codePoint <= 0xEFF);
|
return (codePoint >= 0xE80 && codePoint <= 0xEFF);
|
||||||
case SCRIPT_LATIN:
|
case SCRIPT_LATIN:
|
||||||
// Our supported latin script dictionaries (EFIGS) at the moment only include
|
// Our supported latin script dictionaries (EFIGS) at the moment only include
|
||||||
// characters in the C0, C1, Latin Extended A and B, IPA extensions unicode
|
// characters in the C0, C1, Latin Extended A and B, IPA extensions unicode
|
||||||
// blocks. As it happens, those are back-to-back in the code range 0x40 to 0x2AF,
|
// blocks. As it happens, those are back-to-back in the code range 0x40 to 0x2AF,
|
||||||
// so the below is a very efficient way to test for it. As for the 0-0x3F, it's
|
// so the below is a very efficient way to test for it. As for the 0-0x3F, it's
|
||||||
// excluded from isLetter anyway.
|
// excluded from isLetter anyway.
|
||||||
return codePoint <= 0x2AF && Character.isLetter(codePoint);
|
return codePoint <= 0x2AF && Character.isLetter(codePoint);
|
||||||
case SCRIPT_MALAYALAM:
|
case SCRIPT_MALAYALAM:
|
||||||
// Malayalam unicode block is U+0D00..U+0D7F
|
// Malayalam unicode block is U+0D00..U+0D7F
|
||||||
return (codePoint >= 0xD00 && codePoint <= 0xD7F);
|
return (codePoint >= 0xD00 && codePoint <= 0xD7F);
|
||||||
case SCRIPT_MYANMAR:
|
case SCRIPT_MYANMAR:
|
||||||
// Myanmar has three unicode blocks :
|
// Myanmar has three unicode blocks :
|
||||||
// Myanmar U+1000..U+109F
|
// Myanmar U+1000..U+109F
|
||||||
// Myanmar extended-A U+AA60..U+AA7F
|
// Myanmar extended-A U+AA60..U+AA7F
|
||||||
// Myanmar extended-B U+A9E0..U+A9FF
|
// Myanmar extended-B U+A9E0..U+A9FF
|
||||||
return (codePoint >= 0x1000 && codePoint <= 0x109F
|
return (codePoint >= 0x1000 && codePoint <= 0x109F
|
||||||
|| codePoint >= 0xAA60 && codePoint <= 0xAA7F
|
|| codePoint >= 0xAA60 && codePoint <= 0xAA7F
|
||||||
|| codePoint >= 0xA9E0 && codePoint <= 0xA9FF);
|
|| codePoint >= 0xA9E0 && codePoint <= 0xA9FF);
|
||||||
case SCRIPT_SINHALA:
|
case SCRIPT_SINHALA:
|
||||||
// Sinhala unicode block is U+0D80..U+0DFF
|
// Sinhala unicode block is U+0D80..U+0DFF
|
||||||
return (codePoint >= 0xD80 && codePoint <= 0xDFF);
|
return (codePoint >= 0xD80 && codePoint <= 0xDFF);
|
||||||
case SCRIPT_TAMIL:
|
case SCRIPT_TAMIL:
|
||||||
// Tamil unicode block is U+0B80..U+0BFF
|
// Tamil unicode block is U+0B80..U+0BFF
|
||||||
return (codePoint >= 0xB80 && codePoint <= 0xBFF);
|
return (codePoint >= 0xB80 && codePoint <= 0xBFF);
|
||||||
case SCRIPT_TELUGU:
|
case SCRIPT_TELUGU:
|
||||||
// Telugu unicode block is U+0C00..U+0C7F
|
// Telugu unicode block is U+0C00..U+0C7F
|
||||||
return (codePoint >= 0xC00 && codePoint <= 0xC7F);
|
return (codePoint >= 0xC00 && codePoint <= 0xC7F);
|
||||||
case SCRIPT_THAI:
|
case SCRIPT_THAI:
|
||||||
// Thai unicode block is U+0E00..U+0E7F
|
// Thai unicode block is U+0E00..U+0E7F
|
||||||
return (codePoint >= 0xE00 && codePoint <= 0xE7F);
|
return (codePoint >= 0xE00 && codePoint <= 0xE7F);
|
||||||
case SCRIPT_UNKNOWN:
|
case SCRIPT_UNKNOWN:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
// Should never come here
|
// Should never come here
|
||||||
throw new RuntimeException("Impossible value of script: " + scriptId);
|
throw new RuntimeException("Impossible value of script: " + scriptId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue