use of android.text.style.SpellCheckSpan in project android_frameworks_base by ResurrectionRemix.
the class SpellChecker method onGetSuggestionsInternal.
private SpellCheckSpan onGetSuggestionsInternal(SuggestionsInfo suggestionsInfo, int offset, int length) {
if (suggestionsInfo == null || suggestionsInfo.getCookie() != mCookie) {
return null;
}
final Editable editable = (Editable) mTextView.getText();
final int sequenceNumber = suggestionsInfo.getSequence();
for (int k = 0; k < mLength; ++k) {
if (sequenceNumber == mIds[k]) {
final int attributes = suggestionsInfo.getSuggestionsAttributes();
final boolean isInDictionary = ((attributes & SuggestionsInfo.RESULT_ATTR_IN_THE_DICTIONARY) > 0);
final boolean looksLikeTypo = ((attributes & SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO) > 0);
final SpellCheckSpan spellCheckSpan = mSpellCheckSpans[k];
// checker that will probably be in dictionary.
if (!isInDictionary && looksLikeTypo) {
createMisspelledSuggestionSpan(editable, suggestionsInfo, spellCheckSpan, offset, length);
} else {
// Valid word -- isInDictionary || !looksLikeTypo
if (mIsSentenceSpellCheckSupported) {
// Allow the spell checker to remove existing misspelled span by
// overwriting the span over the same place
final int spellCheckSpanStart = editable.getSpanStart(spellCheckSpan);
final int spellCheckSpanEnd = editable.getSpanEnd(spellCheckSpan);
final int start;
final int end;
if (offset != USE_SPAN_RANGE && length != USE_SPAN_RANGE) {
start = spellCheckSpanStart + offset;
end = start + length;
} else {
start = spellCheckSpanStart;
end = spellCheckSpanEnd;
}
if (spellCheckSpanStart >= 0 && spellCheckSpanEnd > spellCheckSpanStart && end > start) {
final Long key = Long.valueOf(TextUtils.packRangeInLong(start, end));
final SuggestionSpan tempSuggestionSpan = mSuggestionSpanCache.get(key);
if (tempSuggestionSpan != null) {
if (DBG) {
Log.i(TAG, "Remove existing misspelled span. " + editable.subSequence(start, end));
}
editable.removeSpan(tempSuggestionSpan);
mSuggestionSpanCache.remove(key);
}
}
}
}
return spellCheckSpan;
}
}
return null;
}
use of android.text.style.SpellCheckSpan in project android_frameworks_base by ResurrectionRemix.
the class SpellChecker method onGetSuggestions.
@Override
public void onGetSuggestions(SuggestionsInfo[] results) {
final Editable editable = (Editable) mTextView.getText();
for (int i = 0; i < results.length; ++i) {
final SpellCheckSpan spellCheckSpan = onGetSuggestionsInternal(results[i], USE_SPAN_RANGE, USE_SPAN_RANGE);
if (spellCheckSpan != null) {
// onSpellCheckSpanRemoved will recycle this span in the pool
editable.removeSpan(spellCheckSpan);
}
}
scheduleNewSpellCheck();
}
use of android.text.style.SpellCheckSpan in project android_frameworks_base by ResurrectionRemix.
the class SpellChecker method onGetSentenceSuggestions.
@Override
public void onGetSentenceSuggestions(SentenceSuggestionsInfo[] results) {
final Editable editable = (Editable) mTextView.getText();
for (int i = 0; i < results.length; ++i) {
final SentenceSuggestionsInfo ssi = results[i];
if (ssi == null) {
continue;
}
SpellCheckSpan spellCheckSpan = null;
for (int j = 0; j < ssi.getSuggestionsCount(); ++j) {
final SuggestionsInfo suggestionsInfo = ssi.getSuggestionsInfoAt(j);
if (suggestionsInfo == null) {
continue;
}
final int offset = ssi.getOffsetAt(j);
final int length = ssi.getLengthAt(j);
final SpellCheckSpan scs = onGetSuggestionsInternal(suggestionsInfo, offset, length);
if (spellCheckSpan == null && scs != null) {
// the spellCheckSpan is shared by all the "SuggestionsInfo"s in the same
// SentenceSuggestionsInfo. Removal is deferred after this loop.
spellCheckSpan = scs;
}
}
if (spellCheckSpan != null) {
// onSpellCheckSpanRemoved will recycle this span in the pool
editable.removeSpan(spellCheckSpan);
}
}
scheduleNewSpellCheck();
}
use of android.text.style.SpellCheckSpan in project android_frameworks_base by DirtyUnicorns.
the class TextView method spanChange.
/**
* Not private so it can be called from an inner class without going
* through a thunk.
*/
void spanChange(Spanned buf, Object what, int oldStart, int newStart, int oldEnd, int newEnd) {
// XXX Make the start and end move together if this ends up
// spending too much time invalidating.
boolean selChanged = false;
int newSelStart = -1, newSelEnd = -1;
final Editor.InputMethodState ims = mEditor == null ? null : mEditor.mInputMethodState;
if (what == Selection.SELECTION_END) {
selChanged = true;
newSelEnd = newStart;
if (oldStart >= 0 || newStart >= 0) {
invalidateCursor(Selection.getSelectionStart(buf), oldStart, newStart);
checkForResize();
registerForPreDraw();
if (mEditor != null)
mEditor.makeBlink();
}
}
if (what == Selection.SELECTION_START) {
selChanged = true;
newSelStart = newStart;
if (oldStart >= 0 || newStart >= 0) {
int end = Selection.getSelectionEnd(buf);
invalidateCursor(end, oldStart, newStart);
}
}
if (selChanged) {
mHighlightPathBogus = true;
if (mEditor != null && !isFocused())
mEditor.mSelectionMoved = true;
if ((buf.getSpanFlags(what) & Spanned.SPAN_INTERMEDIATE) == 0) {
if (newSelStart < 0) {
newSelStart = Selection.getSelectionStart(buf);
}
if (newSelEnd < 0) {
newSelEnd = Selection.getSelectionEnd(buf);
}
if (mEditor != null) {
mEditor.refreshTextActionMode();
if (!hasSelection() && mEditor.mTextActionMode == null && hasTransientState()) {
// User generated selection has been removed.
setHasTransientState(false);
}
}
onSelectionChanged(newSelStart, newSelEnd);
}
}
if (what instanceof UpdateAppearance || what instanceof ParagraphStyle || what instanceof CharacterStyle) {
if (ims == null || ims.mBatchEditNesting == 0) {
invalidate();
mHighlightPathBogus = true;
checkForResize();
} else {
ims.mContentChanged = true;
}
if (mEditor != null) {
if (oldStart >= 0)
mEditor.invalidateTextDisplayList(mLayout, oldStart, oldEnd);
if (newStart >= 0)
mEditor.invalidateTextDisplayList(mLayout, newStart, newEnd);
mEditor.invalidateHandlesAndActionMode();
}
}
if (MetaKeyKeyListener.isMetaTracker(buf, what)) {
mHighlightPathBogus = true;
if (ims != null && MetaKeyKeyListener.isSelectingMetaTracker(buf, what)) {
ims.mSelectionModeChanged = true;
}
if (Selection.getSelectionStart(buf) >= 0) {
if (ims == null || ims.mBatchEditNesting == 0) {
invalidateCursor();
} else {
ims.mCursorChanged = true;
}
}
}
if (what instanceof ParcelableSpan) {
// the current extract editor would be interested in it.
if (ims != null && ims.mExtractedTextRequest != null) {
if (ims.mBatchEditNesting != 0) {
if (oldStart >= 0) {
if (ims.mChangedStart > oldStart) {
ims.mChangedStart = oldStart;
}
if (ims.mChangedStart > oldEnd) {
ims.mChangedStart = oldEnd;
}
}
if (newStart >= 0) {
if (ims.mChangedStart > newStart) {
ims.mChangedStart = newStart;
}
if (ims.mChangedStart > newEnd) {
ims.mChangedStart = newEnd;
}
}
} else {
if (DEBUG_EXTRACT)
Log.v(LOG_TAG, "Span change outside of batch: " + oldStart + "-" + oldEnd + "," + newStart + "-" + newEnd + " " + what);
ims.mContentChanged = true;
}
}
}
if (mEditor != null && mEditor.mSpellChecker != null && newStart < 0 && what instanceof SpellCheckSpan) {
mEditor.mSpellChecker.onSpellCheckSpanRemoved((SpellCheckSpan) what);
}
}
use of android.text.style.SpellCheckSpan in project android_frameworks_base by DirtyUnicorns.
the class SpellChecker method spellCheck.
private void spellCheck() {
if (mSpellCheckerSession == null)
return;
Editable editable = (Editable) mTextView.getText();
final int selectionStart = Selection.getSelectionStart(editable);
final int selectionEnd = Selection.getSelectionEnd(editable);
TextInfo[] textInfos = new TextInfo[mLength];
int textInfosCount = 0;
for (int i = 0; i < mLength; i++) {
final SpellCheckSpan spellCheckSpan = mSpellCheckSpans[i];
if (mIds[i] < 0 || spellCheckSpan.isSpellCheckInProgress())
continue;
final int start = editable.getSpanStart(spellCheckSpan);
final int end = editable.getSpanEnd(spellCheckSpan);
// Do not check this word if the user is currently editing it
final boolean isEditing;
// Defer spell check when typing a word with an interior apostrophe.
// TODO: a better solution to this would be to make the word
// iterator locale-sensitive and include the apostrophe in
// languages that use it (such as English).
final boolean apostrophe = (selectionStart == end + 1 && editable.charAt(end) == '\'');
if (mIsSentenceSpellCheckSupported) {
// Allow the overlap of the cursor and the first boundary of the spell check span
// no to skip the spell check of the following word because the
// following word will never be spell-checked even if the user finishes composing
isEditing = !apostrophe && (selectionEnd <= start || selectionStart > end);
} else {
isEditing = !apostrophe && (selectionEnd < start || selectionStart > end);
}
if (start >= 0 && end > start && isEditing) {
spellCheckSpan.setSpellCheckInProgress(true);
final TextInfo textInfo = new TextInfo(editable, start, end, mCookie, mIds[i]);
textInfos[textInfosCount++] = textInfo;
if (DBG) {
Log.d(TAG, "create TextInfo: (" + i + "/" + mLength + ") text = " + textInfo.getSequence() + ", cookie = " + mCookie + ", seq = " + mIds[i] + ", sel start = " + selectionStart + ", sel end = " + selectionEnd + ", start = " + start + ", end = " + end);
}
}
}
if (textInfosCount > 0) {
if (textInfosCount < textInfos.length) {
TextInfo[] textInfosCopy = new TextInfo[textInfosCount];
System.arraycopy(textInfos, 0, textInfosCopy, 0, textInfosCount);
textInfos = textInfosCopy;
}
if (mIsSentenceSpellCheckSupported) {
mSpellCheckerSession.getSentenceSuggestions(textInfos, SuggestionSpan.SUGGESTIONS_MAX_SIZE);
} else {
mSpellCheckerSession.getSuggestions(textInfos, SuggestionSpan.SUGGESTIONS_MAX_SIZE, false);
}
}
}
Aggregations