Java Code Examples for android.text.Selection#getSelectionEnd()

The following examples show how to use android.text.Selection#getSelectionEnd() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: MultiTapKeyListener.java    From android_9.0.0_r45 with Apache License 2.0 6 votes vote down vote up
public void run() {
    Spannable buf = mBuffer;

    if (buf != null) {
        int st = Selection.getSelectionStart(buf);
        int en = Selection.getSelectionEnd(buf);

        int start = buf.getSpanStart(TextKeyListener.ACTIVE);
        int end = buf.getSpanEnd(TextKeyListener.ACTIVE);

        if (st == start && en == end) {
            Selection.setSelection(buf, Selection.getSelectionEnd(buf));
        }

        buf.removeSpan(Timeout.this);
    }
}
 
Example 2
Source File: ListSelectionManager.java    From Conversations with GNU General Public License v3.0 6 votes vote down vote up
public void onBeforeNotifyDataSetChanged() {
    if (SUPPORTED) {
        HANDLER.removeMessages(MESSAGE_SEND_RESET);
        HANDLER.removeMessages(MESSAGE_RESET);
        HANDLER.removeMessages(MESSAGE_START_SELECTION);
        if (selectionActionMode != null) {
            final CharSequence text = selectionTextView.getText();
            futureSelectionIdentifier = selectionIdentifier;
            futureSelectionStart = Selection.getSelectionStart(text);
            futureSelectionEnd = Selection.getSelectionEnd(text);
            selectionActionMode.finish();
            selectionActionMode = null;
            selectionIdentifier = null;
            selectionTextView = null;
        }
    }
}
 
Example 3
Source File: BaseKeyListener.java    From android_9.0.0_r45 with Apache License 2.0 6 votes vote down vote up
/**
 * Base implementation handles ACTION_MULTIPLE KEYCODE_UNKNOWN by inserting
 * the event's text into the content.
 */
public boolean onKeyOther(View view, Editable content, KeyEvent event) {
    if (event.getAction() != KeyEvent.ACTION_MULTIPLE
            || event.getKeyCode() != KeyEvent.KEYCODE_UNKNOWN) {
        // Not something we are interested in.
        return false;
    }

    int selectionStart = Selection.getSelectionStart(content);
    int selectionEnd = Selection.getSelectionEnd(content);
    if (selectionEnd < selectionStart) {
        int temp = selectionEnd;
        selectionEnd = selectionStart;
        selectionStart = temp;
    }

    CharSequence text = event.getCharacters();
    if (text == null) {
        return false;
    }

    content.replace(selectionStart, selectionEnd, text);
    return true;
}
 
Example 4
Source File: BaseInputConnection.java    From android_9.0.0_r45 with Apache License 2.0 6 votes vote down vote up
/**
 * The default implementation uses TextUtils.getCapsMode to get the
 * cursor caps mode for the current selection position in the editable
 * text, unless in dummy mode in which case 0 is always returned.
 */
public int getCursorCapsMode(int reqModes) {
    if (mDummyMode) return 0;

    final Editable content = getEditable();
    if (content == null) return 0;

    int a = Selection.getSelectionStart(content);
    int b = Selection.getSelectionEnd(content);

    if (a > b) {
        int tmp = a;
        a = b;
        b = tmp;
    }

    return TextUtils.getCapsMode(content, a, reqModes);
}
 
Example 5
Source File: AdapterInputConnection.java    From android-chromium with BSD 2-Clause "Simplified" License 5 votes vote down vote up
/**
 * Sends selection update to the InputMethodManager unless we are currently in a batch edit or
 * if the exact same selection and composition update was sent already.
 */
private void updateSelectionIfRequired() {
    if (mNumNestedBatchEdits != 0) return;
    Editable editable = getEditable();
    int selectionStart = Selection.getSelectionStart(editable);
    int selectionEnd = Selection.getSelectionEnd(editable);
    int compositionStart = getComposingSpanStart(editable);
    int compositionEnd = getComposingSpanEnd(editable);
    // Avoid sending update if we sent an exact update already previously.
    if (mLastUpdateSelectionStart == selectionStart &&
            mLastUpdateSelectionEnd == selectionEnd &&
            mLastUpdateCompositionStart == compositionStart &&
            mLastUpdateCompositionEnd == compositionEnd) {
        return;
    }
    if (DEBUG) {
        Log.w(TAG, "updateSelectionIfRequired [" + selectionStart + " " + selectionEnd + "] ["
                + compositionStart + " " + compositionEnd + "]");
    }
    // updateSelection should be called every time the selection or composition changes
    // if it happens not within a batch edit, or at the end of each top level batch edit.
    getInputMethodManagerWrapper().updateSelection(mInternalView,
            selectionStart, selectionEnd, compositionStart, compositionEnd);
    mLastUpdateSelectionStart = selectionStart;
    mLastUpdateSelectionEnd = selectionEnd;
    mLastUpdateCompositionStart = compositionStart;
    mLastUpdateCompositionEnd = compositionEnd;
}
 
Example 6
Source File: AdapterInputConnection.java    From android-chromium with BSD 2-Clause "Simplified" License 5 votes vote down vote up
@VisibleForTesting
ImeState getImeStateForTesting() {
    Editable editable = getEditable();
    String text = editable.toString();
    int selectionStart = Selection.getSelectionStart(editable);
    int selectionEnd = Selection.getSelectionEnd(editable);
    int compositionStart = getComposingSpanStart(editable);
    int compositionEnd = getComposingSpanEnd(editable);
    return new ImeState(text, selectionStart, selectionEnd, compositionStart, compositionEnd);
}
 
Example 7
Source File: AdapterInputConnection.java    From android-chromium with BSD 2-Clause "Simplified" License 5 votes vote down vote up
/**
 * Sends selection update to the InputMethodManager unless we are currently in a batch edit or
 * if the exact same selection and composition update was sent already.
 */
private void updateSelectionIfRequired() {
    if (mNumNestedBatchEdits != 0) return;
    Editable editable = getEditable();
    int selectionStart = Selection.getSelectionStart(editable);
    int selectionEnd = Selection.getSelectionEnd(editable);
    int compositionStart = getComposingSpanStart(editable);
    int compositionEnd = getComposingSpanEnd(editable);
    // Avoid sending update if we sent an exact update already previously.
    if (mLastUpdateSelectionStart == selectionStart &&
            mLastUpdateSelectionEnd == selectionEnd &&
            mLastUpdateCompositionStart == compositionStart &&
            mLastUpdateCompositionEnd == compositionEnd) {
        return;
    }
    if (DEBUG) {
        Log.w(TAG, "updateSelectionIfRequired [" + selectionStart + " " + selectionEnd + "] ["
                + compositionStart + " " + compositionEnd + "]");
    }
    // updateSelection should be called every time the selection or composition changes
    // if it happens not within a batch edit, or at the end of each top level batch edit.
    getInputMethodManagerWrapper().updateSelection(mInternalView,
            selectionStart, selectionEnd, compositionStart, compositionEnd);
    mLastUpdateSelectionStart = selectionStart;
    mLastUpdateSelectionEnd = selectionEnd;
    mLastUpdateCompositionStart = compositionStart;
    mLastUpdateCompositionEnd = compositionEnd;
}
 
Example 8
Source File: JotaTextKeyListener.java    From JotaTextEditor with Apache License 2.0 5 votes vote down vote up
/**
 * Performs the action that happens when you press the DEL key in
 * a TextView.  If there is a selection, deletes the selection;
 * otherwise, DEL alone deletes the character before the cursor,
 * if any;
 * ALT+DEL deletes everything on the line the cursor is on.
 *
 * @return true if anything was deleted; false otherwise.
 */
public boolean forwardDelete(View view, Editable content, int keyCode,
                         KeyEvent event) {
    int selStart, selEnd;
    boolean result = true;

    {
        int a = Selection.getSelectionStart(content);
        int b = Selection.getSelectionEnd(content);

        selStart = Math.min(a, b);
        selEnd = Math.max(a, b);
    }

    if (selStart != selEnd) {
        content.delete(selStart, selEnd);
    } else {
        int to = TextUtils.getOffsetAfter(content, selEnd);

        if (to != selEnd) {
            content.delete(Math.min(to, selEnd), Math.max(to, selEnd));
        }
        else {
            result = false;
        }
    }

    if (result)
        adjustMetaAfterKeypress(content);

    return result;
}
 
Example 9
Source File: JotaTextKeyListener.java    From PowerFileExplorer with GNU General Public License v3.0 5 votes vote down vote up
/**
 * Performs the action that happens when you press the DEL key in
 * a TextView.  If there is a selection, deletes the selection;
 * otherwise, DEL alone deletes the character before the cursor,
 * if any;
 * ALT+DEL deletes everything on the line the cursor is on.
 *
 * @return true if anything was deleted; false otherwise.
 */
public boolean forwardDelete(View view, Editable content, int keyCode,
                         KeyEvent event) {
    int selStart, selEnd;
    boolean result = true;

    {
        int a = Selection.getSelectionStart(content);
        int b = Selection.getSelectionEnd(content);

        selStart = Math.min(a, b);
        selEnd = Math.max(a, b);
    }

    if (selStart != selEnd) {
        content.delete(selStart, selEnd);
    } else {
        int to = TextUtils.getOffsetAfter(content, selEnd);

        if (to != selEnd) {
            content.delete(Math.min(to, selEnd), Math.max(to, selEnd));
        }
        else {
            result = false;
        }
    }

    if (result)
        adjustMetaAfterKeypress(content);

    return result;
}
 
Example 10
Source File: AdapterInputConnection.java    From android-chromium with BSD 2-Clause "Simplified" License 5 votes vote down vote up
/**
 * @see BaseInputConnection#getExtractedText(android.view.inputmethod.ExtractedTextRequest,
 *                                           int)
 */
@Override
public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) {
    if (DEBUG) Log.w(TAG, "getExtractedText");
    ExtractedText et = new ExtractedText();
    Editable editable = getEditable();
    et.text = editable.toString();
    et.partialEndOffset = editable.length();
    et.selectionStart = Selection.getSelectionStart(editable);
    et.selectionEnd = Selection.getSelectionEnd(editable);
    et.flags = mSingleLine ? ExtractedText.FLAG_SINGLE_LINE : 0;
    return et;
}
 
Example 11
Source File: AdapterInputConnection.java    From android-chromium with BSD 2-Clause "Simplified" License 5 votes vote down vote up
/**
 * @see BaseInputConnection#deleteSurroundingText(int, int)
 */
@Override
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
    if (DEBUG) {
        Log.w(TAG, "deleteSurroundingText [" + beforeLength + " " + afterLength + "]");
    }
    Editable editable = getEditable();
    int availableBefore = Selection.getSelectionStart(editable);
    int availableAfter = editable.length() - Selection.getSelectionEnd(editable);
    beforeLength = Math.min(beforeLength, availableBefore);
    afterLength = Math.min(afterLength, availableAfter);
    super.deleteSurroundingText(beforeLength, afterLength);
    updateSelectionIfRequired();
    return mImeAdapter.deleteSurroundingText(beforeLength, afterLength);
}
 
Example 12
Source File: AdapterInputConnection.java    From android-chromium with BSD 2-Clause "Simplified" License 5 votes vote down vote up
/**
 * @see BaseInputConnection#deleteSurroundingText(int, int)
 */
@Override
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
    if (DEBUG) {
        Log.w(TAG, "deleteSurroundingText [" + beforeLength + " " + afterLength + "]");
    }
    Editable editable = getEditable();
    int availableBefore = Selection.getSelectionStart(editable);
    int availableAfter = editable.length() - Selection.getSelectionEnd(editable);
    beforeLength = Math.min(beforeLength, availableBefore);
    afterLength = Math.min(afterLength, availableAfter);
    super.deleteSurroundingText(beforeLength, afterLength);
    updateSelectionIfRequired();
    return mImeAdapter.deleteSurroundingText(beforeLength, afterLength);
}
 
Example 13
Source File: AdapterInputConnection.java    From android-chromium with BSD 2-Clause "Simplified" License 5 votes vote down vote up
/**
 * @see BaseInputConnection#getExtractedText(android.view.inputmethod.ExtractedTextRequest,
 *                                           int)
 */
@Override
public ExtractedText getExtractedText(ExtractedTextRequest request, int flags) {
    if (DEBUG) Log.w(TAG, "getExtractedText");
    ExtractedText et = new ExtractedText();
    Editable editable = getEditable();
    et.text = editable.toString();
    et.partialEndOffset = editable.length();
    et.selectionStart = Selection.getSelectionStart(editable);
    et.selectionEnd = Selection.getSelectionEnd(editable);
    et.flags = mSingleLine ? ExtractedText.FLAG_SINGLE_LINE : 0;
    return et;
}
 
Example 14
Source File: BaseInputConnection.java    From android_9.0.0_r45 with Apache License 2.0 5 votes vote down vote up
/**
 * The default implementation returns the given amount of text from the
 * current cursor position in the buffer.
 */
public CharSequence getTextBeforeCursor(int length, int flags) {
    final Editable content = getEditable();
    if (content == null) return null;

    int a = Selection.getSelectionStart(content);
    int b = Selection.getSelectionEnd(content);

    if (a > b) {
        int tmp = a;
        a = b;
        b = tmp;
    }

    if (a <= 0) {
        return "";
    }

    if (length > a) {
        length = a;
    }

    if ((flags&GET_TEXT_WITH_STYLES) != 0) {
        return content.subSequence(a - length, a);
    }
    return TextUtils.substring(content, a - length, a);
}
 
Example 15
Source File: BaseKeyListener.java    From android_9.0.0_r45 with Apache License 2.0 4 votes vote down vote up
private boolean deleteUntilWordBoundary(View view, Editable content, boolean isForwardDelete) {
    int currentCursorOffset = Selection.getSelectionStart(content);

    // If there is a selection, do nothing.
    if (currentCursorOffset != Selection.getSelectionEnd(content)) {
        return false;
    }

    // Early exit if there is no contents to delete.
    if ((!isForwardDelete && currentCursorOffset == 0) ||
        (isForwardDelete && currentCursorOffset == content.length())) {
        return false;
    }

    WordIterator wordIterator = null;
    if (view instanceof TextView) {
        wordIterator = ((TextView)view).getWordIterator();
    }

    if (wordIterator == null) {
        // Default locale is used for WordIterator since the appropriate locale is not clear
        // here.
        // TODO: Use appropriate locale for WordIterator.
        wordIterator = new WordIterator();
    }

    int deleteFrom;
    int deleteTo;

    if (isForwardDelete) {
        deleteFrom = currentCursorOffset;
        wordIterator.setCharSequence(content, deleteFrom, content.length());
        deleteTo = wordIterator.following(currentCursorOffset);
        if (deleteTo == BreakIterator.DONE) {
            deleteTo = content.length();
        }
    } else {
        deleteTo = currentCursorOffset;
        wordIterator.setCharSequence(content, 0, deleteTo);
        deleteFrom = wordIterator.preceding(currentCursorOffset);
        if (deleteFrom == BreakIterator.DONE) {
            deleteFrom = 0;
        }
    }
    content.delete(deleteFrom, deleteTo);
    return true;
}
 
Example 16
Source File: LongClickableLinkMovementMethod.java    From iBeebo with GNU General Public License v3.0 4 votes vote down vote up
private boolean action(int what, TextView widget, Spannable buffer) {
    Layout layout = widget.getLayout();

    int padding = widget.getTotalPaddingTop() + widget.getTotalPaddingBottom();
    int areatop = widget.getScrollY();
    int areabot = areatop + widget.getHeight() - padding;

    int linetop = layout.getLineForVertical(areatop);
    int linebot = layout.getLineForVertical(areabot);

    int first = layout.getLineStart(linetop);
    int last = layout.getLineEnd(linebot);

    MyURLSpan[] candidates = buffer.getSpans(first, last, MyURLSpan.class);

    int a = Selection.getSelectionStart(buffer);
    int b = Selection.getSelectionEnd(buffer);

    int selStart = Math.min(a, b);
    int selEnd = Math.max(a, b);

    if (selStart < 0) {
        if (buffer.getSpanStart(FROM_BELOW) >= 0) {
            selStart = selEnd = buffer.length();
        }
    }

    if (selStart > last) {
        selStart = selEnd = Integer.MAX_VALUE;
    }
    if (selEnd < first) {
        selStart = selEnd = -1;
    }

    switch (what) {
        case CLICK:
            if (selStart == selEnd) {
                return false;
            }

            MyURLSpan[] link = buffer.getSpans(selStart, selEnd, MyURLSpan.class);

            if (link.length != 1) {
                return false;
            }

            link[0].onClick(widget);
            break;

        case UP:
            int best_start = -1;
            int best_end = -1;

            for (MyURLSpan candidate1 : candidates) {
                int end = buffer.getSpanEnd(candidate1);

                if (end < selEnd || selStart == selEnd) {
                    if (end > best_end) {
                        best_start = buffer.getSpanStart(candidate1);
                        best_end = end;
                    }
                }
            }

            if (best_start >= 0) {
                Selection.setSelection(buffer, best_end, best_start);
                return true;
            }

            break;

        case DOWN:
            best_start = Integer.MAX_VALUE;
            best_end = Integer.MAX_VALUE;

            for (MyURLSpan candidate : candidates) {
                int start = buffer.getSpanStart(candidate);

                if (start > selStart || selStart == selEnd) {
                    if (start < best_start) {
                        best_start = start;
                        best_end = buffer.getSpanEnd(candidate);
                    }
                }
            }

            if (best_end < Integer.MAX_VALUE) {
                Selection.setSelection(buffer, best_start, best_end);
                return true;
            }

            break;
    }

    return false;
}
 
Example 17
Source File: JotaTextKeyListener.java    From JotaTextEditor with Apache License 2.0 4 votes vote down vote up
@Override
public boolean onKeyDown(View view, Editable content, int keyCode, KeyEvent event) {
    boolean result = super.onKeyDown(view, content, keyCode, event);

    // auto indent
    if ( sAutoIndent && keyCode == KeyEvent.KEYCODE_ENTER ){

        int a = Selection.getSelectionStart(content);
        int b = Selection.getSelectionEnd(content);
        if ( a == b ){

            // search head of previous line
            int prev = a-2;
            while( prev >=0 && content.charAt(prev)!='\n' ){
                prev--;
            }
            prev ++;
            int pos = prev;
            while(  content.charAt(pos)==' ' || content.charAt(pos)=='\t' || content.charAt(pos)=='\u3000'){
                pos++;
            }
            int len = pos-prev;
            if ( len > 0  ){
                char [] dest = new char[len];
                content.getChars(prev, pos, dest, 0);

                content.replace(a,b, new String(dest) );
                Selection.setSelection(content, a+len);
            }
        }
    }
    if ( Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB ){
        if (keyCode == KEYCODE_FORWARD_DEL ) {
            if ( (event.getMetaState() & 512) == 0 ){       // workaround for Galaxy Note
                forwardDelete(view, content, keyCode, event);
                return true;
            }
        }
    }
    return result;
}
 
Example 18
Source File: AdapterInputConnection.java    From android-chromium with BSD 2-Clause "Simplified" License 4 votes vote down vote up
/**
 * @see BaseInputConnection#sendKeyEvent(android.view.KeyEvent)
 */
@Override
public boolean sendKeyEvent(KeyEvent event) {
    if (DEBUG) {
        Log.w(TAG, "sendKeyEvent [" + event.getAction() + "] [" + event.getKeyCode() + "]");
    }
    // If this is a key-up, and backspace/del or if the key has a character representation,
    // need to update the underlying Editable (i.e. the local representation of the text
    // being edited).
    if (event.getAction() == KeyEvent.ACTION_UP) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_DEL) {
            deleteSurroundingText(1, 0);
            return true;
        } else if (event.getKeyCode() == KeyEvent.KEYCODE_FORWARD_DEL) {
            deleteSurroundingText(0, 1);
            return true;
        } else {
            int unicodeChar = event.getUnicodeChar();
            if (unicodeChar != 0) {
                Editable editable = getEditable();
                int selectionStart = Selection.getSelectionStart(editable);
                int selectionEnd = Selection.getSelectionEnd(editable);
                if (selectionStart > selectionEnd) {
                    int temp = selectionStart;
                    selectionStart = selectionEnd;
                    selectionEnd = temp;
                }
                editable.replace(selectionStart, selectionEnd,
                        Character.toString((char)unicodeChar));
            }
        }
    } else if (event.getAction() == KeyEvent.ACTION_DOWN) {
        // TODO(aurimas): remove this workaround when crbug.com/278584 is fixed.
        if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
            beginBatchEdit();
            finishComposingText();
            mImeAdapter.translateAndSendNativeEvents(event);
            endBatchEdit();
            return true;
        } else if (event.getKeyCode() == KeyEvent.KEYCODE_DEL) {
            return true;
        } else if (event.getKeyCode() == KeyEvent.KEYCODE_FORWARD_DEL) {
            return true;
        }
    }
    mImeAdapter.translateAndSendNativeEvents(event);
    return true;
}
 
Example 19
Source File: FormattedEditText.java    From FormatEditText with MIT License 4 votes vote down vote up
private void formatTextWhenDelete(final Editable editable, int start, int before) {
    mIsFormatted = true;
    final boolean filter = mFilterRestoreTextChangeEvent;
    super.removeTextChangedListener(mTextWatcher);
    InputFilter[] filters = editable.getFilters();
    editable.setFilters(EMPTY_FILTERS);
    int selectionStart, selectionEnd;
    if (!filter) {
        selectionStart = Selection.getSelectionStart(editable);
        selectionEnd = Selection.getSelectionEnd(editable);
        editable.setSpan(SELECTION_SPAN, selectionStart, selectionEnd, Spanned.SPAN_MARK_MARK);
    }
    if (mMode < MODE_MASK) {
        final boolean deletedLast = start >= editable.length();
        if (!deletedLast) {
            formatDefined(editable, start, true);
        } else {
            for (int i = start; i > 0; i--) {
                final char sub = editable.charAt(i - 1);
                final char place = findPlaceholder(i - 1);
                if (sub == place) {
                    editable.delete(i - 1, i);
                } else {
                    break;
                }
            }
        }
    } else {
        formatMask(editable, start, true);
    }
    if (!filter) {
        selectionStart = editable.getSpanStart(SELECTION_SPAN);
        selectionEnd = editable.getSpanEnd(SELECTION_SPAN);
        editable.removeSpan(SELECTION_SPAN);
        editable.setFilters(filters);
        Editable text = getText();
        Selection.setSelection(text, selectionStart, selectionEnd);
    } else {
        setFilters(filters);
    }
    mIsFormatted = false;
    super.addTextChangedListener(mTextWatcher);
}
 
Example 20
Source File: CountLinkMovementMethod.java    From timecat with Apache License 2.0 4 votes vote down vote up
private boolean action(int what, TextView widget, Spannable buffer) {
    Layout layout = widget.getLayout();

    int padding = widget.getTotalPaddingTop() + widget.getTotalPaddingBottom();
    int areatop = widget.getScrollY();
    int areabot = areatop + widget.getHeight() - padding;

    int linetop = layout.getLineForVertical(areatop);
    int linebot = layout.getLineForVertical(areabot);

    int first = layout.getLineStart(linetop);
    int last = layout.getLineEnd(linebot);

    ClickableSpan[] candidates = buffer.getSpans(first, last, ClickableSpan.class);

    int a = Selection.getSelectionStart(buffer);
    int b = Selection.getSelectionEnd(buffer);

    int selStart = Math.min(a, b);
    int selEnd = Math.max(a, b);

    if (selStart < 0) {
        if (buffer.getSpanStart(FROM_BELOW) >= 0) {
            selStart = selEnd = buffer.length();
        }
    }

    if (selStart > last) selStart = selEnd = Integer.MAX_VALUE;
    if (selEnd < first) selStart = selEnd = -1;

    switch (what) {
        case CLICK:
            if (selStart == selEnd) {
                return false;
            }

            ClickableSpan[] link = buffer.getSpans(selStart, selEnd, ClickableSpan.class);

            if (link.length != 1) return false;

            link[0].onClick(widget);
            break;

        case UP:
            int beststart, bestend;

            beststart = -1;
            bestend = -1;

            for (int i = 0; i < candidates.length; i++) {
                int end = buffer.getSpanEnd(candidates[i]);

                if (end < selEnd || selStart == selEnd) {
                    if (end > bestend) {
                        beststart = buffer.getSpanStart(candidates[i]);
                        bestend = end;
                    }
                }
            }

            if (beststart >= 0) {
                Selection.setSelection(buffer, bestend, beststart);
                return true;
            }

            break;

        case DOWN:
            beststart = Integer.MAX_VALUE;
            bestend = Integer.MAX_VALUE;

            for (int i = 0; i < candidates.length; i++) {
                int start = buffer.getSpanStart(candidates[i]);

                if (start > selStart || selStart == selEnd) {
                    if (start < beststart) {
                        beststart = start;
                        bestend = buffer.getSpanEnd(candidates[i]);
                    }
                }
            }

            if (bestend < Integer.MAX_VALUE) {
                Selection.setSelection(buffer, beststart, bestend);
                return true;
            }

            break;
    }

    return false;
}