Merge "Remove "dimension|fraction" format from Key and Keyboard attributes"
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
index f28bc94..fd9edec 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardLayoutSet.java
@@ -32,7 +32,6 @@
import android.util.Log;
import android.util.SparseArray;
import android.util.Xml;
-import android.view.ViewDebug.HierarchyTraceType;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodSubtype;
diff --git a/java/src/com/android/inputmethod/latin/AssetFileAddress.java b/java/src/com/android/inputmethod/latin/AssetFileAddress.java
index 16296f0..47c750f 100644
--- a/java/src/com/android/inputmethod/latin/AssetFileAddress.java
+++ b/java/src/com/android/inputmethod/latin/AssetFileAddress.java
@@ -35,11 +35,14 @@
mLength = length;
}
+ public static AssetFileAddress makeFromFile(final File file) {
+ if (!file.isFile()) return null;
+ return new AssetFileAddress(file.getAbsolutePath(), 0L, file.length());
+ }
+
public static AssetFileAddress makeFromFileName(final String filename) {
if (null == filename) return null;
- final File f = new File(filename);
- if (!f.isFile()) return null;
- return new AssetFileAddress(filename, 0l, f.length());
+ return makeFromFile(new File(filename));
}
public static AssetFileAddress makeFromFileNameAndOffset(final String filename,
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
index d0bd01f..443ffa2 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryFileDumper.java
@@ -149,7 +149,7 @@
final int MODE_MAX = NONE;
final Uri.Builder wordListUriBuilder = getProviderUriBuilder(id);
- final String finalFileName = BinaryDictionaryGetter.getCacheFileName(id, locale, context);
+ final String finalFileName = DictionaryInfoUtils.getCacheFileName(id, locale, context);
String tempFileName;
try {
tempFileName = BinaryDictionaryGetter.getTempFileName(id, context);
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
index 22b5cd5..5da0f1b 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
@@ -66,109 +66,11 @@
private BinaryDictionaryGetter() {}
/**
- * Returns whether we may want to use this character as part of a file name.
- *
- * This basically only accepts ascii letters and numbers, and rejects everything else.
- */
- private static boolean isFileNameCharacter(int codePoint) {
- if (codePoint >= 0x30 && codePoint <= 0x39) return true; // Digit
- if (codePoint >= 0x41 && codePoint <= 0x5A) return true; // Uppercase
- if (codePoint >= 0x61 && codePoint <= 0x7A) return true; // Lowercase
- return codePoint == '_'; // Underscore
- }
-
- /**
- * Escapes a string for any characters that may be suspicious for a file or directory name.
- *
- * Concretely this does a sort of URL-encoding except it will encode everything that's not
- * alphanumeric or underscore. (true URL-encoding leaves alone characters like '*', which
- * we cannot allow here)
- */
- // TODO: create a unit test for this method
- private static String replaceFileNameDangerousCharacters(final String name) {
- // This assumes '%' is fully available as a non-separator, normal
- // character in a file name. This is probably true for all file systems.
- final StringBuilder sb = new StringBuilder();
- final int nameLength = name.length();
- for (int i = 0; i < nameLength; i = name.offsetByCodePoints(i, 1)) {
- final int codePoint = name.codePointAt(i);
- if (isFileNameCharacter(codePoint)) {
- sb.appendCodePoint(codePoint);
- } else {
- // 6 digits - unicode is limited to 21 bits
- sb.append(String.format((Locale)null, "%%%1$06x", codePoint));
- }
- }
- return sb.toString();
- }
-
- /**
- * Reverse escaping done by replaceFileNameDangerousCharacters.
- */
- private static String getWordListIdFromFileName(final String fname) {
- final StringBuilder sb = new StringBuilder();
- final int fnameLength = fname.length();
- for (int i = 0; i < fnameLength; i = fname.offsetByCodePoints(i, 1)) {
- final int codePoint = fname.codePointAt(i);
- if ('%' != codePoint) {
- sb.appendCodePoint(codePoint);
- } else {
- final int encodedCodePoint = Integer.parseInt(fname.substring(i + 1, i + 7), 16);
- i += 6;
- sb.appendCodePoint(encodedCodePoint);
- }
- }
- return sb.toString();
- }
-
- /**
- * Helper method to get the top level cache directory.
- */
- private static String getWordListCacheDirectory(final Context context) {
- return context.getFilesDir() + File.separator + "dicts";
- }
-
- /**
- * Find out the cache directory associated with a specific locale.
- */
- private static String getCacheDirectoryForLocale(final String locale, final Context context) {
- final String relativeDirectoryName = replaceFileNameDangerousCharacters(locale);
- final String absoluteDirectoryName = getWordListCacheDirectory(context) + File.separator
- + relativeDirectoryName;
- final File directory = new File(absoluteDirectoryName);
- if (!directory.exists()) {
- if (!directory.mkdirs()) {
- Log.e(TAG, "Could not create the directory for locale" + locale);
- }
- }
- return absoluteDirectoryName;
- }
-
- /**
- * Generates a file name for the id and locale passed as an argument.
- *
- * In the current implementation the file name returned will always be unique for
- * any id/locale pair, but please do not expect that the id can be the same for
- * different dictionaries with different locales. An id should be unique for any
- * dictionary.
- * The file name is pretty much an URL-encoded version of the id inside a directory
- * named like the locale, except it will also escape characters that look dangerous
- * to some file systems.
- * @param id the id of the dictionary for which to get a file name
- * @param locale the locale for which to get the file name as a string
- * @param context the context to use for getting the directory
- * @return the name of the file to be created
- */
- public static String getCacheFileName(String id, String locale, Context context) {
- final String fileName = replaceFileNameDangerousCharacters(id);
- return getCacheDirectoryForLocale(locale, context) + File.separator + fileName;
- }
-
- /**
* Generates a unique temporary file name in the app cache directory.
*/
public static String getTempFileName(String id, Context context) throws IOException {
- return File.createTempFile(replaceFileNameDangerousCharacters(id), null).getAbsolutePath();
+ return File.createTempFile(DictionaryInfoUtils.replaceFileNameDangerousCharacters(id),
+ null).getAbsolutePath();
}
/**
@@ -222,27 +124,6 @@
}
/**
- * Helper method to the list of cache directories, one for each distinct locale.
- */
- private static File[] getCachedDirectoryList(final Context context) {
- return new File(getWordListCacheDirectory(context)).listFiles();
- }
-
- /**
- * Returns the category for a given file name.
- *
- * This parses the file name, extracts the category, and returns it. See
- * {@link #getMainDictId(Locale)} and {@link #isMainWordListId(String)}.
- * @return The category as a string or null if it can't be found in the file name.
- */
- private static String getCategoryFromFileName(final String fileName) {
- final String id = getWordListIdFromFileName(fileName);
- final String[] idArray = id.split(ID_CATEGORY_SEPARATOR);
- if (2 != idArray.length) return null;
- return idArray[0];
- }
-
- /**
* Utility class for the {@link #getCachedWordLists} method
*/
private static final class FileAndMatchLevel {
@@ -268,20 +149,21 @@
* @param context the context on which to open the files upon.
* @return an array of binary dictionary files, which may be empty but may not be null.
*/
- private static File[] getCachedWordLists(final String locale,
- final Context context) {
- final File[] directoryList = getCachedDirectoryList(context);
+ private static File[] getCachedWordLists(final String locale, final Context context) {
+ final File[] directoryList = DictionaryInfoUtils.getCachedDirectoryList(context);
if (null == directoryList) return EMPTY_FILE_ARRAY;
final HashMap<String, FileAndMatchLevel> cacheFiles = CollectionUtils.newHashMap();
for (File directory : directoryList) {
if (!directory.isDirectory()) continue;
- final String dirLocale = getWordListIdFromFileName(directory.getName());
+ final String dirLocale =
+ DictionaryInfoUtils.getWordListIdFromFileName(directory.getName());
final int matchLevel = LocaleUtils.getMatchLevel(dirLocale, locale);
if (LocaleUtils.isMatch(matchLevel)) {
final File[] wordLists = directory.listFiles();
if (null != wordLists) {
for (File wordList : wordLists) {
- final String category = getCategoryFromFileName(wordList.getName());
+ final String category =
+ DictionaryInfoUtils.getCategoryFromFileName(wordList.getName());
final FileAndMatchLevel currentBestMatch = cacheFiles.get(category);
if (null == currentBestMatch || currentBestMatch.mMatchLevel < matchLevel) {
cacheFiles.put(category, new FileAndMatchLevel(wordList, matchLevel));
@@ -310,7 +192,7 @@
final File fileToKeep) {
try {
final File canonicalFileToKeep = fileToKeep.getCanonicalFile();
- final File[] directoryList = getCachedDirectoryList(context);
+ final File[] directoryList = DictionaryInfoUtils.getCachedDirectoryList(context);
if (null == directoryList) return;
for (File directory : directoryList) {
// There is one directory per locale. See #getCachedDirectoryList
@@ -318,7 +200,8 @@
final File[] wordLists = directory.listFiles();
if (null == wordLists) continue;
for (File wordList : wordLists) {
- final String fileId = getWordListIdFromFileName(wordList.getName());
+ final String fileId =
+ DictionaryInfoUtils.getWordListIdFromFileName(wordList.getName());
if (fileId.equals(id)) {
if (!canonicalFileToKeep.equals(wordList.getCanonicalFile())) {
wordList.delete();
@@ -331,28 +214,6 @@
}
}
-
- /**
- * Returns the id associated with the main word list for a specified locale.
- *
- * Word lists stored in Android Keyboard's resources are referred to as the "main"
- * word lists. Since they can be updated like any other list, we need to assign a
- * unique ID to them. This ID is just the name of the language (locale-wise) they
- * are for, and this method returns this ID.
- */
- private static String getMainDictId(final Locale locale) {
- // This works because we don't include by default different dictionaries for
- // different countries. This actually needs to return the id that we would
- // like to use for word lists included in resources, and the following is okay.
- return MAIN_DICTIONARY_CATEGORY + ID_CATEGORY_SEPARATOR + locale.getLanguage().toString();
- }
-
- private static boolean isMainWordListId(final String id) {
- final String[] idArray = id.split(ID_CATEGORY_SEPARATOR);
- if (2 != idArray.length) return false;
- return MAIN_DICTIONARY_CATEGORY.equals(idArray[0]);
- }
-
// ## HACK ## we prevent usage of a dictionary before version 18 for English only. The reason
// for this is, since those do not include whitelist entries, the new code with an old version
// of the dictionary would lose whitelist functionality.
@@ -429,16 +290,16 @@
hasDefaultWordList);
}
final File[] cachedWordLists = getCachedWordLists(locale.toString(), context);
- final String mainDictId = getMainDictId(locale);
+ final String mainDictId = DictionaryInfoUtils.getMainDictId(locale);
final DictPackSettings dictPackSettings = new DictPackSettings(context);
boolean foundMainDict = false;
final ArrayList<AssetFileAddress> fileList = CollectionUtils.newArrayList();
// cachedWordLists may not be null, see doc for getCachedDictionaryList
for (final File f : cachedWordLists) {
- final String wordListId = getWordListIdFromFileName(f.getName());
+ final String wordListId = DictionaryInfoUtils.getWordListIdFromFileName(f.getName());
final boolean canUse = f.canRead() && hackCanUseDictionaryFile(locale, f);
- if (canUse && isMainWordListId(wordListId)) {
+ if (canUse && DictionaryInfoUtils.isMainWordListId(wordListId)) {
foundMainDict = true;
}
if (!dictPackSettings.isWordListActive(wordListId)) continue;
@@ -451,7 +312,7 @@
if (!foundMainDict && dictPackSettings.isWordListActive(mainDictId)) {
final int fallbackResId =
- DictionaryFactory.getMainDictionaryResourceId(context.getResources(), locale);
+ DictionaryInfoUtils.getMainDictionaryResourceId(context.getResources(), locale);
final AssetFileAddress fallbackAsset = loadFallbackResource(context, fallbackResId);
if (null != fallbackAsset) {
fileList.add(fallbackAsset);
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java
index 388ad6c..40e5167 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java
@@ -31,9 +31,6 @@
*/
public final class DictionaryFactory {
private static final String TAG = DictionaryFactory.class.getSimpleName();
- // This class must be located in the same package as LatinIME.java.
- private static final String RESOURCE_PACKAGE_NAME =
- DictionaryFactory.class.getPackage().getName();
/**
* Initializes a main dictionary collection from a dictionary pack, with explicit flags.
@@ -96,8 +93,8 @@
final Locale locale) {
AssetFileDescriptor afd = null;
try {
- final int resId =
- getMainDictionaryResourceIdIfAvailableForLocale(context.getResources(), locale);
+ final int resId = DictionaryInfoUtils.getMainDictionaryResourceIdIfAvailableForLocale(
+ context.getResources(), locale);
if (0 == resId) return null;
afd = context.getResources().openRawResourceFd(resId);
if (afd == null) {
@@ -154,47 +151,7 @@
*/
public static boolean isDictionaryAvailable(Context context, Locale locale) {
final Resources res = context.getResources();
- return 0 != getMainDictionaryResourceIdIfAvailableForLocale(res, locale);
- }
-
- private static final String DEFAULT_MAIN_DICT = "main";
- private static final String MAIN_DICT_PREFIX = "main_";
-
- /**
- * Helper method to return a dictionary res id for a locale, or 0 if none.
- * @param locale dictionary locale
- * @return main dictionary resource id
- */
- private static int getMainDictionaryResourceIdIfAvailableForLocale(final Resources res,
- final Locale locale) {
- int resId;
- // Try to find main_language_country dictionary.
- if (!locale.getCountry().isEmpty()) {
- final String dictLanguageCountry = MAIN_DICT_PREFIX + locale.toString().toLowerCase();
- if ((resId = res.getIdentifier(
- dictLanguageCountry, "raw", RESOURCE_PACKAGE_NAME)) != 0) {
- return resId;
- }
- }
-
- // Try to find main_language dictionary.
- final String dictLanguage = MAIN_DICT_PREFIX + locale.getLanguage();
- if ((resId = res.getIdentifier(dictLanguage, "raw", RESOURCE_PACKAGE_NAME)) != 0) {
- return resId;
- }
-
- // Not found, return 0
- return 0;
- }
-
- /**
- * Returns a main dictionary resource id
- * @param locale dictionary locale
- * @return main dictionary resource id
- */
- public static int getMainDictionaryResourceId(final Resources res, final Locale locale) {
- int resourceId = getMainDictionaryResourceIdIfAvailableForLocale(res, locale);
- if (0 != resourceId) return resourceId;
- return res.getIdentifier(DEFAULT_MAIN_DICT, "raw", RESOURCE_PACKAGE_NAME);
+ return 0 != DictionaryInfoUtils.getMainDictionaryResourceIdIfAvailableForLocale(
+ res, locale);
}
}
diff --git a/java/src/com/android/inputmethod/latin/DictionaryInfoUtils.java b/java/src/com/android/inputmethod/latin/DictionaryInfoUtils.java
new file mode 100644
index 0000000..c676bf1
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/DictionaryInfoUtils.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.Log;
+
+import com.android.inputmethod.latin.makedict.BinaryDictIOUtils;
+import com.android.inputmethod.latin.makedict.FormatSpec.FileHeader;
+import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Locale;
+
+/**
+ * This class encapsulates the logic for the Latin-IME side of dictionary information management.
+ */
+public class DictionaryInfoUtils {
+ private static final String TAG = DictionaryInfoUtils.class.getSimpleName();
+ // This class must be located in the same package as LatinIME.java.
+ private static final String RESOURCE_PACKAGE_NAME =
+ DictionaryInfoUtils.class.getPackage().getName();
+ private static final String DEFAULT_MAIN_DICT = "main";
+ private static final String MAIN_DICT_PREFIX = "main_";
+ // 6 digits - unicode is limited to 21 bits
+ private static final int MAX_HEX_DIGITS_FOR_CODEPOINT = 6;
+
+ private DictionaryInfoUtils() {
+ // Private constructor to forbid instantation of this helper class.
+ }
+
+ /**
+ * Returns whether we may want to use this character as part of a file name.
+ *
+ * This basically only accepts ascii letters and numbers, and rejects everything else.
+ */
+ private static boolean isFileNameCharacter(int codePoint) {
+ if (codePoint >= 0x30 && codePoint <= 0x39) return true; // Digit
+ if (codePoint >= 0x41 && codePoint <= 0x5A) return true; // Uppercase
+ if (codePoint >= 0x61 && codePoint <= 0x7A) return true; // Lowercase
+ return codePoint == '_'; // Underscore
+ }
+
+ /**
+ * Escapes a string for any characters that may be suspicious for a file or directory name.
+ *
+ * Concretely this does a sort of URL-encoding except it will encode everything that's not
+ * alphanumeric or underscore. (true URL-encoding leaves alone characters like '*', which
+ * we cannot allow here)
+ */
+ // TODO: create a unit test for this method
+ public static String replaceFileNameDangerousCharacters(final String name) {
+ // This assumes '%' is fully available as a non-separator, normal
+ // character in a file name. This is probably true for all file systems.
+ final StringBuilder sb = new StringBuilder();
+ final int nameLength = name.length();
+ for (int i = 0; i < nameLength; i = name.offsetByCodePoints(i, 1)) {
+ final int codePoint = name.codePointAt(i);
+ if (DictionaryInfoUtils.isFileNameCharacter(codePoint)) {
+ sb.appendCodePoint(codePoint);
+ } else {
+ sb.append(String.format((Locale)null, "%%%1$0" + MAX_HEX_DIGITS_FOR_CODEPOINT + "x",
+ codePoint));
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Helper method to get the top level cache directory.
+ */
+ private static String getWordListCacheDirectory(final Context context) {
+ return context.getFilesDir() + File.separator + "dicts";
+ }
+
+ /**
+ * Reverse escaping done by replaceFileNameDangerousCharacters.
+ */
+ public static String getWordListIdFromFileName(final String fname) {
+ final StringBuilder sb = new StringBuilder();
+ final int fnameLength = fname.length();
+ for (int i = 0; i < fnameLength; i = fname.offsetByCodePoints(i, 1)) {
+ final int codePoint = fname.codePointAt(i);
+ if ('%' != codePoint) {
+ sb.appendCodePoint(codePoint);
+ } else {
+ // + 1 to pass the % sign
+ final int encodedCodePoint = Integer.parseInt(
+ fname.substring(i + 1, i + 1 + MAX_HEX_DIGITS_FOR_CODEPOINT), 16);
+ i += MAX_HEX_DIGITS_FOR_CODEPOINT;
+ sb.appendCodePoint(encodedCodePoint);
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Helper method to the list of cache directories, one for each distinct locale.
+ */
+ public static File[] getCachedDirectoryList(final Context context) {
+ return new File(DictionaryInfoUtils.getWordListCacheDirectory(context)).listFiles();
+ }
+
+ /**
+ * Returns the category for a given file name.
+ *
+ * This parses the file name, extracts the category, and returns it. See
+ * {@link #getMainDictId(Locale)} and {@link #isMainWordListId(String)}.
+ * @return The category as a string or null if it can't be found in the file name.
+ */
+ public static String getCategoryFromFileName(final String fileName) {
+ final String id = getWordListIdFromFileName(fileName);
+ final String[] idArray = id.split(BinaryDictionaryGetter.ID_CATEGORY_SEPARATOR);
+ // An id is supposed to be in format category:locale, so splitting on the separator
+ // should yield a 2-elements array
+ if (2 != idArray.length) return null;
+ return idArray[0];
+ }
+
+ /**
+ * Find out the cache directory associated with a specific locale.
+ */
+ private static String getCacheDirectoryForLocale(final String locale, final Context context) {
+ final String relativeDirectoryName = replaceFileNameDangerousCharacters(locale);
+ final String absoluteDirectoryName = getWordListCacheDirectory(context) + File.separator
+ + relativeDirectoryName;
+ final File directory = new File(absoluteDirectoryName);
+ if (!directory.exists()) {
+ if (!directory.mkdirs()) {
+ Log.e(TAG, "Could not create the directory for locale" + locale);
+ }
+ }
+ return absoluteDirectoryName;
+ }
+
+ /**
+ * Generates a file name for the id and locale passed as an argument.
+ *
+ * In the current implementation the file name returned will always be unique for
+ * any id/locale pair, but please do not expect that the id can be the same for
+ * different dictionaries with different locales. An id should be unique for any
+ * dictionary.
+ * The file name is pretty much an URL-encoded version of the id inside a directory
+ * named like the locale, except it will also escape characters that look dangerous
+ * to some file systems.
+ * @param id the id of the dictionary for which to get a file name
+ * @param locale the locale for which to get the file name as a string
+ * @param context the context to use for getting the directory
+ * @return the name of the file to be created
+ */
+ public static String getCacheFileName(String id, String locale, Context context) {
+ final String fileName = replaceFileNameDangerousCharacters(id);
+ return getCacheDirectoryForLocale(locale, context) + File.separator + fileName;
+ }
+
+ public static boolean isMainWordListId(final String id) {
+ final String[] idArray = id.split(BinaryDictionaryGetter.ID_CATEGORY_SEPARATOR);
+ // An id is supposed to be in format category:locale, so splitting on the separator
+ // should yield a 2-elements array
+ if (2 != idArray.length) return false;
+ return BinaryDictionaryGetter.MAIN_DICTIONARY_CATEGORY.equals(idArray[0]);
+ }
+
+ /**
+ * Helper method to return a dictionary res id for a locale, or 0 if none.
+ * @param locale dictionary locale
+ * @return main dictionary resource id
+ */
+ public static int getMainDictionaryResourceIdIfAvailableForLocale(final Resources res,
+ final Locale locale) {
+ int resId;
+ // Try to find main_language_country dictionary.
+ if (!locale.getCountry().isEmpty()) {
+ final String dictLanguageCountry =
+ MAIN_DICT_PREFIX + locale.toString().toLowerCase(Locale.ROOT);
+ if ((resId = res.getIdentifier(
+ dictLanguageCountry, "raw", RESOURCE_PACKAGE_NAME)) != 0) {
+ return resId;
+ }
+ }
+
+ // Try to find main_language dictionary.
+ final String dictLanguage = MAIN_DICT_PREFIX + locale.getLanguage();
+ if ((resId = res.getIdentifier(dictLanguage, "raw", RESOURCE_PACKAGE_NAME)) != 0) {
+ return resId;
+ }
+
+ // Not found, return 0
+ return 0;
+ }
+
+ /**
+ * Returns a main dictionary resource id
+ * @param locale dictionary locale
+ * @return main dictionary resource id
+ */
+ public static int getMainDictionaryResourceId(final Resources res, final Locale locale) {
+ int resourceId = getMainDictionaryResourceIdIfAvailableForLocale(res, locale);
+ if (0 != resourceId) return resourceId;
+ return res.getIdentifier(DEFAULT_MAIN_DICT, "raw", RESOURCE_PACKAGE_NAME);
+ }
+
+ /**
+ * Returns the id associated with the main word list for a specified locale.
+ *
+ * Word lists stored in Android Keyboard's resources are referred to as the "main"
+ * word lists. Since they can be updated like any other list, we need to assign a
+ * unique ID to them. This ID is just the name of the language (locale-wise) they
+ * are for, and this method returns this ID.
+ */
+ public static String getMainDictId(final Locale locale) {
+ // This works because we don't include by default different dictionaries for
+ // different countries. This actually needs to return the id that we would
+ // like to use for word lists included in resources, and the following is okay.
+ return BinaryDictionaryGetter.MAIN_DICTIONARY_CATEGORY +
+ BinaryDictionaryGetter.ID_CATEGORY_SEPARATOR + locale.getLanguage().toString();
+ }
+
+ public static FileHeader getDictionaryFileHeaderOrNull(final File file) {
+ try {
+ final FileHeader header = BinaryDictIOUtils.getDictionaryFileHeader(file);
+ return header;
+ } catch (UnsupportedFormatException e) {
+ return null;
+ } catch (IOException e) {
+ return null;
+ }
+ }
+}
diff --git a/java/src/com/android/inputmethod/latin/ExternalDictionaryGetterForDebug.java b/java/src/com/android/inputmethod/latin/ExternalDictionaryGetterForDebug.java
index 6e5a37c..d9e4bb6 100644
--- a/java/src/com/android/inputmethod/latin/ExternalDictionaryGetterForDebug.java
+++ b/java/src/com/android/inputmethod/latin/ExternalDictionaryGetterForDebug.java
@@ -21,11 +21,8 @@
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.os.Environment;
-import android.util.Log;
-import com.android.inputmethod.latin.makedict.BinaryDictIOUtils;
import com.android.inputmethod.latin.makedict.FormatSpec.FileHeader;
-import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
@@ -44,22 +41,11 @@
+ "/Download";
private static final String DICTIONARY_LOCALE_ATTRIBUTE = "locale";
- private static FileHeader getDictionaryFileHeaderOrNull(final File file) {
- try {
- final FileHeader header = BinaryDictIOUtils.getDictionaryFileHeader(file);
- return header;
- } catch (UnsupportedFormatException e) {
- return null;
- } catch (IOException e) {
- return null;
- }
- }
-
private static String[] findDictionariesInTheDownloadedFolder() {
final File[] files = new File(SOURCE_FOLDER).listFiles();
final ArrayList<String> eligibleList = CollectionUtils.newArrayList();
for (File f : files) {
- final FileHeader header = getDictionaryFileHeaderOrNull(f);
+ final FileHeader header = DictionaryInfoUtils.getDictionaryFileHeaderOrNull(f);
if (null == header) continue;
eligibleList.add(f.getName());
}
@@ -102,7 +88,7 @@
private static void askInstallFile(final Context context, final String fileName) {
final File file = new File(SOURCE_FOLDER, fileName.toString());
- final FileHeader header = getDictionaryFileHeaderOrNull(file);
+ final FileHeader header = DictionaryInfoUtils.getDictionaryFileHeaderOrNull(file);
final StringBuilder message = new StringBuilder();
final String locale =
header.mDictionaryOptions.mAttributes.get(DICTIONARY_LOCALE_ATTRIBUTE);
@@ -143,7 +129,7 @@
final String id = BinaryDictionaryGetter.MAIN_DICTIONARY_CATEGORY
+ BinaryDictionaryGetter.ID_CATEGORY_SEPARATOR + locale;
final String finalFileName =
- BinaryDictionaryGetter.getCacheFileName(id, locale, context);
+ DictionaryInfoUtils.getCacheFileName(id, locale, context);
final String tempFileName = BinaryDictionaryGetter.getTempFileName(id, context);
tempFile = new File(tempFileName);
tempFile.delete();
diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
index 5c8ef7e..ca38b0d 100644
--- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
+++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp
@@ -87,7 +87,7 @@
AKLOGE("DICT: Can't allocate memory region for dictionary. errno=%d", errno);
return 0;
}
- int ret = fseek(file, (long)dictOffset, SEEK_SET);
+ int ret = fseek(file, static_cast<long>(dictOffset), SEEK_SET);
if (ret != 0) {
AKLOGE("DICT: Failure in fseek. ret=%d errno=%d", ret, errno);
return 0;
@@ -121,7 +121,7 @@
}
PROF_END(66);
PROF_CLOSE;
- return (jlong)dictionary;
+ return reinterpret_cast<jlong>(dictionary);
}
static int latinime_BinaryDictionary_getSuggestions(JNIEnv *env, jclass clazz, jlong dict,
@@ -216,7 +216,7 @@
static jboolean latinime_BinaryDictionary_isValidBigram(JNIEnv *env, jclass clazz, jlong dict,
jintArray wordArray1, jintArray wordArray2) {
Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict);
- if (!dictionary) return (jboolean) false;
+ if (!dictionary) return JNI_FALSE;
const jsize codePointLength1 = env->GetArrayLength(wordArray1);
const jsize codePointLength2 = env->GetArrayLength(wordArray2);
int codePoints1[codePointLength1];
diff --git a/native/jni/src/binary_format.h b/native/jni/src/binary_format.h
index 61780de..f19d5e3 100644
--- a/native/jni/src/binary_format.h
+++ b/native/jni/src/binary_format.h
@@ -314,7 +314,7 @@
}
static AK_FORCE_INLINE int shortcutByteSize(const uint8_t *const dict, const int pos) {
- return ((int)(dict[pos] << 8)) + (dict[pos + 1]);
+ return (static_cast<int>(dict[pos] << 8)) + (dict[pos + 1]);
}
inline int BinaryFormat::skipChildrenPosition(const uint8_t flags, const int pos) {
diff --git a/native/jni/src/correction.cpp b/native/jni/src/correction.cpp
index e892c85..d4bd4aa 100644
--- a/native/jni/src/correction.cpp
+++ b/native/jni/src/correction.cpp
@@ -112,7 +112,7 @@
mMaxErrors = maxErrors;
}
-void Correction::checkState() {
+void Correction::checkState() const {
if (DEBUG_DICT) {
int inputCount = 0;
if (mSkipPos >= 0) ++inputCount;
@@ -121,12 +121,12 @@
}
}
-bool Correction::sameAsTyped() {
+bool Correction::sameAsTyped() const {
return mProximityInfoState.sameAsTyped(mWord, mOutputIndex);
}
int Correction::getFreqForSplitMultipleWords(const int *freqArray, const int *wordLengthArray,
- const int wordCount, const bool isSpaceProximity, const int *word) {
+ const int wordCount, const bool isSpaceProximity, const int *word) const {
return Correction::RankingAlgorithm::calcFreqForSplitMultipleWords(freqArray, wordLengthArray,
wordCount, this, isSpaceProximity, word);
}
@@ -677,7 +677,7 @@
const float factor =
SuggestUtils::getDistanceScalingFactor(static_cast<float>(squaredDistance));
if (factor > 0.0f) {
- multiplyRate((int)(factor * 100.0f), &finalFreq);
+ multiplyRate(static_cast<int>(factor * 100.0f), &finalFreq);
} else if (squaredDistance == PROXIMITY_CHAR_WITHOUT_DISTANCE_INFO) {
multiplyRate(WORDS_WITH_PROXIMITY_CHARACTER_DEMOTION_RATE, &finalFreq);
}
diff --git a/native/jni/src/correction.h b/native/jni/src/correction.h
index 89e300d..0873dae 100644
--- a/native/jni/src/correction.h
+++ b/native/jni/src/correction.h
@@ -64,8 +64,8 @@
void setCorrectionParams(const int skipPos, const int excessivePos, const int transposedPos,
const int spaceProximityPos, const int missingSpacePos, const bool useFullEditDistance,
const bool doAutoCompletion, const int maxErrors);
- void checkState();
- bool sameAsTyped();
+ void checkState() const;
+ bool sameAsTyped() const;
bool initProcessState(const int index);
int getInputIndex() const;
@@ -77,7 +77,7 @@
}
int getFreqForSplitMultipleWords(const int *freqArray, const int *wordLengthArray,
- const int wordCount, const bool isSpaceProximity, const int *word);
+ const int wordCount, const bool isSpaceProximity, const int *word) const;
int getFinalProbability(const int probability, int **word, int *wordLength);
int getFinalProbabilityForSubQueue(const int probability, int **word, int *wordLength,
const int inputSize);
diff --git a/native/jni/src/proximity_info_state.cpp b/native/jni/src/proximity_info_state.cpp
index 387b03a..141be26 100644
--- a/native/jni/src/proximity_info_state.cpp
+++ b/native/jni/src/proximity_info_state.cpp
@@ -27,8 +27,6 @@
namespace latinime {
-const int ProximityInfoState::NOT_A_CODE = -1;
-
void ProximityInfoState::initInputParams(const int pointerId, const float maxPointToKeyLength,
const ProximityInfo *proximityInfo, const int *const inputCodes, const int inputSize,
const int *const xCoordinates, const int *const yCoordinates, const int *const times,
diff --git a/native/jni/src/proximity_info_state.h b/native/jni/src/proximity_info_state.h
index 7422cb0..ff1b350 100644
--- a/native/jni/src/proximity_info_state.h
+++ b/native/jni/src/proximity_info_state.h
@@ -32,9 +32,6 @@
class ProximityInfoState {
public:
-
- static const int NOT_A_CODE;
-
/////////////////////////////////////////
// Defined in proximity_info_state.cpp //
/////////////////////////////////////////
@@ -196,6 +193,7 @@
const int from, const int to, const int keyId, const bool extend) const;
bool isKeyInSerchKeysAfterIndex(const int index, const int keyId) const;
+
private:
DISALLOW_COPY_AND_ASSIGN(ProximityInfoState);
/////////////////////////////////////////
diff --git a/native/jni/src/proximity_info_state_utils.cpp b/native/jni/src/proximity_info_state_utils.cpp
index 9f85743..ac74a4e 100644
--- a/native/jni/src/proximity_info_state_utils.cpp
+++ b/native/jni/src/proximity_info_state_utils.cpp
@@ -211,7 +211,7 @@
ProximityInfoParams::NOT_A_DISTANCE_FLOAT;
if (squaredDistance >= 0.0f) {
normalizedSquaredDistances[i * MAX_PROXIMITY_CHARS_SIZE + j] =
- (int) (squaredDistance
+ static_cast<int>(squaredDistance
* ProximityInfoParams::NORMALIZED_SQUARED_DISTANCE_SCALING_FACTOR);
} else {
normalizedSquaredDistances[i * MAX_PROXIMITY_CHARS_SIZE + j] =
diff --git a/native/jni/src/suggest_utils.h b/native/jni/src/suggest_utils.h
index 7d49cde..aab9f7b 100644
--- a/native/jni/src/suggest_utils.h
+++ b/native/jni/src/suggest_utils.h
@@ -19,7 +19,6 @@
#include "defines.h"
#include "proximity_info_params.h"
-#include "proximity_info_state.h"
namespace latinime {
class SuggestUtils {
diff --git a/native/jni/src/words_priority_queue.h b/native/jni/src/words_priority_queue.h
index 7aab1e0..8a22f05 100644
--- a/native/jni/src/words_priority_queue.h
+++ b/native/jni/src/words_priority_queue.h
@@ -87,7 +87,7 @@
}
}
- SuggestedWord *top() {
+ SuggestedWord *top() const {
if (mSuggestions.empty()) return 0;
SuggestedWord *sw = mSuggestions.top();
return sw;
@@ -110,7 +110,7 @@
}
}
- AK_FORCE_INLINE void dumpTopWord() {
+ AK_FORCE_INLINE void dumpTopWord() const {
if (size() <= 0) {
return;
}
@@ -118,7 +118,7 @@
}
AK_FORCE_INLINE float getHighestNormalizedScore(const int *before, const int beforeLength,
- int **outWord, int *outScore, int *outLength) {
+ int **outWord, int *outScore, int *outLength) const {
if (!mHighestSuggestedWord) {
return 0.0f;
}
@@ -137,7 +137,7 @@
}
};
- SuggestedWord *getFreeSuggestedWord(int score, int *word, int wordLength, int type) {
+ SuggestedWord *getFreeSuggestedWord(int score, int *word, int wordLength, int type) const {
for (int i = 0; i < MAX_WORD_LENGTH; ++i) {
if (!mSuggestedWords[i].mUsed) {
mSuggestedWords[i].setParams(score, word, wordLength, type);
diff --git a/native/jni/src/words_priority_queue_pool.h b/native/jni/src/words_priority_queue_pool.h
index cfe7ede..2cd210a 100644
--- a/native/jni/src/words_priority_queue_pool.h
+++ b/native/jni/src/words_priority_queue_pool.h
@@ -44,11 +44,11 @@
}
}
- WordsPriorityQueue *getMasterQueue() {
+ WordsPriorityQueue *getMasterQueue() const {
return mMasterQueue;
}
- WordsPriorityQueue *getSubQueue(const int wordIndex, const int inputWordLength) {
+ WordsPriorityQueue *getSubQueue(const int wordIndex, const int inputWordLength) const {
if (wordIndex >= MULTIPLE_WORDS_SUGGESTION_MAX_WORDS) {
return 0;
}
@@ -77,7 +77,7 @@
}
}
- void dumpSubQueue1TopSuggestions() {
+ void dumpSubQueue1TopSuggestions() const {
AKLOGI("DUMP SUBQUEUE1 TOP SUGGESTIONS");
for (int i = 0; i < SUB_QUEUE_MAX_COUNT; ++i) {
getSubQueue(0, i)->dumpTopWord();