Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ac3e5990 authored by Yohei Yukawa's avatar Yohei Yukawa Committed by Android (Google) Code Review
Browse files

Merge "Introdude IC#deleteSurroundingTextInCodePoints()."

parents 8c2dd1f7 c89e22a6
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -43411,6 +43411,7 @@ package android.view.inputmethod {
    method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
    method public boolean commitText(java.lang.CharSequence, int);
    method public boolean deleteSurroundingText(int, int);
    method public boolean deleteSurroundingTextInCodePoints(int, int);
    method public boolean endBatchEdit();
    method public boolean finishComposingText();
    method public static int getComposingSpanEnd(android.text.Spannable);
@@ -43576,6 +43577,7 @@ package android.view.inputmethod {
    method public abstract boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
    method public abstract boolean commitText(java.lang.CharSequence, int);
    method public abstract boolean deleteSurroundingText(int, int);
    method public abstract boolean deleteSurroundingTextInCodePoints(int, int);
    method public abstract boolean endBatchEdit();
    method public abstract boolean finishComposingText();
    method public abstract int getCursorCapsMode(int);
@@ -43606,6 +43608,7 @@ package android.view.inputmethod {
    method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
    method public boolean commitText(java.lang.CharSequence, int);
    method public boolean deleteSurroundingText(int, int);
    method public boolean deleteSurroundingTextInCodePoints(int, int);
    method public boolean endBatchEdit();
    method public boolean finishComposingText();
    method public int getCursorCapsMode(int);
+3 −0
Original line number Diff line number Diff line
@@ -45807,6 +45807,7 @@ package android.view.inputmethod {
    method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
    method public boolean commitText(java.lang.CharSequence, int);
    method public boolean deleteSurroundingText(int, int);
    method public boolean deleteSurroundingTextInCodePoints(int, int);
    method public boolean endBatchEdit();
    method public boolean finishComposingText();
    method public static int getComposingSpanEnd(android.text.Spannable);
@@ -45972,6 +45973,7 @@ package android.view.inputmethod {
    method public abstract boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
    method public abstract boolean commitText(java.lang.CharSequence, int);
    method public abstract boolean deleteSurroundingText(int, int);
    method public abstract boolean deleteSurroundingTextInCodePoints(int, int);
    method public abstract boolean endBatchEdit();
    method public abstract boolean finishComposingText();
    method public abstract int getCursorCapsMode(int);
@@ -46002,6 +46004,7 @@ package android.view.inputmethod {
    method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
    method public boolean commitText(java.lang.CharSequence, int);
    method public boolean deleteSurroundingText(int, int);
    method public boolean deleteSurroundingTextInCodePoints(int, int);
    method public boolean endBatchEdit();
    method public boolean finishComposingText();
    method public int getCursorCapsMode(int);
+3 −0
Original line number Diff line number Diff line
@@ -43427,6 +43427,7 @@ package android.view.inputmethod {
    method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
    method public boolean commitText(java.lang.CharSequence, int);
    method public boolean deleteSurroundingText(int, int);
    method public boolean deleteSurroundingTextInCodePoints(int, int);
    method public boolean endBatchEdit();
    method public boolean finishComposingText();
    method public static int getComposingSpanEnd(android.text.Spannable);
@@ -43592,6 +43593,7 @@ package android.view.inputmethod {
    method public abstract boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
    method public abstract boolean commitText(java.lang.CharSequence, int);
    method public abstract boolean deleteSurroundingText(int, int);
    method public abstract boolean deleteSurroundingTextInCodePoints(int, int);
    method public abstract boolean endBatchEdit();
    method public abstract boolean finishComposingText();
    method public abstract int getCursorCapsMode(int);
@@ -43622,6 +43624,7 @@ package android.view.inputmethod {
    method public boolean commitCorrection(android.view.inputmethod.CorrectionInfo);
    method public boolean commitText(java.lang.CharSequence, int);
    method public boolean deleteSurroundingText(int, int);
    method public boolean deleteSurroundingTextInCodePoints(int, int);
    method public boolean endBatchEdit();
    method public boolean finishComposingText();
    method public int getCursorCapsMode(int);
+162 −1
Original line number Diff line number Diff line
@@ -229,7 +229,7 @@ public class BaseInputConnection implements InputConnection {
            b = tmp;
        }

        // ignore the composing text.
        // Ignore the composing text.
        int ca = getComposingSpanStart(content);
        int cb = getComposingSpanEnd(content);
        if (cb < ca) {
@@ -265,6 +265,167 @@ public class BaseInputConnection implements InputConnection {
        return true;
    }

    private static int INVALID_INDEX = -1;
    private static int findIndexBackward(final CharSequence cs, final int from,
            final int numCodePoints) {
        int currentIndex = from;
        boolean waitingHighSurrogate = false;
        final int N = cs.length();
        if (currentIndex < 0 || N < currentIndex) {
            return INVALID_INDEX;  // The starting point is out of range.
        }
        if (numCodePoints < 0) {
            return INVALID_INDEX;  // Basically this should not happen.
        }
        int remainingCodePoints = numCodePoints;
        while (true) {
            if (remainingCodePoints == 0) {
                return currentIndex;  // Reached to the requested length in code points.
            }

            --currentIndex;
            if (currentIndex < 0) {
                if (waitingHighSurrogate) {
                    return INVALID_INDEX;  // An invalid surrogate pair is found.
                }
                return 0;  // Reached to the beginning of the text w/o any invalid surrogate pair.
            }
            final char c = cs.charAt(currentIndex);
            if (waitingHighSurrogate) {
                if (!java.lang.Character.isHighSurrogate(c)) {
                    return INVALID_INDEX;  // An invalid surrogate pair is found.
                }
                waitingHighSurrogate = false;
                --remainingCodePoints;
                continue;
            }
            if (!java.lang.Character.isSurrogate(c)) {
                --remainingCodePoints;
                continue;
            }
            if (java.lang.Character.isHighSurrogate(c)) {
                return INVALID_INDEX;  // A invalid surrogate pair is found.
            }
            waitingHighSurrogate = true;
        }
    }

    private static int findIndexForward(final CharSequence cs, final int from,
            final int numCodePoints) {
        int currentIndex = from;
        boolean waitingLowSurrogate = false;
        final int N = cs.length();
        if (currentIndex < 0 || N < currentIndex) {
            return INVALID_INDEX;  // The starting point is out of range.
        }
        if (numCodePoints < 0) {
            return INVALID_INDEX;  // Basically this should not happen.
        }
        int remainingCodePoints = numCodePoints;

        while (true) {
            if (remainingCodePoints == 0) {
                return currentIndex;  // Reached to the requested length in code points.
            }

            if (currentIndex >= N) {
                if (waitingLowSurrogate) {
                    return INVALID_INDEX;  // An invalid surrogate pair is found.
                }
                return N;  // Reached to the end of the text w/o any invalid surrogate pair.
            }
            final char c = cs.charAt(currentIndex);
            if (waitingLowSurrogate) {
                if (!java.lang.Character.isLowSurrogate(c)) {
                    return INVALID_INDEX;  // An invalid surrogate pair is found.
                }
                --remainingCodePoints;
                waitingLowSurrogate = false;
                ++currentIndex;
                continue;
            }
            if (!java.lang.Character.isSurrogate(c)) {
                --remainingCodePoints;
                ++currentIndex;
                continue;
            }
            if (java.lang.Character.isLowSurrogate(c)) {
                return INVALID_INDEX;  // A invalid surrogate pair is found.
            }
            waitingLowSurrogate = true;
            ++currentIndex;
        }
    }

    /**
     * The default implementation performs the deletion around the current selection position of the
     * editable text.
     * @param beforeLength The number of characters before the cursor to be deleted, in code points.
     *        If this is greater than the number of existing characters between the beginning of the
     *        text and the cursor, then this method does not fail but deletes all the characters in
     *        that range.
     * @param afterLength The number of characters after the cursor to be deleted, in code points.
     *        If this is greater than the number of existing characters between the cursor and
     *        the end of the text, then this method does not fail but deletes all the characters in
     *        that range.
     */
    public boolean deleteSurroundingTextInCodePoints(int beforeLength, int afterLength) {
        if (DEBUG) Log.v(TAG, "deleteSurroundingText " + beforeLength
                + " / " + afterLength);
        final Editable content = getEditable();
        if (content == null) return false;

        beginBatchEdit();

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

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

        // Ignore the composing text.
        int ca = getComposingSpanStart(content);
        int cb = getComposingSpanEnd(content);
        if (cb < ca) {
            int tmp = ca;
            ca = cb;
            cb = tmp;
        }
        if (ca != -1 && cb != -1) {
            if (ca < a) a = ca;
            if (cb > b) b = cb;
        }

        if (a >= 0 && b >= 0) {
            final int start = findIndexBackward(content, a, Math.max(beforeLength, 0));
            if (start != INVALID_INDEX) {
                final int end = findIndexForward(content, b, Math.max(afterLength, 0));
                if (end != INVALID_INDEX) {
                    final int numDeleteBefore = a - start;
                    if (numDeleteBefore > 0) {
                        content.delete(start, a);
                    }
                    final int numDeleteAfter = end - b;
                    if (numDeleteAfter > 0) {
                        content.delete(b - numDeleteBefore, end - numDeleteBefore);
                    }
                }
            }
            // NOTE: You may think we should return false here if start and/or end is INVALID_INDEX,
            // but the truth is that IInputConnectionWrapper running in the middle of IPC calls
            // always returns true to the IME without waiting for the completion of this method as
            // IInputConnectionWrapper#isAtive() returns true.  This is actually why some methods
            // including this method look like asynchronous calls from the IME.
        }

        endBatchEdit();

        return true;
    }

    /**
     * The default implementation removes the composing state from the
     * current editable text.  In addition, only if dummy mode, a key event is
+27 −0
Original line number Diff line number Diff line
@@ -347,6 +347,33 @@ public interface InputConnection {
     */
    public boolean deleteSurroundingText(int beforeLength, int afterLength);

    /**
     * A variant of {@link #deleteSurroundingText(int, int)}. Major differences are:
     *
     * <ul>
     *     <li>The lengths are supplied in code points, not in Java chars or in glyphs.</>
     *     <li>This method does nothing if there are one or more invalid surrogate pairs in the
     *     requested range.</li>
     * </ul>
     *
     * <p><strong>Editor authors:</strong> In addition to the requirement in
     * {@link #deleteSurroundingText(int, int)}, make sure to do nothing when one ore more invalid
     * surrogate pairs are found in the requested range.</p>
     *
     * @see #deleteSurroundingText(int, int)
     *
     * @param beforeLength The number of characters before the cursor to be deleted, in code points.
     *        If this is greater than the number of existing characters between the beginning of the
     *        text and the cursor, then this method does not fail but deletes all the characters in
     *        that range.
     * @param afterLength The number of characters after the cursor to be deleted, in code points.
     *        If this is greater than the number of existing characters between the cursor and
     *        the end of the text, then this method does not fail but deletes all the characters in
     *        that range.
     * @return true on success, false if the input connection is no longer valid.
     */
    public boolean deleteSurroundingTextInCodePoints(int beforeLength, int afterLength);

    /**
     * Replace the currently composing text with the given text, and
     * set the new cursor position. Any composing text set previously
Loading