1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.inputmethod.latin.settings;
18 
19 import android.content.res.Resources;
20 
21 import com.android.inputmethod.annotations.UsedForTesting;
22 import com.android.inputmethod.keyboard.internal.MoreKeySpec;
23 import com.android.inputmethod.latin.PunctuationSuggestions;
24 import com.android.inputmethod.latin.R;
25 import com.android.inputmethod.latin.common.Constants;
26 import com.android.inputmethod.latin.common.StringUtils;
27 
28 import java.util.Arrays;
29 import java.util.Locale;
30 
31 public final class SpacingAndPunctuations {
32     private final int[] mSortedSymbolsPrecededBySpace;
33     private final int[] mSortedSymbolsFollowedBySpace;
34     private final int[] mSortedSymbolsClusteringTogether;
35     private final int[] mSortedWordConnectors;
36     public final int[] mSortedWordSeparators;
37     public final PunctuationSuggestions mSuggestPuncList;
38     private final int mSentenceSeparator;
39     private final int mAbbreviationMarker;
40     private final int[] mSortedSentenceTerminators;
41     public final String mSentenceSeparatorAndSpace;
42     public final boolean mCurrentLanguageHasSpaces;
43     public final boolean mUsesAmericanTypography;
44     public final boolean mUsesGermanRules;
45 
SpacingAndPunctuations(final Resources res)46     public SpacingAndPunctuations(final Resources res) {
47         // To be able to binary search the code point. See {@link #isUsuallyPrecededBySpace(int)}.
48         mSortedSymbolsPrecededBySpace = StringUtils.toSortedCodePointArray(
49                 res.getString(R.string.symbols_preceded_by_space));
50         // To be able to binary search the code point. See {@link #isUsuallyFollowedBySpace(int)}.
51         mSortedSymbolsFollowedBySpace = StringUtils.toSortedCodePointArray(
52                 res.getString(R.string.symbols_followed_by_space));
53         mSortedSymbolsClusteringTogether = StringUtils.toSortedCodePointArray(
54                 res.getString(R.string.symbols_clustering_together));
55         // To be able to binary search the code point. See {@link #isWordConnector(int)}.
56         mSortedWordConnectors = StringUtils.toSortedCodePointArray(
57                 res.getString(R.string.symbols_word_connectors));
58         mSortedWordSeparators = StringUtils.toSortedCodePointArray(
59                 res.getString(R.string.symbols_word_separators));
60         mSortedSentenceTerminators = StringUtils.toSortedCodePointArray(
61                 res.getString(R.string.symbols_sentence_terminators));
62         mSentenceSeparator = res.getInteger(R.integer.sentence_separator);
63         mAbbreviationMarker = res.getInteger(R.integer.abbreviation_marker);
64         mSentenceSeparatorAndSpace = new String(new int[] {
65                 mSentenceSeparator, Constants.CODE_SPACE }, 0, 2);
66         mCurrentLanguageHasSpaces = res.getBoolean(R.bool.current_language_has_spaces);
67         final Locale locale = res.getConfiguration().locale;
68         // Heuristic: we use American Typography rules because it's the most common rules for all
69         // English variants. German rules (not "German typography") also have small gotchas.
70         mUsesAmericanTypography = Locale.ENGLISH.getLanguage().equals(locale.getLanguage());
71         mUsesGermanRules = Locale.GERMAN.getLanguage().equals(locale.getLanguage());
72         final String[] suggestPuncsSpec = MoreKeySpec.splitKeySpecs(
73                 res.getString(R.string.suggested_punctuations));
74         mSuggestPuncList = PunctuationSuggestions.newPunctuationSuggestions(suggestPuncsSpec);
75     }
76 
77     @UsedForTesting
SpacingAndPunctuations(final SpacingAndPunctuations model, final int[] overrideSortedWordSeparators)78     public SpacingAndPunctuations(final SpacingAndPunctuations model,
79             final int[] overrideSortedWordSeparators) {
80         mSortedSymbolsPrecededBySpace = model.mSortedSymbolsPrecededBySpace;
81         mSortedSymbolsFollowedBySpace = model.mSortedSymbolsFollowedBySpace;
82         mSortedSymbolsClusteringTogether = model.mSortedSymbolsClusteringTogether;
83         mSortedWordConnectors = model.mSortedWordConnectors;
84         mSortedWordSeparators = overrideSortedWordSeparators;
85         mSortedSentenceTerminators = model.mSortedSentenceTerminators;
86         mSuggestPuncList = model.mSuggestPuncList;
87         mSentenceSeparator = model.mSentenceSeparator;
88         mAbbreviationMarker = model.mAbbreviationMarker;
89         mSentenceSeparatorAndSpace = model.mSentenceSeparatorAndSpace;
90         mCurrentLanguageHasSpaces = model.mCurrentLanguageHasSpaces;
91         mUsesAmericanTypography = model.mUsesAmericanTypography;
92         mUsesGermanRules = model.mUsesGermanRules;
93     }
94 
isWordSeparator(final int code)95     public boolean isWordSeparator(final int code) {
96         return Arrays.binarySearch(mSortedWordSeparators, code) >= 0;
97     }
98 
isWordConnector(final int code)99     public boolean isWordConnector(final int code) {
100         return Arrays.binarySearch(mSortedWordConnectors, code) >= 0;
101     }
102 
isWordCodePoint(final int code)103     public boolean isWordCodePoint(final int code) {
104         return Character.isLetter(code) || isWordConnector(code);
105     }
106 
isUsuallyPrecededBySpace(final int code)107     public boolean isUsuallyPrecededBySpace(final int code) {
108         return Arrays.binarySearch(mSortedSymbolsPrecededBySpace, code) >= 0;
109     }
110 
isUsuallyFollowedBySpace(final int code)111     public boolean isUsuallyFollowedBySpace(final int code) {
112         return Arrays.binarySearch(mSortedSymbolsFollowedBySpace, code) >= 0;
113     }
114 
isClusteringSymbol(final int code)115     public boolean isClusteringSymbol(final int code) {
116         return Arrays.binarySearch(mSortedSymbolsClusteringTogether, code) >= 0;
117     }
118 
isSentenceTerminator(final int code)119     public boolean isSentenceTerminator(final int code) {
120         return Arrays.binarySearch(mSortedSentenceTerminators, code) >= 0;
121     }
122 
isAbbreviationMarker(final int code)123     public boolean isAbbreviationMarker(final int code) {
124         return code == mAbbreviationMarker;
125     }
126 
isSentenceSeparator(final int code)127     public boolean isSentenceSeparator(final int code) {
128         return code == mSentenceSeparator;
129     }
130 
dump()131     public String dump() {
132         final StringBuilder sb = new StringBuilder();
133         sb.append("mSortedSymbolsPrecededBySpace = ");
134         sb.append("" + Arrays.toString(mSortedSymbolsPrecededBySpace));
135         sb.append("\n   mSortedSymbolsFollowedBySpace = ");
136         sb.append("" + Arrays.toString(mSortedSymbolsFollowedBySpace));
137         sb.append("\n   mSortedWordConnectors = ");
138         sb.append("" + Arrays.toString(mSortedWordConnectors));
139         sb.append("\n   mSortedWordSeparators = ");
140         sb.append("" + Arrays.toString(mSortedWordSeparators));
141         sb.append("\n   mSuggestPuncList = ");
142         sb.append("" + mSuggestPuncList);
143         sb.append("\n   mSentenceSeparator = ");
144         sb.append("" + mSentenceSeparator);
145         sb.append("\n   mSentenceSeparatorAndSpace = ");
146         sb.append("" + mSentenceSeparatorAndSpace);
147         sb.append("\n   mCurrentLanguageHasSpaces = ");
148         sb.append("" + mCurrentLanguageHasSpaces);
149         sb.append("\n   mUsesAmericanTypography = ");
150         sb.append("" + mUsesAmericanTypography);
151         sb.append("\n   mUsesGermanRules = ");
152         sb.append("" + mUsesGermanRules);
153         return sb.toString();
154     }
155 }
156