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

Commit 03789e8d authored by Gilles Debunne's avatar Gilles Debunne
Browse files

Smart word detection in text selection. Manual merge in HC of 63569.

Selecting between words selects the spaces instead of the closest word, facilitating
paste insertion vs word replacement.

Pasting adds/removes space before and after if needed so that pasted text is not appended to
existing text.

Change-Id: Iffa0fb573d3535af72b639d05c5dc0721e80bda5
parent 8624e639
Loading
Loading
Loading
Loading
+51 −5
Original line number Diff line number Diff line
@@ -5875,7 +5875,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
     * Return true iff there is a selection inside this text view.
     */
    public boolean hasSelection() {
        return getSelectionStart() != getSelectionEnd();
        final int selectionStart = getSelectionStart();
        final int selectionEnd = getSelectionEnd();

        return selectionStart >= 0 && selectionStart != selectionEnd;
    }

    /**
@@ -7068,7 +7071,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            return false;
        }

        if (mText.length() > 0 && getSelectionStart() >= 0) {
        if (mText.length() > 0 && hasSelection()) {
            if (mText instanceof Editable && mInput != null) {
                return true;
            }
@@ -7082,7 +7085,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            return false;
        }

        if (mText.length() > 0 && getSelectionStart() >= 0) {
        if (mText.length() > 0 && hasSelection()) {
            return true;
        }

@@ -7203,6 +7206,49 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        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;
                    }
                }
            }

            // '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;
            }
        }

        long wordLimits = getWordLimitsAt(minOffset);
        if (wordLimits >= 0) {
            selectionStart = (int) (wordLimits >>> 32);