SpannableStringBuilder.java revision bc6862300fe5675addfe4ed5d0c7c345aad463aa
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 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Canvas; 20f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Feltimport android.graphics.Paint; 216435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne 226435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunneimport com.android.internal.util.ArrayUtils; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.reflect.Array; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This is the class for text whose content and markup can both be changed. 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 296435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunnepublic class SpannableStringBuilder implements CharSequence, GetChars, Spannable, Editable, 306435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne Appendable, GraphicsOperations { 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a new SpannableStringBuilder with empty contents 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannableStringBuilder() { 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(""); 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a new SpannableStringBuilder containing a copy of the 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * specified text, including its spans if any. 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannableStringBuilder(CharSequence text) { 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(text, 0, text.length()); 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a new SpannableStringBuilder containing a copy of the 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * specified slice of the specified text, including its spans if any. 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannableStringBuilder(CharSequence text, int start, int end) { 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int srclen = end - start; 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = ArrayUtils.idealCharArraySize(srclen + 1); 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mText = new char[len]; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGapStart = srclen; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGapLength = len - srclen; 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextUtils.getChars(text, start, end, mText, 0); 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanCount = 0; 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int alloc = ArrayUtils.idealIntArraySize(0); 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpans = new Object[alloc]; 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanStarts = new int[alloc]; 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanEnds = new int[alloc]; 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanFlags = new int[alloc]; 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (text instanceof Spanned) { 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spanned sp = (Spanned) text; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] spans = sp.getSpans(start, end, Object.class); 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < spans.length; i++) { 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spans[i] instanceof NoCopySpan) { 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int st = sp.getSpanStart(spans[i]) - start; 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int en = sp.getSpanEnd(spans[i]) - start; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fl = sp.getSpanFlags(spans[i]); 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (st < 0) 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project st = 0; 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (st > end - start) 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project st = end - start; 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (en < 0) 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project en = 0; 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (en > end - start) 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project en = end - start; 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSpan(spans[i], st, en, fl); 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static SpannableStringBuilder valueOf(CharSequence source) { 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (source instanceof SpannableStringBuilder) { 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (SpannableStringBuilder) source; 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new SpannableStringBuilder(source); 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the char at the specified offset within the buffer. 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public char charAt(int where) { 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = length(); 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (where < 0) { 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IndexOutOfBoundsException("charAt: " + where + " < 0"); 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (where >= len) { 1116435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne throw new IndexOutOfBoundsException("charAt: " + where + " >= length " + len); 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (where >= mGapStart) 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mText[where + mGapLength]; 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mText[where]; 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the number of chars in the buffer. 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int length() { 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mText.length - mGapLength; 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void resizeFor(int size) { 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int newlen = ArrayUtils.idealCharArraySize(size + 1); 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char[] newtext = new char[newlen]; 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int after = mText.length - (mGapStart + mGapLength); 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mText, 0, newtext, 0, mGapStart); 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mText, mText.length - after, 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newtext, newlen - after, after); 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < mSpanCount; i++) { 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSpanStarts[i] > mGapStart) 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanStarts[i] += newlen - mText.length; 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSpanEnds[i] > mGapStart) 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanEnds[i] += newlen - mText.length; 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int oldlen = mText.length; 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mText = newtext; 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGapLength += mText.length - oldlen; 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mGapLength < 1) 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new Exception("mGapLength < 1").printStackTrace(); 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void moveGapTo(int where) { 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (where == mGapStart) 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 156bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne boolean atend = (where == length()); 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (where < mGapStart) { 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int overlap = mGapStart - where; 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mText, where, 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mText, mGapStart + mGapLength - overlap, overlap); 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else /* where > mGapStart */ { 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int overlap = where - mGapStart; 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mText, where + mGapLength - overlap, 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mText, mGapStart, overlap); 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // XXX be more clever 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < mSpanCount; i++) { 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int start = mSpanStarts[i]; 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int end = mSpanEnds[i]; 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (start > mGapStart) 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start -= mGapLength; 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (start > where) 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start += mGapLength; 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else if (start == where) { 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int flag = (mSpanFlags[i] & START_MASK) >> START_SHIFT; 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 182bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne if (flag == POINT || (atend && flag == PARAGRAPH)) 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start += mGapLength; 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end > mGapStart) 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end -= mGapLength; 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end > where) 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end += mGapLength; 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else if (end == where) { 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int flag = (mSpanFlags[i] & END_MASK); 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 193bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne if (flag == POINT || (atend && flag == PARAGRAPH)) 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end += mGapLength; 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanStarts[i] = start; 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanEnds[i] = end; 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGapStart = where; 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannableStringBuilder insert(int where, CharSequence tb, int start, int end) { 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return replace(where, where, tb, start, end); 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannableStringBuilder insert(int where, CharSequence tb) { 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return replace(where, where, tb, 0, tb.length()); 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannableStringBuilder delete(int start, int end) { 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SpannableStringBuilder ret = replace(start, end, "", 0, 0); 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mGapLength > 2 * length()) 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project resizeFor(length()); 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret; // == this 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void clear() { 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project replace(0, length(), "", 0, 0); 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void clearSpans() { 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = mSpanCount - 1; i >= 0; i--) { 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object what = mSpans[i]; 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ostart = mSpanStarts[i]; 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int oend = mSpanEnds[i]; 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ostart > mGapStart) 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ostart -= mGapLength; 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (oend > mGapStart) 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project oend -= mGapLength; 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanCount = i; 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpans[i] = null; 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sendSpanRemoved(what, ostart, oend); 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannableStringBuilder append(CharSequence text) { 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int length = length(); 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return replace(length, length, text, 0, text.length()); 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannableStringBuilder append(CharSequence text, int start, int end) { 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int length = length(); 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return replace(length, length, text, start, end); 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannableStringBuilder append(char text) { 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return append(String.valueOf(text)); 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 265b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne private void change(int start, int end, CharSequence tb, int tbstart, int tbend) { 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkRange("replace", start, end); 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = mSpanCount - 1; i >= 0; i--) { 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((mSpanFlags[i] & SPAN_PARAGRAPH) == SPAN_PARAGRAPH) { 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int st = mSpanStarts[i]; 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (st > mGapStart) 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project st -= mGapLength; 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int en = mSpanEnds[i]; 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (en > mGapStart) 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project en -= mGapLength; 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ost = st; 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int oen = en; 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int clen = length(); 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (st > start && st <= end) { 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (st = end; st < clen; st++) 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (st > end && charAt(st - 1) == '\n') 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (en > start && en <= end) { 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (en = end; en < clen; en++) 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (en > end && charAt(en - 1) == '\n') 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (st != ost || en != oen) 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSpan(mSpans[i], st, en, mSpanFlags[i]); 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project moveGapTo(end); 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 301312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne // Can be negative 302312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne final int nbNewChars = (tbend - tbstart) - (end - start); 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 304312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne if (nbNewChars >= mGapLength) { 305312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne resizeFor(mText.length + nbNewChars - mGapLength); 306312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne } 307312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne 308312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne mGapStart += nbNewChars; 309312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne mGapLength -= nbNewChars; 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mGapLength < 1) 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new Exception("mGapLength < 1").printStackTrace(); 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextUtils.getChars(tb, tbstart, tbend, mText, start); 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (tb instanceof Spanned) { 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spanned sp = (Spanned) tb; 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] spans = sp.getSpans(tbstart, tbend, Object.class); 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < spans.length; i++) { 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int st = sp.getSpanStart(spans[i]); 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int en = sp.getSpanEnd(spans[i]); 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (st < tbstart) 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project st = tbstart; 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (en > tbend) 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project en = tbend; 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (getSpanStart(spans[i]) < 0) { 330b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne setSpan(false, spans[i], 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project st - tbstart + start, 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project en - tbstart + start, 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp.getSpanFlags(spans[i])); 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 338b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne if (end > start) { 339b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne // no need for span fixup on pure insertion 340b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne boolean atEnd = (mGapStart + mGapLength == mText.length); 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 342b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne for (int i = mSpanCount - 1; i >= 0; i--) { 343b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne if (mSpanStarts[i] >= start && 344b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne mSpanStarts[i] < mGapStart + mGapLength) { 345b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne int flag = (mSpanFlags[i] & START_MASK) >> START_SHIFT; 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 347b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne if (flag == POINT || (flag == PARAGRAPH && atEnd)) 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanStarts[i] = mGapStart + mGapLength; 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanStarts[i] = start; 351b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne } 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 353b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne if (mSpanEnds[i] >= start && 354b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne mSpanEnds[i] < mGapStart + mGapLength) { 355b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne int flag = (mSpanFlags[i] & END_MASK); 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 357b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne if (flag == POINT || (flag == PARAGRAPH && atEnd)) 358b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne mSpanEnds[i] = mGapStart + mGapLength; 359b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne else 360b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne mSpanEnds[i] = start; 361b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne } 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 363b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne // remove 0-length SPAN_EXCLUSIVE_EXCLUSIVE 364b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne if (mSpanEnds[i] < mSpanStarts[i]) { 365b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne removeSpan(i); 366b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne } 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 37175beb336f4b164c3bed5d4b91f0b9c6ea49a3437Gilles Debunne private void removeSpan(int i) { 3726435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne Object object = mSpans[i]; 3736435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne 3746435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne int start = mSpanStarts[i]; 3756435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne int end = mSpanEnds[i]; 3766435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne 3776435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne if (start > mGapStart) start -= mGapLength; 3786435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne if (end > mGapStart) end -= mGapLength; 3796435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne 3806435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne int count = mSpanCount - (i + 1); 3816435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne System.arraycopy(mSpans, i + 1, mSpans, i, count); 3826435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne System.arraycopy(mSpanStarts, i + 1, mSpanStarts, i, count); 3836435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne System.arraycopy(mSpanEnds, i + 1, mSpanEnds, i, count); 3846435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne System.arraycopy(mSpanFlags, i + 1, mSpanFlags, i, count); 38575beb336f4b164c3bed5d4b91f0b9c6ea49a3437Gilles Debunne 38675beb336f4b164c3bed5d4b91f0b9c6ea49a3437Gilles Debunne mSpanCount--; 3876435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne 3886435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne mSpans[mSpanCount] = null; 3896435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne 3906435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne sendSpanRemoved(object, start, end); 39175beb336f4b164c3bed5d4b91f0b9c6ea49a3437Gilles Debunne } 39275beb336f4b164c3bed5d4b91f0b9c6ea49a3437Gilles Debunne 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannableStringBuilder replace(int start, int end, CharSequence tb) { 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return replace(start, end, tb, 0, tb.length()); 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannableStringBuilder replace(final int start, final int end, 400bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne CharSequence tb, int tbstart, int tbend) { 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int filtercount = mFilters.length; 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < filtercount; i++) { 403b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne CharSequence repl = mFilters[i].filter(tb, tbstart, tbend, this, start, end); 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (repl != null) { 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tb = repl; 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tbstart = 0; 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tbend = repl.length(); 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 412b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne final int origLen = end - start; 413b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne final int newLen = tbend - tbstart; 414b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne 415b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne if (origLen == 0 && newLen == 0) { 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return this; 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 419b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne TextWatcher[] textWatchers = getSpans(start, start + origLen, TextWatcher.class); 420b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne sendBeforeTextChanged(textWatchers, start, origLen, newLen); 421b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne 422bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne if (origLen == 0 || newLen == 0) { 423bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne change(start, end, tb, tbstart, tbend); 424bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne } else { 425bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne int selstart = Selection.getSelectionStart(this); 426bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne int selend = Selection.getSelectionEnd(this); 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 428bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne // XXX just make the span fixups in change() do the right thing 429bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne // instead of this madness! 430bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne 431bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne checkRange("replace", start, end); 432bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne moveGapTo(end); 433bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne 434bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne if (mGapLength < 2) 435bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne resizeFor(length() + 1); 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 437bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne for (int i = mSpanCount - 1; i >= 0; i--) { 438bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne if (mSpanStarts[i] == mGapStart) 439bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne mSpanStarts[i]++; 440bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne 441bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne if (mSpanEnds[i] == mGapStart) 442bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne mSpanEnds[i]++; 443bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne } 444bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne 445bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne mText[mGapStart] = ' '; 446bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne mGapStart++; 447bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne mGapLength--; 448bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne 449bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne if (mGapLength < 1) { 450bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne new Exception("mGapLength < 1").printStackTrace(); 451bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne } 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 453bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne change(start + 1, start + 1, tb, tbstart, tbend); 454bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne change(start, start + 1, "", 0, 0); 455bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne change(start + newLen, start + newLen + origLen, "", 0, 0); 456bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne 457bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne /* 458bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne * Special case to keep the cursor in the same position 459bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne * if it was somewhere in the middle of the replaced region. 460bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne * If it was at the start or the end or crossing the whole 461bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne * replacement, it should already be where it belongs. 462bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne * TODO: Is there some more general mechanism that could 463bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne * accomplish this? 464bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne */ 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (selstart > start && selstart < end) { 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long off = selstart - start; 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 468bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne off = off * newLen / (end - start); 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project selstart = (int) off + start; 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSpan(false, Selection.SELECTION_START, selstart, selstart, 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spanned.SPAN_POINT_POINT); 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (selend > start && selend < end) { 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long off = selend - start; 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 477bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne off = off * newLen / (end - start); 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project selend = (int) off + start; 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4806435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne setSpan(false, Selection.SELECTION_END, selend, selend, Spanned.SPAN_POINT_POINT); 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4836435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne 484b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne sendTextChanged(textWatchers, start, origLen, newLen); 485b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne sendAfterTextChanged(textWatchers); 486b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return this; 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Mark the specified range of text with the specified object. 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The flags determine how the span will behave when text is 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * inserted at the start or end of the span's range. 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setSpan(Object what, int start, int end, int flags) { 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSpan(true, what, start, end, flags); 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4996435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne private void setSpan(boolean send, Object what, int start, int end, int flags) { 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int nstart = start; 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int nend = end; 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkRange("setSpan", start, end); 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((flags & START_MASK) == (PARAGRAPH << START_SHIFT)) { 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (start != 0 && start != length()) { 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char c = charAt(start - 1); 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c != '\n') 5106435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne throw new RuntimeException("PARAGRAPH span must start at paragraph boundary"); 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((flags & END_MASK) == PARAGRAPH) { 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end != 0 && end != length()) { 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char c = charAt(end - 1); 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c != '\n') 5196435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne throw new RuntimeException("PARAGRAPH span must end at paragraph boundary"); 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5236435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne if (start > mGapStart) { 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start += mGapLength; 5256435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne } else if (start == mGapStart) { 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int flag = (flags & START_MASK) >> START_SHIFT; 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (flag == POINT || (flag == PARAGRAPH && start == length())) 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start += mGapLength; 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5326435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne if (end > mGapStart) { 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end += mGapLength; 5346435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne } else if (end == mGapStart) { 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int flag = (flags & END_MASK); 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (flag == POINT || (flag == PARAGRAPH && end == length())) 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end += mGapLength; 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = mSpanCount; 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] spans = mSpans; 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spans[i] == what) { 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ostart = mSpanStarts[i]; 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int oend = mSpanEnds[i]; 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ostart > mGapStart) 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ostart -= mGapLength; 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (oend > mGapStart) 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project oend -= mGapLength; 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanStarts[i] = start; 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanEnds[i] = end; 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanFlags[i] = flags; 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 558fc1190b8f143bd00c825d4e52928c577e40e6c49Gilles Debunne if (send) sendSpanChanged(what, ostart, oend, nstart, nend); 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSpanCount + 1 >= mSpans.length) { 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int newsize = ArrayUtils.idealIntArraySize(mSpanCount + 1); 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] newspans = new Object[newsize]; 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] newspanstarts = new int[newsize]; 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] newspanends = new int[newsize]; 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] newspanflags = new int[newsize]; 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mSpans, 0, newspans, 0, mSpanCount); 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mSpanStarts, 0, newspanstarts, 0, mSpanCount); 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mSpanEnds, 0, newspanends, 0, mSpanCount); 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mSpanFlags, 0, newspanflags, 0, mSpanCount); 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpans = newspans; 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanStarts = newspanstarts; 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanEnds = newspanends; 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanFlags = newspanflags; 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpans[mSpanCount] = what; 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanStarts[mSpanCount] = start; 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanEnds[mSpanCount] = end; 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanFlags[mSpanCount] = flags; 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanCount++; 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 588fc1190b8f143bd00c825d4e52928c577e40e6c49Gilles Debunne if (send) sendSpanAdded(what, nstart, nend); 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Remove the specified markup object from the buffer. 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void removeSpan(Object what) { 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = mSpanCount - 1; i >= 0; i--) { 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSpans[i] == what) { 5976435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne removeSpan(i); 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the buffer offset of the beginning of the specified 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * markup object, or -1 if it is not attached to this buffer. 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getSpanStart(Object what) { 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = mSpanCount; 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] spans = mSpans; 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = count - 1; i >= 0; i--) { 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spans[i] == what) { 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int where = mSpanStarts[i]; 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (where > mGapStart) 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project where -= mGapLength; 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return where; 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the buffer offset of the end of the specified 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * markup object, or -1 if it is not attached to this buffer. 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getSpanEnd(Object what) { 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = mSpanCount; 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] spans = mSpans; 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = count - 1; i >= 0; i--) { 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spans[i] == what) { 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int where = mSpanEnds[i]; 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (where > mGapStart) 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project where -= mGapLength; 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return where; 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the flags of the end of the specified 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * markup object, or 0 if it is not attached to this buffer. 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getSpanFlags(Object what) { 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = mSpanCount; 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] spans = mSpans; 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = count - 1; i >= 0; i--) { 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spans[i] == what) { 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mSpanFlags[i]; 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return an array of the spans of the specified type that overlap 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the specified range of the buffer. The kind may be Object.class to get 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a list of all the spans regardless of type. 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 669312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne @SuppressWarnings("unchecked") 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public <T> T[] getSpans(int queryStart, int queryEnd, Class<T> kind) { 6716435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne if (kind == null) return ArrayUtils.emptyArray(kind); 6726435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int spanCount = mSpanCount; 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] spans = mSpans; 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] starts = mSpanStarts; 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] ends = mSpanEnds; 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] flags = mSpanFlags; 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int gapstart = mGapStart; 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int gaplen = mGapLength; 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = 0; 682312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne T[] ret = null; 683312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne T ret1 = null; 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < spanCount; i++) { 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int spanStart = starts[i]; 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spanStart > gapstart) { 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project spanStart -= gaplen; 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spanStart > queryEnd) { 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 693b062e81e3a16af43db3619d721aa522c137d1aa9Gilles Debunne 694b062e81e3a16af43db3619d721aa522c137d1aa9Gilles Debunne int spanEnd = ends[i]; 695b062e81e3a16af43db3619d721aa522c137d1aa9Gilles Debunne if (spanEnd > gapstart) { 696b062e81e3a16af43db3619d721aa522c137d1aa9Gilles Debunne spanEnd -= gaplen; 697b062e81e3a16af43db3619d721aa522c137d1aa9Gilles Debunne } 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spanEnd < queryStart) { 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spanStart != spanEnd && queryStart != queryEnd) { 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spanStart == queryEnd) 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spanEnd == queryStart) 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 709945ee9b1661e60e0074d4f16f61fc147c728c6bfGilles Debunne // Expensive test, should be performed after the previous tests 710945ee9b1661e60e0074d4f16f61fc147c728c6bfGilles Debunne if (!kind.isInstance(spans[i])) continue; 711945ee9b1661e60e0074d4f16f61fc147c728c6bfGilles Debunne 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (count == 0) { 713312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne // Safe conversion thanks to the isInstance test above 714312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne ret1 = (T) spans[i]; 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project count++; 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (count == 1) { 718312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne // Safe conversion, but requires a suppressWarning 719312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne ret = (T[]) Array.newInstance(kind, spanCount - i + 1); 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret[0] = ret1; 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int prio = flags[i] & SPAN_PRIORITY; 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (prio != 0) { 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int j; 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (j = 0; j < count; j++) { 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int p = getSpanFlags(ret[j]) & SPAN_PRIORITY; 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (prio > p) { 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(ret, j, ret, j + 1, count - j); 736312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne // Safe conversion thanks to the isInstance test above 737312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne ret[j] = (T) spans[i]; 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project count++; 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 740312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne // Safe conversion thanks to the isInstance test above 741312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne ret[count++] = (T) spans[i]; 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (count == 0) { 747f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt return ArrayUtils.emptyArray(kind); 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (count == 1) { 750312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne // Safe conversion, but requires a suppressWarning 751312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne ret = (T[]) Array.newInstance(kind, 1); 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret[0] = ret1; 753312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne return ret; 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (count == ret.length) { 756312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne return ret; 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 759312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne // Safe conversion, but requires a suppressWarning 760312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne T[] nret = (T[]) Array.newInstance(kind, count); 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(ret, 0, nret, 0, count); 762312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne return nret; 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the next offset after <code>start</code> but less than or 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * equal to <code>limit</code> where a span of the specified type 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * begins or ends. 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int nextSpanTransition(int start, int limit, Class kind) { 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = mSpanCount; 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] spans = mSpans; 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] starts = mSpanStarts; 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] ends = mSpanEnds; 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int gapstart = mGapStart; 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int gaplen = mGapLength; 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (kind == null) { 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project kind = Object.class; 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int st = starts[i]; 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int en = ends[i]; 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (st > gapstart) 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project st -= gaplen; 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (en > gapstart) 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project en -= gaplen; 7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (st > start && st < limit && kind.isInstance(spans[i])) 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project limit = st; 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (en > start && en < limit && kind.isInstance(spans[i])) 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project limit = en; 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return limit; 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return a new CharSequence containing a copy of the specified 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * range of this buffer, including the overlapping spans. 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public CharSequence subSequence(int start, int end) { 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new SpannableStringBuilder(this, start, end); 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copy the specified range of chars from this buffer into the 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * specified array, beginning at the specified offset. 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void getChars(int start, int end, char[] dest, int destoff) { 8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkRange("getChars", start, end); 8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end <= mGapStart) { 8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mText, start, dest, destoff, end - start); 8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (start >= mGapStart) { 8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mText, start + mGapLength, 8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest, destoff, end - start); 8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mText, start, dest, destoff, mGapStart - start); 8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mText, mGapStart + mGapLength, 8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest, destoff + (mGapStart - start), 8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end - mGapStart); 8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return a String containing a copy of the chars in this buffer. 8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 831312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne @Override 8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String toString() { 8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = length(); 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char[] buf = new char[len]; 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getChars(0, len, buf, 0); 8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new String(buf); 8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 840653d3a27878d5358b4a91518a756f6b9b3407b07Gilles Debunne /** 841653d3a27878d5358b4a91518a756f6b9b3407b07Gilles Debunne * Return a String containing a copy of the chars in this buffer, limited to the 842653d3a27878d5358b4a91518a756f6b9b3407b07Gilles Debunne * [start, end[ range. 843653d3a27878d5358b4a91518a756f6b9b3407b07Gilles Debunne * @hide 844653d3a27878d5358b4a91518a756f6b9b3407b07Gilles Debunne */ 845653d3a27878d5358b4a91518a756f6b9b3407b07Gilles Debunne public String substring(int start, int end) { 846653d3a27878d5358b4a91518a756f6b9b3407b07Gilles Debunne char[] buf = new char[end - start]; 847653d3a27878d5358b4a91518a756f6b9b3407b07Gilles Debunne getChars(start, end, buf, 0); 848653d3a27878d5358b4a91518a756f6b9b3407b07Gilles Debunne return new String(buf); 849653d3a27878d5358b4a91518a756f6b9b3407b07Gilles Debunne } 850653d3a27878d5358b4a91518a756f6b9b3407b07Gilles Debunne 851b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne private void sendBeforeTextChanged(TextWatcher[] watchers, int start, int before, int after) { 852b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne int n = watchers.length; 8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < n; i++) { 855b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne watchers[i].beforeTextChanged(this, start, before, after); 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 859b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne private void sendTextChanged(TextWatcher[] watchers, int start, int before, int after) { 860b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne int n = watchers.length; 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < n; i++) { 863b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne watchers[i].onTextChanged(this, start, before, after); 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 867b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne private void sendAfterTextChanged(TextWatcher[] watchers) { 868b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne int n = watchers.length; 8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < n; i++) { 871b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne watchers[i].afterTextChanged(this); 8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void sendSpanAdded(Object what, int start, int end) { 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SpanWatcher[] recip = getSpans(start, end, SpanWatcher.class); 8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int n = recip.length; 8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < n; i++) { 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project recip[i].onSpanAdded(this, what, start, end); 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void sendSpanRemoved(Object what, int start, int end) { 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SpanWatcher[] recip = getSpans(start, end, SpanWatcher.class); 8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int n = recip.length; 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < n; i++) { 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project recip[i].onSpanRemoved(this, what, start, end); 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void sendSpanChanged(Object what, int s, int e, int st, int en) { 8946435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne SpanWatcher[] recip = getSpans(Math.min(s, st), Math.max(e, en), SpanWatcher.class); 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int n = recip.length; 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < n; i++) { 8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project recip[i].onSpanChanged(this, what, s, e, st, en); 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static String region(int start, int end) { 9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "(" + start + " ... " + end + ")"; 9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void checkRange(final String operation, int start, int end) { 9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end < start) { 9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IndexOutOfBoundsException(operation + " " + 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project region(start, end) + 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project " has end before start"); 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = length(); 9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (start > len || end > len) { 9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IndexOutOfBoundsException(operation + " " + 9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project region(start, end) + 9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project " ends beyond length " + len); 9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (start < 0 || end < 0) { 9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IndexOutOfBoundsException(operation + " " + 9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project region(start, end) + 9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project " starts before 0"); 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 928312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne/* 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean isprint(char c) { // XXX 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c >= ' ' && c <= '~') 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int startFlag(int flag) { 9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (flag >> 4) & 0x0F; 9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int endFlag(int flag) { 9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return flag & 0x0F; 9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void dump() { // XXX 9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < mGapStart; i++) { 9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print('|'); 9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print(' '); 9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print(isprint(mText[i]) ? mText[i] : '.'); 9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print(' '); 9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = mGapStart; i < mGapStart + mGapLength; i++) { 9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print('|'); 9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print('('); 9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print(isprint(mText[i]) ? mText[i] : '.'); 9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print(')'); 9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = mGapStart + mGapLength; i < mText.length; i++) { 9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print('|'); 9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print(' '); 9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print(isprint(mText[i]) ? mText[i] : '.'); 9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print(' '); 9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print('\n'); 9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < mText.length + 1; i++) { 9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int found = 0; 9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int wfound = 0; 9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int j = 0; j < mSpanCount; j++) { 9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSpanStarts[j] == i) { 9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project found = 1; 9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project wfound = j; 9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSpanEnds[j] == i) { 9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project found = 2; 9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project wfound = j; 9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (found == 1) { 9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (startFlag(mSpanFlags[wfound]) == MARK) 9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print("( "); 9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (startFlag(mSpanFlags[wfound]) == PARAGRAPH) 9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print("< "); 9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print("[ "); 9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (found == 2) { 9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (endFlag(mSpanFlags[wfound]) == POINT) 9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print(") "); 9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (endFlag(mSpanFlags[wfound]) == PARAGRAPH) 9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print("> "); 9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print("] "); 10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print(" "); 10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print("\n"); 10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project*/ 10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Don't call this yourself -- exists for Canvas to use internally. 10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide} 10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1013b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne public void drawText(Canvas c, int start, int end, float x, float y, Paint p) { 10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkRange("drawText", start, end); 10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end <= mGapStart) { 10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c.drawText(mText, start, end - start, x, y, p); 10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (start >= mGapStart) { 10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c.drawText(mText, start + mGapLength, end - start, x, y, p); 10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char[] buf = TextUtils.obtain(end - start); 10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getChars(start, end, buf, 0); 10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c.drawText(buf, 0, end - start, x, y, p); 10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextUtils.recycle(buf); 10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10290c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1031f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt * Don't call this yourself -- exists for Canvas to use internally. 1032f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt * {@hide} 1033f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt */ 1034b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne public void drawTextRun(Canvas c, int start, int end, int contextStart, int contextEnd, 10350c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt float x, float y, int flags, Paint p) { 1036f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt checkRange("drawTextRun", start, end); 1037f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt 10380c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt int contextLen = contextEnd - contextStart; 10390c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt int len = end - start; 10400c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt if (contextEnd <= mGapStart) { 10410c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt c.drawTextRun(mText, start, len, contextStart, contextLen, x, y, flags, p); 10420c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt } else if (contextStart >= mGapStart) { 10430c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt c.drawTextRun(mText, start + mGapLength, len, contextStart + mGapLength, 10440c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt contextLen, x, y, flags, p); 1045f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt } else { 10460c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt char[] buf = TextUtils.obtain(contextLen); 10470c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt getChars(contextStart, contextEnd, buf, 0); 10480c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt c.drawTextRun(buf, start - contextStart, len, 0, contextLen, x, y, flags, p); 1049f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt TextUtils.recycle(buf); 1050f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt } 1051f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt } 1052f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt 1053f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt /** 10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Don't call this yourself -- exists for Paint to use internally. 10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide} 10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public float measureText(int start, int end, Paint p) { 10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkRange("measureText", start, end); 10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float ret; 10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end <= mGapStart) { 10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = p.measureText(mText, start, end - start); 10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (start >= mGapStart) { 10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = p.measureText(mText, start + mGapLength, end - start); 10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char[] buf = TextUtils.obtain(end - start); 10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getChars(start, end, buf, 0); 10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = p.measureText(buf, 0, end - start); 10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextUtils.recycle(buf); 10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret; 10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Don't call this yourself -- exists for Paint to use internally. 10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide} 10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getTextWidths(int start, int end, float[] widths, Paint p) { 10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkRange("getTextWidths", start, end); 10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ret; 10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end <= mGapStart) { 10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = p.getTextWidths(mText, start, end - start, widths); 10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (start >= mGapStart) { 10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = p.getTextWidths(mText, start + mGapLength, end - start, 10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project widths); 10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char[] buf = TextUtils.obtain(end - start); 10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getChars(start, end, buf, 0); 10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = p.getTextWidths(buf, 0, end - start, widths); 10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextUtils.recycle(buf); 10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret; 11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11020c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt /** 11030c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt * Don't call this yourself -- exists for Paint to use internally. 11040c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt * {@hide} 11050c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt */ 11060c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt public float getTextRunAdvances(int start, int end, int contextStart, int contextEnd, int flags, 11070c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt float[] advances, int advancesPos, Paint p) { 11080c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 11090c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt float ret; 11100c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 11110c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt int contextLen = contextEnd - contextStart; 11120c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt int len = end - start; 11130c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 11140c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt if (end <= mGapStart) { 11150c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt ret = p.getTextRunAdvances(mText, start, len, contextStart, contextLen, 11160c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt flags, advances, advancesPos); 11170c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt } else if (start >= mGapStart) { 11180c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt ret = p.getTextRunAdvances(mText, start + mGapLength, len, 11190c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt contextStart + mGapLength, contextLen, flags, advances, advancesPos); 11200c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt } else { 11210c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt char[] buf = TextUtils.obtain(contextLen); 11220c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt getChars(contextStart, contextEnd, buf, 0); 11230c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt ret = p.getTextRunAdvances(buf, start - contextStart, len, 11240c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 0, contextLen, flags, advances, advancesPos); 11250c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt TextUtils.recycle(buf); 11260c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt } 11270c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 11280c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt return ret; 11290c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt } 11300c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 1131f09d510cd18854f41632433503ca46cc41362febGilles Debunne /** 1132eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio * Don't call this yourself -- exists for Paint to use internally. 1133eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio * {@hide} 1134eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio */ 11350a1413e4bf9dcda2a8abb2287e43f612a7fb2453Fabrice Di Meglio public float getTextRunAdvances(int start, int end, int contextStart, int contextEnd, int flags, 11360a1413e4bf9dcda2a8abb2287e43f612a7fb2453Fabrice Di Meglio float[] advances, int advancesPos, Paint p, int reserved) { 1137eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio 1138eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio float ret; 1139eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio 1140eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio int contextLen = contextEnd - contextStart; 1141eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio int len = end - start; 1142eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio 1143eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio if (end <= mGapStart) { 11440a1413e4bf9dcda2a8abb2287e43f612a7fb2453Fabrice Di Meglio ret = p.getTextRunAdvances(mText, start, len, contextStart, contextLen, 11450a1413e4bf9dcda2a8abb2287e43f612a7fb2453Fabrice Di Meglio flags, advances, advancesPos, reserved); 1146eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio } else if (start >= mGapStart) { 11470a1413e4bf9dcda2a8abb2287e43f612a7fb2453Fabrice Di Meglio ret = p.getTextRunAdvances(mText, start + mGapLength, len, 11480a1413e4bf9dcda2a8abb2287e43f612a7fb2453Fabrice Di Meglio contextStart + mGapLength, contextLen, flags, advances, advancesPos, reserved); 1149eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio } else { 1150eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio char[] buf = TextUtils.obtain(contextLen); 1151eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio getChars(contextStart, contextEnd, buf, 0); 11520a1413e4bf9dcda2a8abb2287e43f612a7fb2453Fabrice Di Meglio ret = p.getTextRunAdvances(buf, start - contextStart, len, 11530a1413e4bf9dcda2a8abb2287e43f612a7fb2453Fabrice Di Meglio 0, contextLen, flags, advances, advancesPos, reserved); 1154eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio TextUtils.recycle(buf); 1155eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio } 1156eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio 1157eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio return ret; 1158eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio } 1159eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio 1160eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio /** 1161f09d510cd18854f41632433503ca46cc41362febGilles Debunne * Returns the next cursor position in the run. This avoids placing the cursor between 1162f09d510cd18854f41632433503ca46cc41362febGilles Debunne * surrogates, between characters that form conjuncts, between base characters and combining 1163f09d510cd18854f41632433503ca46cc41362febGilles Debunne * marks, or within a reordering cluster. 1164f09d510cd18854f41632433503ca46cc41362febGilles Debunne * 1165f09d510cd18854f41632433503ca46cc41362febGilles Debunne * <p>The context is the shaping context for cursor movement, generally the bounds of the metric 1166f09d510cd18854f41632433503ca46cc41362febGilles Debunne * span enclosing the cursor in the direction of movement. 1167f09d510cd18854f41632433503ca46cc41362febGilles Debunne * <code>contextStart</code>, <code>contextEnd</code> and <code>offset</code> are relative to 1168f09d510cd18854f41632433503ca46cc41362febGilles Debunne * the start of the string.</p> 1169f09d510cd18854f41632433503ca46cc41362febGilles Debunne * 1170616f3835a0a67328b378cb1cbc126f17478ab4a0Gilles Debunne * <p>If cursorOpt is CURSOR_AT and the offset is not a valid cursor position, 1171f09d510cd18854f41632433503ca46cc41362febGilles Debunne * this returns -1. Otherwise this will never return a value before contextStart or after 1172f09d510cd18854f41632433503ca46cc41362febGilles Debunne * contextEnd.</p> 1173f09d510cd18854f41632433503ca46cc41362febGilles Debunne * 1174f09d510cd18854f41632433503ca46cc41362febGilles Debunne * @param contextStart the start index of the context 1175f09d510cd18854f41632433503ca46cc41362febGilles Debunne * @param contextEnd the (non-inclusive) end index of the context 1176616f3835a0a67328b378cb1cbc126f17478ab4a0Gilles Debunne * @param flags either DIRECTION_RTL or DIRECTION_LTR 1177f09d510cd18854f41632433503ca46cc41362febGilles Debunne * @param offset the cursor position to move from 1178616f3835a0a67328b378cb1cbc126f17478ab4a0Gilles Debunne * @param cursorOpt how to move the cursor, one of CURSOR_AFTER, 1179616f3835a0a67328b378cb1cbc126f17478ab4a0Gilles Debunne * CURSOR_AT_OR_AFTER, CURSOR_BEFORE, 1180616f3835a0a67328b378cb1cbc126f17478ab4a0Gilles Debunne * CURSOR_AT_OR_BEFORE, or CURSOR_AT 1181f09d510cd18854f41632433503ca46cc41362febGilles Debunne * @param p the Paint object that is requesting this information 1182f09d510cd18854f41632433503ca46cc41362febGilles Debunne * @return the offset of the next position, or -1 1183b0b225602cc84e0602450a417a562e8f53f29c6bGilles Debunne * @deprecated This is an internal method, refrain from using it in your code 1184f09d510cd18854f41632433503ca46cc41362febGilles Debunne */ 1185b0b225602cc84e0602450a417a562e8f53f29c6bGilles Debunne @Deprecated 11860c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt public int getTextRunCursor(int contextStart, int contextEnd, int flags, int offset, 11870c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt int cursorOpt, Paint p) { 11880c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 11890c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt int ret; 11900c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 11910c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt int contextLen = contextEnd - contextStart; 11920c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt if (contextEnd <= mGapStart) { 11930c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt ret = p.getTextRunCursor(mText, contextStart, contextLen, 11940c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt flags, offset, cursorOpt); 11950c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt } else if (contextStart >= mGapStart) { 11960c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt ret = p.getTextRunCursor(mText, contextStart + mGapLength, contextLen, 1197312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne flags, offset + mGapLength, cursorOpt) - mGapLength; 11980c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt } else { 11990c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt char[] buf = TextUtils.obtain(contextLen); 12000c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt getChars(contextStart, contextEnd, buf, 0); 12010c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt ret = p.getTextRunCursor(buf, 0, contextLen, 12020c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt flags, offset - contextStart, cursorOpt) + contextStart; 12030c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt TextUtils.recycle(buf); 12040c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt } 12050c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 12060c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt return ret; 12070c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt } 12080c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setFilters(InputFilter[] filters) { 12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (filters == null) { 12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException(); 12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFilters = filters; 12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public InputFilter[] getFilters() { 12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mFilters; 12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final InputFilter[] NO_FILTERS = new InputFilter[0]; 12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private InputFilter[] mFilters = NO_FILTERS; 12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private char[] mText; 12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mGapStart; 12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mGapLength; 12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Object[] mSpans; 12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int[] mSpanStarts; 12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int[] mSpanEnds; 12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int[] mSpanFlags; 12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mSpanCount; 12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1236b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne // TODO These value are tightly related to the public SPAN_MARK/POINT values in {@link Spanned} 12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int POINT = 2; 12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int PARAGRAPH = 3; 12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int START_MASK = 0xF0; 12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int END_MASK = 0x0F; 12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int START_SHIFT = 4; 12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1244