3030
3131import com .android .internal .util .ArrayUtils ;
3232
33- import java .util .Locale ;
34-
3533
3634/**
3735 * Helper class for TextView. Bridge between the TextView and the Dictionnary service.
@@ -167,15 +165,12 @@ public void spellCheck() {
167165
168166 @ Override
169167 public void onGetSuggestions (SuggestionsInfo [] results ) {
170- final Editable editable = (Editable ) mTextView .getText ();
171168 for (int i = 0 ; i < results .length ; i ++) {
172169 SuggestionsInfo suggestionsInfo = results [i ];
173170 if (suggestionsInfo .getCookie () != mCookie ) continue ;
174171 final int sequenceNumber = suggestionsInfo .getSequence ();
175172
176173 for (int j = 0 ; j < mLength ; j ++) {
177- final SpellCheckSpan spellCheckSpan = mSpellCheckSpans [j ];
178-
179174 if (sequenceNumber == mIds [j ]) {
180175 final int attributes = suggestionsInfo .getSuggestionsAttributes ();
181176 boolean isInDictionary =
@@ -184,31 +179,78 @@ public void onGetSuggestions(SuggestionsInfo[] results) {
184179 ((attributes & SuggestionsInfo .RESULT_ATTR_LOOKS_LIKE_TYPO ) > 0 );
185180
186181 if (!isInDictionary && looksLikeTypo ) {
187- String [] suggestions = getSuggestions (suggestionsInfo );
188- SuggestionSpan suggestionSpan = new SuggestionSpan (
189- mTextView .getContext (), suggestions ,
190- SuggestionSpan .FLAG_EASY_CORRECT |
191- SuggestionSpan .FLAG_MISSPELLED );
192- final int start = editable .getSpanStart (spellCheckSpan );
193- final int end = editable .getSpanEnd (spellCheckSpan );
194- editable .setSpan (suggestionSpan , start , end ,
195- Spanned .SPAN_EXCLUSIVE_EXCLUSIVE );
196- // TODO limit to the word rectangle region
197- mTextView .invalidate ();
182+ createMisspelledSuggestionSpan (suggestionsInfo , mSpellCheckSpans [j ]);
198183 }
199- editable . removeSpan ( spellCheckSpan ) ;
184+ break ;
200185 }
201186 }
202187 }
203188 }
204189
205- private static String [] getSuggestions (SuggestionsInfo suggestionsInfo ) {
206- // A negative suggestion count is possible
207- final int len = Math .max (0 , suggestionsInfo .getSuggestionsCount ());
208- String [] suggestions = new String [len ];
209- for (int j = 0 ; j < len ; j ++) {
210- suggestions [j ] = suggestionsInfo .getSuggestionAt (j );
190+ private void createMisspelledSuggestionSpan (SuggestionsInfo suggestionsInfo ,
191+ SpellCheckSpan spellCheckSpan ) {
192+ final Editable editable = (Editable ) mTextView .getText ();
193+ final int start = editable .getSpanStart (spellCheckSpan );
194+ final int end = editable .getSpanEnd (spellCheckSpan );
195+
196+ // Other suggestion spans may exist on that region, with identical suggestions, filter
197+ // them out to avoid duplicates. First, filter suggestion spans on that exact region.
198+ SuggestionSpan [] suggestionSpans = editable .getSpans (start , end , SuggestionSpan .class );
199+ final int length = suggestionSpans .length ;
200+ for (int i = 0 ; i < length ; i ++) {
201+ final int spanStart = editable .getSpanStart (suggestionSpans [i ]);
202+ final int spanEnd = editable .getSpanEnd (suggestionSpans [i ]);
203+ if (spanStart != start || spanEnd != end ) {
204+ suggestionSpans [i ] = null ;
205+ break ;
206+ }
207+ }
208+
209+ final int suggestionsCount = suggestionsInfo .getSuggestionsCount ();
210+ String [] suggestions ;
211+ if (suggestionsCount <= 0 ) {
212+ // A negative suggestion count is possible
213+ suggestions = ArrayUtils .emptyArray (String .class );
214+ } else {
215+ int numberOfSuggestions = 0 ;
216+ suggestions = new String [suggestionsCount ];
217+
218+ for (int i = 0 ; i < suggestionsCount ; i ++) {
219+ final String spellSuggestion = suggestionsInfo .getSuggestionAt (i );
220+ if (spellSuggestion == null ) break ;
221+ boolean suggestionFound = false ;
222+
223+ for (int j = 0 ; j < length && !suggestionFound ; j ++) {
224+ if (suggestionSpans [j ] == null ) break ;
225+
226+ String [] suggests = suggestionSpans [j ].getSuggestions ();
227+ for (int k = 0 ; k < suggests .length ; k ++) {
228+ if (spellSuggestion .equals (suggests [k ])) {
229+ // The suggestion is already provided by an other SuggestionSpan
230+ suggestionFound = true ;
231+ break ;
232+ }
233+ }
234+ }
235+
236+ if (!suggestionFound ) {
237+ suggestions [numberOfSuggestions ++] = spellSuggestion ;
238+ }
239+ }
240+
241+ if (numberOfSuggestions != suggestionsCount ) {
242+ String [] newSuggestions = new String [numberOfSuggestions ];
243+ System .arraycopy (suggestions , 0 , newSuggestions , 0 , numberOfSuggestions );
244+ suggestions = newSuggestions ;
245+ }
211246 }
212- return suggestions ;
247+
248+ SuggestionSpan suggestionSpan = new SuggestionSpan (mTextView .getContext (), suggestions ,
249+ SuggestionSpan .FLAG_EASY_CORRECT | SuggestionSpan .FLAG_MISSPELLED );
250+ editable .setSpan (suggestionSpan , start , end , Spanned .SPAN_EXCLUSIVE_EXCLUSIVE );
251+
252+ // TODO limit to the word rectangle region
253+ mTextView .invalidate ();
254+ editable .removeSpan (spellCheckSpan );
213255 }
214256}
0 commit comments