SpannableStringBuilder.java revision f47d7405bbcb25d7cdf89ebb059f41520fe9ab87
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 com.android.internal.util.ArrayUtils; 20f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Canvas; 22f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Feltimport android.graphics.Paint; 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 */ 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class SpannableStringBuilder 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimplements CharSequence, GetChars, Spannable, Editable, Appendable, 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project GraphicsOperations 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a new SpannableStringBuilder with empty contents 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannableStringBuilder() { 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(""); 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a new SpannableStringBuilder containing a copy of the 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * specified text, including its spans if any. 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannableStringBuilder(CharSequence text) { 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(text, 0, text.length()); 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a new SpannableStringBuilder containing a copy of the 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * specified slice of the specified text, including its spans if any. 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannableStringBuilder(CharSequence text, int start, int end) { 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int srclen = end - start; 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = ArrayUtils.idealCharArraySize(srclen + 1); 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mText = new char[len]; 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGapStart = srclen; 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGapLength = len - srclen; 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextUtils.getChars(text, start, end, mText, 0); 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanCount = 0; 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int alloc = ArrayUtils.idealIntArraySize(0); 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpans = new Object[alloc]; 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanStarts = new int[alloc]; 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanEnds = new int[alloc]; 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanFlags = new int[alloc]; 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (text instanceof Spanned) { 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spanned sp = (Spanned) text; 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] spans = sp.getSpans(start, end, Object.class); 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < spans.length; i++) { 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spans[i] instanceof NoCopySpan) { 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int st = sp.getSpanStart(spans[i]) - start; 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int en = sp.getSpanEnd(spans[i]) - start; 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fl = sp.getSpanFlags(spans[i]); 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (st < 0) 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project st = 0; 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (st > end - start) 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project st = end - start; 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (en < 0) 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project en = 0; 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (en > end - start) 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project en = end - start; 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSpan(spans[i], st, en, fl); 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static SpannableStringBuilder valueOf(CharSequence source) { 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (source instanceof SpannableStringBuilder) { 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (SpannableStringBuilder) source; 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new SpannableStringBuilder(source); 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the char at the specified offset within the buffer. 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public char charAt(int where) { 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = length(); 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (where < 0) { 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IndexOutOfBoundsException("charAt: " + where + " < 0"); 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (where >= len) { 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IndexOutOfBoundsException("charAt: " + where + 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project " >= length " + len); 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (where >= mGapStart) 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mText[where + mGapLength]; 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mText[where]; 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the number of chars in the buffer. 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int length() { 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mText.length - mGapLength; 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void resizeFor(int size) { 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int newlen = ArrayUtils.idealCharArraySize(size + 1); 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char[] newtext = new char[newlen]; 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int after = mText.length - (mGapStart + mGapLength); 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mText, 0, newtext, 0, mGapStart); 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mText, mText.length - after, 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newtext, newlen - after, after); 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < mSpanCount; i++) { 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSpanStarts[i] > mGapStart) 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanStarts[i] += newlen - mText.length; 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSpanEnds[i] > mGapStart) 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanEnds[i] += newlen - mText.length; 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int oldlen = mText.length; 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mText = newtext; 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGapLength += mText.length - oldlen; 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mGapLength < 1) 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new Exception("mGapLength < 1").printStackTrace(); 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void moveGapTo(int where) { 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (where == mGapStart) 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean atend = (where == length()); 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (where < mGapStart) { 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int overlap = mGapStart - where; 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mText, where, 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mText, mGapStart + mGapLength - overlap, overlap); 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else /* where > mGapStart */ { 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int overlap = where - mGapStart; 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mText, where + mGapLength - overlap, 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mText, mGapStart, overlap); 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // XXX be more clever 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < mSpanCount; i++) { 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int start = mSpanStarts[i]; 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int end = mSpanEnds[i]; 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (start > mGapStart) 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start -= mGapLength; 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (start > where) 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start += mGapLength; 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else if (start == where) { 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int flag = (mSpanFlags[i] & START_MASK) >> START_SHIFT; 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (flag == POINT || (atend && flag == PARAGRAPH)) 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start += mGapLength; 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end > mGapStart) 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end -= mGapLength; 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end > where) 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end += mGapLength; 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else if (end == where) { 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int flag = (mSpanFlags[i] & END_MASK); 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (flag == POINT || (atend && flag == PARAGRAPH)) 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end += mGapLength; 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanStarts[i] = start; 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanEnds[i] = end; 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGapStart = where; 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannableStringBuilder insert(int where, CharSequence tb, int start, int end) { 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return replace(where, where, tb, start, end); 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannableStringBuilder insert(int where, CharSequence tb) { 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return replace(where, where, tb, 0, tb.length()); 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannableStringBuilder delete(int start, int end) { 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SpannableStringBuilder ret = replace(start, end, "", 0, 0); 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mGapLength > 2 * length()) 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project resizeFor(length()); 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret; // == this 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void clear() { 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project replace(0, length(), "", 0, 0); 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void clearSpans() { 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = mSpanCount - 1; i >= 0; i--) { 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object what = mSpans[i]; 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ostart = mSpanStarts[i]; 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int oend = mSpanEnds[i]; 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ostart > mGapStart) 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ostart -= mGapLength; 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (oend > mGapStart) 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project oend -= mGapLength; 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanCount = i; 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpans[i] = null; 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sendSpanRemoved(what, ostart, oend); 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannableStringBuilder append(CharSequence text) { 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int length = length(); 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return replace(length, length, text, 0, text.length()); 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannableStringBuilder append(CharSequence text, int start, int end) { 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int length = length(); 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return replace(length, length, text, start, end); 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannableStringBuilder append(char text) { 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return append(String.valueOf(text)); 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int change(int start, int end, 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence tb, int tbstart, int tbend) { 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return change(true, start, end, tb, tbstart, tbend); 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int change(boolean notify, int start, int end, 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence tb, int tbstart, int tbend) { 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkRange("replace", start, end); 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ret = tbend - tbstart; 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextWatcher[] recipients = null; 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (notify) 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project recipients = sendTextWillChange(start, end - start, 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tbend - tbstart); 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = mSpanCount - 1; i >= 0; i--) { 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((mSpanFlags[i] & SPAN_PARAGRAPH) == SPAN_PARAGRAPH) { 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int st = mSpanStarts[i]; 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (st > mGapStart) 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project st -= mGapLength; 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int en = mSpanEnds[i]; 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (en > mGapStart) 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project en -= mGapLength; 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ost = st; 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int oen = en; 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int clen = length(); 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (st > start && st <= end) { 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (st = end; st < clen; st++) 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (st > end && charAt(st - 1) == '\n') 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (en > start && en <= end) { 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (en = end; en < clen; en++) 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (en > end && charAt(en - 1) == '\n') 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (st != ost || en != oen) 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSpan(mSpans[i], st, en, mSpanFlags[i]); 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project moveGapTo(end); 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (tbend - tbstart >= mGapLength + (end - start)) 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project resizeFor(mText.length - mGapLength + 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tbend - tbstart - (end - start)); 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGapStart += tbend - tbstart - (end - start); 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGapLength -= tbend - tbstart - (end - start); 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mGapLength < 1) 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new Exception("mGapLength < 1").printStackTrace(); 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextUtils.getChars(tb, tbstart, tbend, mText, start); 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (tb instanceof Spanned) { 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spanned sp = (Spanned) tb; 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] spans = sp.getSpans(tbstart, tbend, Object.class); 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < spans.length; i++) { 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int st = sp.getSpanStart(spans[i]); 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int en = sp.getSpanEnd(spans[i]); 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (st < tbstart) 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project st = tbstart; 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (en > tbend) 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project en = tbend; 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (getSpanStart(spans[i]) < 0) { 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSpan(false, spans[i], 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project st - tbstart + start, 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project en - tbstart + start, 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sp.getSpanFlags(spans[i])); 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // no need for span fixup on pure insertion 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (tbend > tbstart && end - start == 0) { 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (notify) { 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sendTextChange(recipients, start, end - start, tbend - tbstart); 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sendTextHasChanged(recipients); 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret; 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean atend = (mGapStart + mGapLength == mText.length); 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = mSpanCount - 1; i >= 0; i--) { 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSpanStarts[i] >= start && 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanStarts[i] < mGapStart + mGapLength) { 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int flag = (mSpanFlags[i] & START_MASK) >> START_SHIFT; 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (flag == POINT || (flag == PARAGRAPH && atend)) 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanStarts[i] = mGapStart + mGapLength; 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanStarts[i] = start; 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSpanEnds[i] >= start && 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanEnds[i] < mGapStart + mGapLength) { 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int flag = (mSpanFlags[i] & END_MASK); 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (flag == POINT || (flag == PARAGRAPH && atend)) 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanEnds[i] = mGapStart + mGapLength; 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanEnds[i] = start; 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // remove 0-length SPAN_EXCLUSIVE_EXCLUSIVE 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // XXX send notification on removal 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSpanEnds[i] < mSpanStarts[i]) { 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mSpans, i + 1, 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpans, i, mSpanCount - (i + 1)); 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mSpanStarts, i + 1, 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanStarts, i, mSpanCount - (i + 1)); 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mSpanEnds, i + 1, 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanEnds, i, mSpanCount - (i + 1)); 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mSpanFlags, i + 1, 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanFlags, i, mSpanCount - (i + 1)); 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanCount--; 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (notify) { 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sendTextChange(recipients, start, end - start, tbend - tbstart); 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sendTextHasChanged(recipients); 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret; 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannableStringBuilder replace(int start, int end, CharSequence tb) { 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return replace(start, end, tb, 0, tb.length()); 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannableStringBuilder replace(final int start, final int end, 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence tb, int tbstart, int tbend) { 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int filtercount = mFilters.length; 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < filtercount; i++) { 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence repl = mFilters[i].filter(tb, tbstart, tbend, 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this, start, end); 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (repl != null) { 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tb = repl; 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tbstart = 0; 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tbend = repl.length(); 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end == start && tbstart == tbend) { 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return this; 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end == start || tbstart == tbend) { 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project change(start, end, tb, tbstart, tbend); 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int selstart = Selection.getSelectionStart(this); 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int selend = Selection.getSelectionEnd(this); 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // XXX just make the span fixups in change() do the right thing 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // instead of this madness! 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkRange("replace", start, end); 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project moveGapTo(end); 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextWatcher[] recipients; 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project recipients = sendTextWillChange(start, end - start, 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tbend - tbstart); 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int origlen = end - start; 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mGapLength < 2) 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project resizeFor(length() + 1); 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = mSpanCount - 1; i >= 0; i--) { 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSpanStarts[i] == mGapStart) 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanStarts[i]++; 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSpanEnds[i] == mGapStart) 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanEnds[i]++; 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mText[mGapStart] = ' '; 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGapStart++; 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGapLength--; 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mGapLength < 1) 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new Exception("mGapLength < 1").printStackTrace(); 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int oldlen = (end + 1) - start; 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int inserted = change(false, start + 1, start + 1, 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tb, tbstart, tbend); 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project change(false, start, start + 1, "", 0, 0); 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project change(false, start + inserted, start + inserted + oldlen - 1, 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "", 0, 0); 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Special case to keep the cursor in the same position 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * if it was somewhere in the middle of the replaced region. 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If it was at the start or the end or crossing the whole 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * replacement, it should already be where it belongs. 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * TODO: Is there some more general mechanism that could 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * accomplish this? 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (selstart > start && selstart < end) { 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long off = selstart - start; 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project off = off * inserted / (end - start); 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project selstart = (int) off + start; 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSpan(false, Selection.SELECTION_START, selstart, selstart, 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spanned.SPAN_POINT_POINT); 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (selend > start && selend < end) { 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long off = selend - start; 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project off = off * inserted / (end - start); 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project selend = (int) off + start; 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSpan(false, Selection.SELECTION_END, selend, selend, 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spanned.SPAN_POINT_POINT); 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sendTextChange(recipients, start, origlen, inserted); 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sendTextHasChanged(recipients); 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return this; 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Mark the specified range of text with the specified object. 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The flags determine how the span will behave when text is 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * inserted at the start or end of the span's range. 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setSpan(Object what, int start, int end, int flags) { 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSpan(true, what, start, end, flags); 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void setSpan(boolean send, 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object what, int start, int end, int flags) { 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int nstart = start; 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int nend = end; 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkRange("setSpan", start, end); 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((flags & START_MASK) == (PARAGRAPH << START_SHIFT)) { 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (start != 0 && start != length()) { 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char c = charAt(start - 1); 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c != '\n') 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new RuntimeException( 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "PARAGRAPH span must start at paragraph boundary"); 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((flags & END_MASK) == PARAGRAPH) { 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end != 0 && end != length()) { 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char c = charAt(end - 1); 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c != '\n') 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new RuntimeException( 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "PARAGRAPH span must end at paragraph boundary"); 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (start > mGapStart) 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start += mGapLength; 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else if (start == mGapStart) { 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int flag = (flags & START_MASK) >> START_SHIFT; 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (flag == POINT || (flag == PARAGRAPH && start == length())) 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start += mGapLength; 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end > mGapStart) 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end += mGapLength; 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else if (end == mGapStart) { 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int flag = (flags & END_MASK); 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (flag == POINT || (flag == PARAGRAPH && end == length())) 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end += mGapLength; 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = mSpanCount; 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] spans = mSpans; 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spans[i] == what) { 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ostart = mSpanStarts[i]; 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int oend = mSpanEnds[i]; 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ostart > mGapStart) 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ostart -= mGapLength; 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (oend > mGapStart) 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project oend -= mGapLength; 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanStarts[i] = start; 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanEnds[i] = end; 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanFlags[i] = flags; 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (send) 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sendSpanChanged(what, ostart, oend, nstart, nend); 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSpanCount + 1 >= mSpans.length) { 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int newsize = ArrayUtils.idealIntArraySize(mSpanCount + 1); 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] newspans = new Object[newsize]; 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] newspanstarts = new int[newsize]; 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] newspanends = new int[newsize]; 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] newspanflags = new int[newsize]; 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mSpans, 0, newspans, 0, mSpanCount); 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mSpanStarts, 0, newspanstarts, 0, mSpanCount); 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mSpanEnds, 0, newspanends, 0, mSpanCount); 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mSpanFlags, 0, newspanflags, 0, mSpanCount); 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpans = newspans; 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanStarts = newspanstarts; 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanEnds = newspanends; 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanFlags = newspanflags; 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpans[mSpanCount] = what; 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanStarts[mSpanCount] = start; 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanEnds[mSpanCount] = end; 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanFlags[mSpanCount] = flags; 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanCount++; 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (send) 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sendSpanAdded(what, nstart, nend); 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Remove the specified markup object from the buffer. 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void removeSpan(Object what) { 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = mSpanCount - 1; i >= 0; i--) { 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSpans[i] == what) { 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ostart = mSpanStarts[i]; 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int oend = mSpanEnds[i]; 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ostart > mGapStart) 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ostart -= mGapLength; 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (oend > mGapStart) 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project oend -= mGapLength; 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = mSpanCount - (i + 1); 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mSpans, i + 1, mSpans, i, count); 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mSpanStarts, i + 1, mSpanStarts, i, count); 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mSpanEnds, i + 1, mSpanEnds, i, count); 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mSpanFlags, i + 1, mSpanFlags, i, count); 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanCount--; 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpans[mSpanCount] = null; 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sendSpanRemoved(what, ostart, oend); 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the buffer offset of the beginning of the specified 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * markup object, or -1 if it is not attached to this buffer. 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getSpanStart(Object what) { 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = mSpanCount; 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] spans = mSpans; 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = count - 1; i >= 0; i--) { 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spans[i] == what) { 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int where = mSpanStarts[i]; 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (where > mGapStart) 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project where -= mGapLength; 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return where; 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the buffer offset of the end of the specified 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * markup object, or -1 if it is not attached to this buffer. 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getSpanEnd(Object what) { 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = mSpanCount; 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] spans = mSpans; 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = count - 1; i >= 0; i--) { 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spans[i] == what) { 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int where = mSpanEnds[i]; 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (where > mGapStart) 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project where -= mGapLength; 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return where; 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the flags of the end of the specified 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * markup object, or 0 if it is not attached to this buffer. 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getSpanFlags(Object what) { 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = mSpanCount; 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] spans = mSpans; 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = count - 1; i >= 0; i--) { 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spans[i] == what) { 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mSpanFlags[i]; 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return an array of the spans of the specified type that overlap 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the specified range of the buffer. The kind may be Object.class to get 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a list of all the spans regardless of type. 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public <T> T[] getSpans(int queryStart, int queryEnd, Class<T> kind) { 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int spanCount = mSpanCount; 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] spans = mSpans; 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] starts = mSpanStarts; 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] ends = mSpanEnds; 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] flags = mSpanFlags; 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int gapstart = mGapStart; 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int gaplen = mGapLength; 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = 0; 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] ret = null; 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object ret1 = null; 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < spanCount; i++) { 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int spanStart = starts[i]; 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int spanEnd = ends[i]; 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spanStart > gapstart) { 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project spanStart -= gaplen; 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spanEnd > gapstart) { 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project spanEnd -= gaplen; 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spanStart > queryEnd) { 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spanEnd < queryStart) { 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spanStart != spanEnd && queryStart != queryEnd) { 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spanStart == queryEnd) 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spanEnd == queryStart) 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (kind != null && !kind.isInstance(spans[i])) { 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (count == 0) { 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret1 = spans[i]; 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project count++; 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (count == 1) { 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = (Object[]) Array.newInstance(kind, spanCount - i + 1); 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret[0] = ret1; 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int prio = flags[i] & SPAN_PRIORITY; 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (prio != 0) { 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int j; 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (j = 0; j < count; j++) { 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int p = getSpanFlags(ret[j]) & SPAN_PRIORITY; 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (prio > p) { 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(ret, j, ret, j + 1, count - j); 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret[j] = spans[i]; 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project count++; 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret[count++] = spans[i]; 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (count == 0) { 784f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt return ArrayUtils.emptyArray(kind); 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (count == 1) { 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = (Object[]) Array.newInstance(kind, 1); 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret[0] = ret1; 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (T[]) ret; 7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (count == ret.length) { 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (T[]) ret; 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] nret = (Object[]) Array.newInstance(kind, count); 7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(ret, 0, nret, 0, count); 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (T[]) nret; 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the next offset after <code>start</code> but less than or 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * equal to <code>limit</code> where a span of the specified type 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * begins or ends. 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int nextSpanTransition(int start, int limit, Class kind) { 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = mSpanCount; 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] spans = mSpans; 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] starts = mSpanStarts; 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] ends = mSpanEnds; 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int gapstart = mGapStart; 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int gaplen = mGapLength; 8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (kind == null) { 8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project kind = Object.class; 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int st = starts[i]; 8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int en = ends[i]; 8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (st > gapstart) 8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project st -= gaplen; 8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (en > gapstart) 8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project en -= gaplen; 8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (st > start && st < limit && kind.isInstance(spans[i])) 8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project limit = st; 8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (en > start && en < limit && kind.isInstance(spans[i])) 8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project limit = en; 8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return limit; 8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return a new CharSequence containing a copy of the specified 8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * range of this buffer, including the overlapping spans. 8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public CharSequence subSequence(int start, int end) { 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new SpannableStringBuilder(this, start, end); 8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copy the specified range of chars from this buffer into the 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * specified array, beginning at the specified offset. 8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void getChars(int start, int end, char[] dest, int destoff) { 8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkRange("getChars", start, end); 8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end <= mGapStart) { 8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mText, start, dest, destoff, end - start); 8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (start >= mGapStart) { 8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mText, start + mGapLength, 8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest, destoff, end - start); 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mText, start, dest, destoff, mGapStart - start); 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mText, mGapStart + mGapLength, 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dest, destoff + (mGapStart - start), 8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end - mGapStart); 8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return a String containing a copy of the chars in this buffer. 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String toString() { 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = length(); 8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char[] buf = new char[len]; 8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getChars(0, len, buf, 0); 8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new String(buf); 8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private TextWatcher[] sendTextWillChange(int start, int before, int after) { 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextWatcher[] recip = getSpans(start, start + before, TextWatcher.class); 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int n = recip.length; 8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < n; i++) { 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project recip[i].beforeTextChanged(this, start, before, after); 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return recip; 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void sendTextChange(TextWatcher[] recip, int start, int before, 8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int after) { 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int n = recip.length; 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < n; i++) { 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project recip[i].onTextChanged(this, start, before, after); 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void sendTextHasChanged(TextWatcher[] recip) { 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].afterTextChanged(this); 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void sendSpanAdded(Object what, int start, int end) { 9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SpanWatcher[] recip = getSpans(start, end, SpanWatcher.class); 9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int n = recip.length; 9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < n; i++) { 9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project recip[i].onSpanAdded(this, what, start, end); 9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void sendSpanRemoved(Object what, int start, int end) { 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SpanWatcher[] recip = getSpans(start, end, SpanWatcher.class); 9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int n = recip.length; 9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < n; i++) { 9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project recip[i].onSpanRemoved(this, what, start, end); 9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void sendSpanChanged(Object what, int s, int e, int st, int en) { 9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SpanWatcher[] recip = getSpans(Math.min(s, st), Math.max(e, en), 9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SpanWatcher.class); 9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int n = recip.length; 9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < n; i++) { 9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project recip[i].onSpanChanged(this, what, s, e, st, en); 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static String region(int start, int end) { 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "(" + start + " ... " + end + ")"; 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void checkRange(final String operation, int start, int end) { 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end < start) { 9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IndexOutOfBoundsException(operation + " " + 9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project region(start, end) + 9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project " has end before start"); 9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = length(); 9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (start > len || end > len) { 9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IndexOutOfBoundsException(operation + " " + 9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project region(start, end) + 9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project " ends beyond length " + len); 9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (start < 0 || end < 0) { 9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IndexOutOfBoundsException(operation + " " + 9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project region(start, end) + 9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project " starts before 0"); 9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean isprint(char c) { // XXX 9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c >= ' ' && c <= '~') 9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int startFlag(int flag) { 9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (flag >> 4) & 0x0F; 9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int endFlag(int flag) { 9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return flag & 0x0F; 9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void dump() { // XXX 9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < mGapStart; i++) { 9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print('|'); 9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print(' '); 9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print(isprint(mText[i]) ? mText[i] : '.'); 9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print(' '); 9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = mGapStart; i < mGapStart + mGapLength; i++) { 9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print('|'); 9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print('('); 9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print(isprint(mText[i]) ? mText[i] : '.'); 9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print(')'); 9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = mGapStart + mGapLength; i < mText.length; i++) { 9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print('|'); 9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print(' '); 9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print(isprint(mText[i]) ? mText[i] : '.'); 9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print(' '); 9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print('\n'); 9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < mText.length + 1; i++) { 9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int found = 0; 9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int wfound = 0; 9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int j = 0; j < mSpanCount; j++) { 10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSpanStarts[j] == i) { 10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project found = 1; 10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project wfound = j; 10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSpanEnds[j] == i) { 10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project found = 2; 10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project wfound = j; 10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (found == 1) { 10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (startFlag(mSpanFlags[wfound]) == MARK) 10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print("( "); 10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (startFlag(mSpanFlags[wfound]) == PARAGRAPH) 10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print("< "); 10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print("[ "); 10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (found == 2) { 10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (endFlag(mSpanFlags[wfound]) == POINT) 10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print(") "); 10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (endFlag(mSpanFlags[wfound]) == PARAGRAPH) 10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print("> "); 10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print("] "); 10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print(" "); 10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print("\n"); 10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project*/ 10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Don't call this yourself -- exists for Canvas to use internally. 10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide} 10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void drawText(Canvas c, int start, int end, 10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float x, float y, Paint p) { 10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkRange("drawText", start, end); 10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end <= mGapStart) { 10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c.drawText(mText, start, end - start, x, y, p); 10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (start >= mGapStart) { 10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c.drawText(mText, start + mGapLength, end - start, x, y, p); 10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char[] buf = TextUtils.obtain(end - start); 10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getChars(start, end, buf, 0); 10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c.drawText(buf, 0, end - start, x, y, p); 10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextUtils.recycle(buf); 10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1059f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt * Don't call this yourself -- exists for Canvas to use internally. 1060f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt * {@hide} 1061f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt */ 1062f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt public void drawTextRun(Canvas c, int start, int end, 1063f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt float x, float y, int flags, Paint p) { 1064f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt checkRange("drawTextRun", start, end); 1065f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt 1066f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt // Assume context requires no more than 8 chars on either side. 1067f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt // This is ample, only decomposed U+FDFA falls into this 1068f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt // category, and no one should put a style break within it 1069f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt // anyway. 1070f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt int cstart = start - 8; 1071f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt if (cstart < 0) { 1072f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt cstart = 0; 1073f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt } 1074f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt int cend = end + 8; 1075f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt int max = length(); 1076f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt if (cend > max) { 1077f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt cend = max; 1078f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt } 1079f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt if (cend <= mGapStart) { 1080f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt c.drawTextRun(mText, start, end - start, x, y, flags, p); 1081f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt } else if (cstart >= mGapStart) { 1082f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt c.drawTextRun(mText, start + mGapLength, end - start, x, y, flags, p); 1083f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt } else { 1084f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt char[] buf = TextUtils.obtain(cend - cstart); 1085f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt getChars(cstart, cend, buf, 0); 1086f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt c.drawTextRun(buf, start - cstart, end - start, x, y, flags, p); 1087f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt TextUtils.recycle(buf); 1088f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt } 1089f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt } 1090f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt 1091f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt /** 10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Don't call this yourself -- exists for Paint to use internally. 10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide} 10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public float measureText(int start, int end, Paint p) { 10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkRange("measureText", start, end); 10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float ret; 10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end <= mGapStart) { 11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = p.measureText(mText, start, end - start); 11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (start >= mGapStart) { 11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = p.measureText(mText, start + mGapLength, end - start); 11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char[] buf = TextUtils.obtain(end - start); 11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getChars(start, end, buf, 0); 11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = p.measureText(buf, 0, end - start); 11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextUtils.recycle(buf); 11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret; 11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Don't call this yourself -- exists for Paint to use internally. 11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide} 11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getTextWidths(int start, int end, float[] widths, Paint p) { 11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkRange("getTextWidths", start, end); 11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ret; 11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end <= mGapStart) { 11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = p.getTextWidths(mText, start, end - start, widths); 11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (start >= mGapStart) { 11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = p.getTextWidths(mText, start + mGapLength, end - start, 11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project widths); 11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char[] buf = TextUtils.obtain(end - start); 11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getChars(start, end, buf, 0); 11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = p.getTextWidths(buf, 0, end - start, widths); 11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextUtils.recycle(buf); 11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret; 11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setFilters(InputFilter[] filters) { 11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (filters == null) { 11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException(); 11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFilters = filters; 11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public InputFilter[] getFilters() { 11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mFilters; 11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final InputFilter[] NO_FILTERS = new InputFilter[0]; 11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private InputFilter[] mFilters = NO_FILTERS; 11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private char[] mText; 11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mGapStart; 11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mGapLength; 11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Object[] mSpans; 11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int[] mSpanStarts; 11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int[] mSpanEnds; 11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int[] mSpanFlags; 11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mSpanCount; 11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int MARK = 1; 11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int POINT = 2; 11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int PARAGRAPH = 3; 11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int START_MASK = 0xF0; 11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int END_MASK = 0x0F; 11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int START_SHIFT = 4; 11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1175