/* * Copyright (C) 2012 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.keyboard.internal; import android.content.Context; import android.content.res.Resources; import android.text.TextUtils; import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.latin.utils.CollectionUtils; import java.util.HashMap; /** * !!!!! DO NOT EDIT THIS FILE !!!!! * * This file is generated by tools/make-keyboard-text. The base template file is * tools/make-keyboard-text/res/com/android/inputmethod/keyboard/internal/KeyboardTextsSet.tmpl * * This file must be updated when any text resources in keyboard layout files have been changed. * These text resources are referred as "!text/" in keyboard XML definitions, * and should be defined in * tools/make-keyboard-text/res/values-/donottranslate-more-keys.xml * * To update this file, please run the following commands. * $ cd $ANDROID_BUILD_TOP * $ mmm packages/inputmethods/LatinIME/tools/make-keyboard-text * $ make-keyboard-text -java packages/inputmethods/LatinIME/java/src * * The updated source file will be generated to the following path (this file). * packages/inputmethods/LatinIME/java/src/com/android/inputmethod/keyboard/internal/ * KeyboardTextsSet.java */ public final class KeyboardTextsSet { private static final String PREFIX_TEXT = "!text/"; private static final char BACKSLASH = '\\'; private static final int MAX_STRING_REFERENCE_INDIRECTION = 10; // Language to texts map. private static final HashMap sLocaleToTextsMap = CollectionUtils.newHashMap(); private static final HashMap sNameToIdsMap = CollectionUtils.newHashMap(); private String[] mTexts; // Resource name to text map. private HashMap mResourceNameToTextsMap = CollectionUtils.newHashMap(); public void setLanguage(final String language) { mTexts = sLocaleToTextsMap.get(language); if (mTexts == null) { mTexts = LANGUAGE_DEFAULT; } } public void loadStringResources(final Context context) { final int referenceId = context.getApplicationInfo().labelRes; loadStringResourcesInternal(context, RESOURCE_NAMES, referenceId); } @UsedForTesting void loadStringResourcesInternal(final Context context, final String[] resourceNames, final int referenceId) { final Resources res = context.getResources(); final String packageName = res.getResourcePackageName(referenceId); for (final String resName : resourceNames) { final int resId = res.getIdentifier(resName, "string", packageName); mResourceNameToTextsMap.put(resName, res.getString(resId)); } } public String getText(final String name) { String text = mResourceNameToTextsMap.get(name); if (text != null) { return text; } final Integer id = sNameToIdsMap.get(name); if (id == null) throw new RuntimeException("Unknown label: " + name); text = (id < mTexts.length) ? mTexts[id] : null; return (text == null) ? LANGUAGE_DEFAULT[id] : text; } private static int searchTextNameEnd(final String text, final int start) { final int size = text.length(); for (int pos = start; pos < size; pos++) { final char c = text.charAt(pos); // Label name should be consisted of [a-zA-Z_0-9]. if ((c >= 'a' && c <= 'z') || c == '_' || (c >= '0' && c <= '9')) { continue; } return pos; } return size; } public String resolveTextReference(final String rawText) { if (TextUtils.isEmpty(rawText)) { return null; } int level = 0; String text = rawText; StringBuilder sb; do { level++; if (level >= MAX_STRING_REFERENCE_INDIRECTION) { throw new RuntimeException("too many @string/resource indirection: " + text); } final int prefixLen = PREFIX_TEXT.length(); final int size = text.length(); if (size < prefixLen) { return TextUtils.isEmpty(text) ? null : text; } sb = null; for (int pos = 0; pos < size; pos++) { final char c = text.charAt(pos); if (text.startsWith(PREFIX_TEXT, pos)) { if (sb == null) { sb = new StringBuilder(text.substring(0, pos)); } final int end = searchTextNameEnd(text, pos + prefixLen); final String name = text.substring(pos + prefixLen, end); sb.append(getText(name)); pos = end - 1; } else if (c == BACKSLASH) { if (sb != null) { // Append both escape character and escaped character. sb.append(text.substring(pos, Math.min(pos + 2, size))); } pos++; } else if (sb != null) { sb.append(c); } } if (sb != null) { text = sb.toString(); } } while (sb != null); return TextUtils.isEmpty(text) ? null : text; } // These texts' name should be aligned with the @string/ in // values*/strings-action-keys.xml. private static final String[] RESOURCE_NAMES = { // Labels for action. "label_go_key", "label_send_key", "label_next_key", "label_done_key", "label_previous_key", // Other labels. "label_pause_key", "label_wait_key", }; private static final String[] NAMES = { /* @NAMES@ */ }; private static final String EMPTY = ""; /* Default texts */ private static final String[] LANGUAGE_DEFAULT = { /* @DEFAULT_TEXTS@ */ }; /* @TEXTS@ */ // TODO: Use the language + "_" + region representation for the locale string key. // Currently we are dropping the region from the key. private static final Object[] LANGUAGES_AND_TEXTS = { /* @LANGUAGES_AND_TEXTS@ */ }; static { int id = 0; for (final String name : NAMES) { sNameToIdsMap.put(name, id++); } for (int i = 0; i < LANGUAGES_AND_TEXTS.length; i += 2) { final String language = (String)LANGUAGES_AND_TEXTS[i]; final String[] texts = (String[])LANGUAGES_AND_TEXTS[i + 1]; sLocaleToTextsMap.put(language, texts); } } }