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

Commit cf1e925a authored by Gilles Debunne's avatar Gilles Debunne
Browse files

resolved conflicts for merge of ba04dbc6 to master

Change-Id: I175aa21ef01b98b0c3c46aea0b754d14984128b9
parents 2409cdb5 ba04dbc6
Loading
Loading
Loading
Loading
+80 −52
Original line number Diff line number Diff line
@@ -4364,6 +4364,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener

        switch (keyCode) {
            case KeyEvent.KEYCODE_ENTER:
                mEnterKeyIsDown = true;
                // If ALT modifier is held, then we always insert a
                // newline character.
                if ((event.getMetaState()&KeyEvent.META_ALT_ON) == 0) {
@@ -4396,6 +4397,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                break;
                
            case KeyEvent.KEYCODE_DPAD_CENTER:
                mDPadCenterIsDown = true;
                if (shouldAdvanceFocusOnEnter()) {
                    return 0;
                }
@@ -4490,6 +4492,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener

        switch (keyCode) {
            case KeyEvent.KEYCODE_DPAD_CENTER:
                mDPadCenterIsDown = false;
                /*
                 * If there is a click listener, just call through to
                 * super, which will invoke it.
@@ -4510,6 +4513,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                return super.onKeyUp(keyCode, event);
                
            case KeyEvent.KEYCODE_ENTER:
                mEnterKeyIsDown = false;
                if (mInputContentType != null
                        && mInputContentType.onEditorActionListener != null
                        && mInputContentType.enterDown) {
@@ -7288,9 +7292,21 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        }

        // Two ints packed in a long
        return packRangeInLong(start, end);
    }

    private static long packRangeInLong(int start, int end) {
        return (((long) start) << 32) | end;
    }

    private static int extractRangeStartFromLong(long range) {
        return (int) (range >>> 32);
    }

    private static int extractRangeEndFromLong(long range) {
        return (int) (range & 0x00000000FFFFFFFFL);
    }
    
    private void selectCurrentWord() {
        // In case selection mode is started after an orientation change or after a select all,
        // use the current selection instead of creating one
@@ -7298,67 +7314,31 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            return;
        }

        int selectionStart, selectionEnd;
        int minOffset, maxOffset;

        if (mDPadCenterIsDown || mEnterKeyIsDown) {
            minOffset = getSelectionStart();
            maxOffset = getSelectionEnd();
        } else {
            // selectionModifierCursorController is not null at that point
            SelectionModifierCursorController selectionModifierCursorController =
                ((SelectionModifierCursorController) mSelectionModifierCursorController);
        int minOffset = selectionModifierCursorController.getMinTouchOffset();
        int maxOffset = selectionModifierCursorController.getMaxTouchOffset();

        if (minOffset == maxOffset) {
            int offset = Math.max(0, Math.min(minOffset, mTransformed.length()));

            // Tolerance, number of charaters around tapped position
            final int range = 1;
            final int max = mTransformed.length() - 1;

            // 'Smart' word selection: detect position between words
            for (int i = -range; i <= range; i++) {
                int index = offset + i;
                if (index >= 0 && index <= max) {
                    if (Character.isSpaceChar(mTransformed.charAt(index))) {
                        // Select current space
                        selectionStart = index;
                        selectionEnd = selectionStart + 1;

                        // Extend selection to maximum space range
                        while (selectionStart > 0 &&
                                Character.isSpaceChar(mTransformed.charAt(selectionStart - 1))) {
                            selectionStart--;
                        }
                        while (selectionEnd < max &&
                                Character.isSpaceChar(mTransformed.charAt(selectionEnd))) {
                            selectionEnd++;
                        }

                        Selection.setSelection((Spannable) mText, selectionStart, selectionEnd);
                        return;
                    }
                }
            minOffset = selectionModifierCursorController.getMinTouchOffset();
            maxOffset = selectionModifierCursorController.getMaxTouchOffset();
        }

            // 'Smart' word selection: detect position at beginning or end of text.
            if (offset <= range) {
                Selection.setSelection((Spannable) mText, 0, 0);
                return;
            }
            if (offset >= (max - range)) {
                Selection.setSelection((Spannable) mText, max + 1, max + 1);
                return;
            }
        }
        int selectionStart, selectionEnd;

        long wordLimits = getWordLimitsAt(minOffset);
        if (wordLimits >= 0) {
            selectionStart = (int) (wordLimits >>> 32);
            selectionStart = extractRangeStartFromLong(wordLimits);
        } else {
            selectionStart = Math.max(minOffset - 5, 0);
        }

        wordLimits = getWordLimitsAt(maxOffset);
        if (wordLimits >= 0) {
            selectionEnd = (int) (wordLimits & 0x00000000FFFFFFFFL);
            selectionEnd = extractRangeEndFromLong(wordLimits);
        } else {
            selectionEnd = Math.min(maxOffset + 5, mText.length());
        }
@@ -7487,7 +7467,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener

        switch (id) {
            case ID_COPY_URL:

                URLSpan[] urls = ((Spanned) mText).getSpans(min, max, URLSpan.class);
                if (urls.length >= 1) {
                    ClipData clip = null;
@@ -7513,6 +7492,49 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        return false;
    }

    /**
     * Prepare text so that there are not zero or two spaces at beginning and end of region defined
     * by [min, max] when replacing this region by paste.
     */
    private long prepareSpacesAroundPaste(int min, int max, CharSequence paste) {
        // Paste adds/removes spaces before or after insertion as needed.
        if (Character.isSpaceChar(paste.charAt(0))) {
            if (min > 0 && Character.isSpaceChar(mTransformed.charAt(min - 1))) {
                // Two spaces at beginning of paste: remove one
                final int originalLength = mText.length();
                ((Editable) mText).replace(min - 1, min, "");
                // Due to filters, there is no garantee that exactly one character was
                // removed. Count instead.
                final int delta = mText.length() - originalLength;
                min += delta;
                max += delta;
            }
        } else {
            if (min > 0 && !Character.isSpaceChar(mTransformed.charAt(min - 1))) {
                // No space at beginning of paste: add one
                final int originalLength = mText.length();
                ((Editable) mText).replace(min, min, " ");
                // Taking possible filters into account as above.
                final int delta = mText.length() - originalLength;
                min += delta;
                max += delta;
            }
        }

        if (Character.isSpaceChar(paste.charAt(paste.length() - 1))) {
            if (max < mText.length() && Character.isSpaceChar(mTransformed.charAt(max))) {
                // Two spaces at end of paste: remove one
                ((Editable) mText).replace(max, max + 1, "");
            }
        } else {
            if (max < mText.length() && !Character.isSpaceChar(mTransformed.charAt(max))) {
                // No space at end of paste: add one
                ((Editable) mText).replace(max, max, " ");
            }
        }
        return packRangeInLong(min, max);
    }

    @Override
    public boolean performLongClick() {
        if (super.performLongClick()) {
@@ -7704,6 +7726,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                            CharSequence paste = clip.getItem(i).coerceToText(getContext());
                            if (paste != null) {
                                if (!didfirst) {
                                    long minMax = prepareSpacesAroundPaste(min, max, paste);
                                    min = extractRangeStartFromLong(minMax);
                                    max = extractRangeEndFromLong(minMax);
                                    Selection.setSelection((Spannable) mText, max);
                                    ((Editable) mText).replace(min, max, paste);
                                } else {
@@ -7714,7 +7739,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                        }
                        stopSelectionActionMode();
                    }

                    return true;

                case ID_CUT:
@@ -8329,6 +8353,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
    private CursorController        mSelectionModifierCursorController;
    private ActionMode              mSelectionActionMode;
    private int                     mLastTouchOffset = -1;
    // These are needed to desambiguate a long click. If the long click comes from ones of these, we
    // select from the current cursor position. Otherwise, select from long pressed position.
    private boolean                 mDPadCenterIsDown = false;
    private boolean                 mEnterKeyIsDown = false;
    // Created once and shared by different CursorController helper methods.
    // Only one cursor controller is active at any time which prevent race conditions.
    private static Rect             sCursorControllerTempRect = new Rect();