19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.text; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkeyimport java.text.BreakIterator; 20e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Utility class for manipulating cursors and selections in CharSequences. 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A cursor is a selection where the start and end are at the same offset. 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class Selection { 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Selection() { /* cannot be instantiated */ } 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Retrieving the selection 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the offset of the selection anchor or cursor, or -1 if 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * there is no selection or cursor. 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int getSelectionStart(CharSequence text) { 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (text instanceof Spanned) 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ((Spanned) text).getSpanStart(SELECTION_START); 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 43e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the offset of the selection edge or cursor, or -1 if 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * there is no selection or cursor. 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int getSelectionEnd(CharSequence text) { 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (text instanceof Spanned) 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ((Spanned) text).getSpanStart(SELECTION_END); 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Setting the selection 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // private static int pin(int value, int min, int max) { 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // return value < min ? 0 : (value > max ? max : value); 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // } 62e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Set the selection anchor to <code>start</code> and the selection edge 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to <code>stop</code>. 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void setSelection(Spannable text, int start, int stop) { 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // int len = text.length(); 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // start = pin(start, 0, len); XXX remove unless we really need it 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // stop = pin(stop, 0, len); 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ostart = getSelectionStart(text); 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int oend = getSelectionEnd(text); 74e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ostart != start || oend != stop) { 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.setSpan(SELECTION_START, start, start, 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spanned.SPAN_POINT_POINT|Spanned.SPAN_INTERMEDIATE); 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.setSpan(SELECTION_END, stop, stop, 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spanned.SPAN_POINT_POINT); 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Move the cursor to offset <code>index</code>. 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final void setSelection(Spannable text, int index) { 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSelection(text, index, index); 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Select the entire text. 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final void selectAll(Spannable text) { 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSelection(text, 0, text.length()); 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Move the selection edge to offset <code>index</code>. 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final void extendSelection(Spannable text, int index) { 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (text.getSpanStart(SELECTION_END) != index) 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.setSpan(SELECTION_END, index, index, Spanned.SPAN_POINT_POINT); 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Remove the selection or cursor, if any, from the text. 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final void removeSelection(Spannable text) { 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.removeSpan(SELECTION_START); 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project text.removeSpan(SELECTION_END); 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Moving the selection within the layout 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Move the cursor to the buffer offset physically above the current 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * offset, or return false if the cursor is already on the top line. 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static boolean moveUp(Spannable text, Layout layout) { 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int start = getSelectionStart(text); 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int end = getSelectionEnd(text); 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (start != end) { 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int min = Math.min(start, end); 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int max = Math.max(start, end); 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSelection(text, min); 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (min == 0 && max == text.length()) { 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int line = layout.getLineForOffset(end); 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (line > 0) { 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int move; 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (layout.getParagraphDirection(line) == 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project layout.getParagraphDirection(line - 1)) { 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float h = layout.getPrimaryHorizontal(end); 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project move = layout.getOffsetForHorizontal(line - 1, h); 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project move = layout.getLineStart(line - 1); 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSelection(text, move); 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Move the cursor to the buffer offset physically below the current 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * offset, or return false if the cursor is already on the bottom line. 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static boolean moveDown(Spannable text, Layout layout) { 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int start = getSelectionStart(text); 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int end = getSelectionEnd(text); 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (start != end) { 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int min = Math.min(start, end); 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int max = Math.max(start, end); 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSelection(text, max); 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (min == 0 && max == text.length()) { 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int line = layout.getLineForOffset(end); 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (line < layout.getLineCount() - 1) { 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int move; 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (layout.getParagraphDirection(line) == 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project layout.getParagraphDirection(line + 1)) { 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float h = layout.getPrimaryHorizontal(end); 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project move = layout.getOffsetForHorizontal(line + 1, h); 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project move = layout.getLineStart(line + 1); 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSelection(text, move); 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Move the cursor to the buffer offset physically to the left of 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the current offset, or return false if the cursor is already 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * at the left edge of the line and there is not another line to move it to. 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static boolean moveLeft(Spannable text, Layout layout) { 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int start = getSelectionStart(text); 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int end = getSelectionEnd(text); 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (start != end) { 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSelection(text, chooseHorizontal(layout, -1, start, end)); 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int to = layout.getOffsetToLeftOf(end); 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (to != end) { 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSelection(text, to); 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Move the cursor to the buffer offset physically to the right of 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the current offset, or return false if the cursor is already at 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * at the right edge of the line and there is not another line 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to move it to. 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static boolean moveRight(Spannable text, Layout layout) { 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int start = getSelectionStart(text); 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int end = getSelectionEnd(text); 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (start != end) { 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSelection(text, chooseHorizontal(layout, 1, start, end)); 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int to = layout.getOffsetToRightOf(end); 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (to != end) { 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSelection(text, to); 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Move the selection end to the buffer offset physically above 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the current selection end. 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static boolean extendUp(Spannable text, Layout layout) { 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int end = getSelectionEnd(text); 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int line = layout.getLineForOffset(end); 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (line > 0) { 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int move; 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (layout.getParagraphDirection(line) == 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project layout.getParagraphDirection(line - 1)) { 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float h = layout.getPrimaryHorizontal(end); 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project move = layout.getOffsetForHorizontal(line - 1, h); 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project move = layout.getLineStart(line - 1); 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project extendSelection(text, move); 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (end != 0) { 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project extendSelection(text, 0); 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Move the selection end to the buffer offset physically below 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the current selection end. 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static boolean extendDown(Spannable text, Layout layout) { 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int end = getSelectionEnd(text); 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int line = layout.getLineForOffset(end); 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (line < layout.getLineCount() - 1) { 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int move; 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (layout.getParagraphDirection(line) == 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project layout.getParagraphDirection(line + 1)) { 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float h = layout.getPrimaryHorizontal(end); 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project move = layout.getOffsetForHorizontal(line + 1, h); 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project move = layout.getLineStart(line + 1); 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project extendSelection(text, move); 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (end != text.length()) { 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project extendSelection(text, text.length()); 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Move the selection end to the buffer offset physically to the left of 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the current selection end. 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static boolean extendLeft(Spannable text, Layout layout) { 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int end = getSelectionEnd(text); 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int to = layout.getOffsetToLeftOf(end); 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (to != end) { 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project extendSelection(text, to); 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Move the selection end to the buffer offset physically to the right of 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the current selection end. 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static boolean extendRight(Spannable text, Layout layout) { 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int end = getSelectionEnd(text); 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int to = layout.getOffsetToRightOf(end); 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (to != end) { 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project extendSelection(text, to); 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static boolean extendToLeftEdge(Spannable text, Layout layout) { 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int where = findEdge(text, layout, -1); 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project extendSelection(text, where); 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static boolean extendToRightEdge(Spannable text, Layout layout) { 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int where = findEdge(text, layout, 1); 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project extendSelection(text, where); 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static boolean moveToLeftEdge(Spannable text, Layout layout) { 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int where = findEdge(text, layout, -1); 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSelection(text, where); 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static boolean moveToRightEdge(Spannable text, Layout layout) { 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int where = findEdge(text, layout, 1); 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSelection(text, where); 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 362e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey /** {@hide} */ 363e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey public static interface PositionIterator { 364e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey public static final int DONE = BreakIterator.DONE; 365e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey 366e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey public int preceding(int position); 367e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey public int following(int position); 368e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey } 369e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey 370e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey /** {@hide} */ 371e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey public static boolean moveToPreceding( 372e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey Spannable text, PositionIterator iter, boolean extendSelection) { 373e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey final int offset = iter.preceding(getSelectionEnd(text)); 374e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey if (offset != PositionIterator.DONE) { 375e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey if (extendSelection) { 376e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey extendSelection(text, offset); 377e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey } else { 378e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey setSelection(text, offset); 379e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey } 380e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey } 381e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey return true; 382e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey } 383e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey 384e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey /** {@hide} */ 385e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey public static boolean moveToFollowing( 386e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey Spannable text, PositionIterator iter, boolean extendSelection) { 387e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey final int offset = iter.following(getSelectionEnd(text)); 388e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey if (offset != PositionIterator.DONE) { 389e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey if (extendSelection) { 390e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey extendSelection(text, offset); 391e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey } else { 392e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey setSelection(text, offset); 393e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey } 394e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey } 395e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey return true; 396e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey } 397e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static int findEdge(Spannable text, Layout layout, int dir) { 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int pt = getSelectionEnd(text); 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int line = layout.getLineForOffset(pt); 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int pdir = layout.getParagraphDirection(line); 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dir * pdir < 0) { 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return layout.getLineStart(line); 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int end = layout.getLineEnd(line); 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (line == layout.getLineCount() - 1) 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return end; 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return end - 1; 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static int chooseHorizontal(Layout layout, int direction, 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int off1, int off2) { 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int line1 = layout.getLineForOffset(off1); 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int line2 = layout.getLineForOffset(off2); 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (line1 == line2) { 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // same line, so it goes by pure physical direction 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float h1 = layout.getPrimaryHorizontal(off1); 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float h2 = layout.getPrimaryHorizontal(off2); 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (direction < 0) { 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // to left 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (h1 < h2) 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return off1; 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return off2; 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // to right 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (h1 > h2) 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return off1; 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return off2; 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // different line, so which line is "left" and which is "right" 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // depends upon the directionality of the text 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This only checks at one end, but it's not clear what the 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // right thing to do is if the ends don't agree. Even if it 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // is wrong it should still not be too bad. 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int line = layout.getLineForOffset(off1); 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int textdir = layout.getParagraphDirection(line); 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (textdir == direction) 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return Math.max(off1, off2); 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return Math.min(off1, off2); 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4582d0e87b64402459d89adfd004083a748f81a0391Gilles Debunne private static final class START implements NoCopySpan { } 4592d0e87b64402459d89adfd004083a748f81a0391Gilles Debunne private static final class END implements NoCopySpan { } 460e982dfc1bae36620f67371efc7b0a0f8adc9450dJeff Sharkey 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Public constants 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final Object SELECTION_START = new START(); 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final Object SELECTION_END = new END(); 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 468