SpannableStringBuilder.java revision 174c44c6cfeead714bb180d21332e712e8b0bbd8
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.text; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Canvas; 20f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Feltimport android.graphics.Paint; 2134ec2b54da52eeed39d9cf9e5f215650b447edd7Gilles Debunneimport android.util.Log; 226435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne 236435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunneimport com.android.internal.util.ArrayUtils; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.reflect.Array; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This is the class for text whose content and markup can both be changed. 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 306435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunnepublic class SpannableStringBuilder implements CharSequence, GetChars, Spannable, Editable, 316435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne Appendable, GraphicsOperations { 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a new SpannableStringBuilder with empty contents 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannableStringBuilder() { 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(""); 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a new SpannableStringBuilder containing a copy of the 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * specified text, including its spans if any. 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannableStringBuilder(CharSequence text) { 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(text, 0, text.length()); 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a new SpannableStringBuilder containing a copy of the 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * specified slice of the specified text, including its spans if any. 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannableStringBuilder(CharSequence text, int start, int end) { 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int srclen = end - start; 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 540249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne if (srclen < 0) throw new StringIndexOutOfBoundsException(); 550249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = ArrayUtils.idealCharArraySize(srclen + 1); 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mText = new char[len]; 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGapStart = srclen; 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGapLength = len - srclen; 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextUtils.getChars(text, start, end, mText, 0); 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanCount = 0; 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int alloc = ArrayUtils.idealIntArraySize(0); 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpans = new Object[alloc]; 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanStarts = new int[alloc]; 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanEnds = new int[alloc]; 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanFlags = new int[alloc]; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (text instanceof Spanned) { 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spanned sp = (Spanned) text; 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] spans = sp.getSpans(start, end, Object.class); 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < spans.length; i++) { 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spans[i] instanceof NoCopySpan) { 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 78174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int st = sp.getSpanStart(spans[i]) - start; 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int en = sp.getSpanEnd(spans[i]) - start; 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fl = sp.getSpanFlags(spans[i]); 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (st < 0) 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project st = 0; 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (st > end - start) 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project st = end - start; 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (en < 0) 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project en = 0; 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (en > end - start) 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project en = end - start; 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 930249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne setSpan(false, spans[i], st, en, fl); 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static SpannableStringBuilder valueOf(CharSequence source) { 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (source instanceof SpannableStringBuilder) { 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (SpannableStringBuilder) source; 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new SpannableStringBuilder(source); 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the char at the specified offset within the buffer. 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public char charAt(int where) { 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = length(); 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (where < 0) { 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IndexOutOfBoundsException("charAt: " + where + " < 0"); 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (where >= len) { 1146435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne throw new IndexOutOfBoundsException("charAt: " + where + " >= 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) { 1317c5f670bd698c984dcafea8125f4d3939bc42972Gilles Debunne final int oldLength = mText.length; 1327c5f670bd698c984dcafea8125f4d3939bc42972Gilles Debunne final int newLength = ArrayUtils.idealCharArraySize(size + 1); 1337c5f670bd698c984dcafea8125f4d3939bc42972Gilles Debunne final int after = oldLength - (mGapStart + mGapLength); 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1357c5f670bd698c984dcafea8125f4d3939bc42972Gilles Debunne char[] newText = new char[newLength]; 1367c5f670bd698c984dcafea8125f4d3939bc42972Gilles Debunne System.arraycopy(mText, 0, newText, 0, mGapStart); 1377c5f670bd698c984dcafea8125f4d3939bc42972Gilles Debunne System.arraycopy(mText, oldLength - after, newText, newLength - after, after); 1387c5f670bd698c984dcafea8125f4d3939bc42972Gilles Debunne mText = newText; 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1407c5f670bd698c984dcafea8125f4d3939bc42972Gilles Debunne final int delta = newLength - oldLength; 1417c5f670bd698c984dcafea8125f4d3939bc42972Gilles Debunne mGapLength += delta; 1427c5f670bd698c984dcafea8125f4d3939bc42972Gilles Debunne if (mGapLength < 1) 1437c5f670bd698c984dcafea8125f4d3939bc42972Gilles Debunne new Exception("mGapLength < 1").printStackTrace(); 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < mSpanCount; i++) { 1467c5f670bd698c984dcafea8125f4d3939bc42972Gilles Debunne if (mSpanStarts[i] > mGapStart) mSpanStarts[i] += delta; 1477c5f670bd698c984dcafea8125f4d3939bc42972Gilles Debunne if (mSpanEnds[i] > mGapStart) mSpanEnds[i] += delta; 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void moveGapTo(int where) { 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (where == mGapStart) 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1550249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne boolean atEnd = (where == length()); 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (where < mGapStart) { 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int overlap = mGapStart - where; 1597c5f670bd698c984dcafea8125f4d3939bc42972Gilles Debunne System.arraycopy(mText, where, mText, mGapStart + mGapLength - overlap, overlap); 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else /* where > mGapStart */ { 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int overlap = where - mGapStart; 1627c5f670bd698c984dcafea8125f4d3939bc42972Gilles Debunne System.arraycopy(mText, where + mGapLength - overlap, mText, mGapStart, overlap); 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // XXX be more clever 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < mSpanCount; i++) { 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int start = mSpanStarts[i]; 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int end = mSpanEnds[i]; 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (start > mGapStart) 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start -= mGapLength; 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (start > where) 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start += mGapLength; 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else if (start == where) { 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int flag = (mSpanFlags[i] & START_MASK) >> START_SHIFT; 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1770249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne if (flag == POINT || (atEnd && flag == PARAGRAPH)) 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start += mGapLength; 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end > mGapStart) 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end -= mGapLength; 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end > where) 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end += mGapLength; 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else if (end == where) { 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int flag = (mSpanFlags[i] & END_MASK); 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1880249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne if (flag == POINT || (atEnd && flag == PARAGRAPH)) 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end += mGapLength; 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanStarts[i] = start; 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanEnds[i] = end; 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGapStart = where; 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannableStringBuilder insert(int where, CharSequence tb, int start, int end) { 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return replace(where, where, tb, start, end); 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannableStringBuilder insert(int where, CharSequence tb) { 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return replace(where, where, tb, 0, tb.length()); 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannableStringBuilder delete(int start, int end) { 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SpannableStringBuilder ret = replace(start, end, "", 0, 0); 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mGapLength > 2 * length()) 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project resizeFor(length()); 215174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret; // == this 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void clear() { 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project replace(0, length(), "", 0, 0); 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 223174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void clearSpans() { 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = mSpanCount - 1; i >= 0; i--) { 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object what = mSpans[i]; 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ostart = mSpanStarts[i]; 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int oend = mSpanEnds[i]; 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ostart > mGapStart) 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ostart -= mGapLength; 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (oend > mGapStart) 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project oend -= mGapLength; 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanCount = i; 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpans[i] = null; 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sendSpanRemoved(what, ostart, oend); 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannableStringBuilder append(CharSequence text) { 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int length = length(); 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return replace(length, length, text, 0, text.length()); 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannableStringBuilder append(CharSequence text, int start, int end) { 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int length = length(); 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return replace(length, length, text, start, end); 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannableStringBuilder append(char text) { 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return append(String.valueOf(text)); 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 260174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne private void change(int start, int end, CharSequence cs, int csStart, int csEnd) { 261174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne // Can be negative 262174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne final int nbNewChars = (csEnd - csStart) - (end - start); 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = mSpanCount - 1; i >= 0; i--) { 265174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne int spanStart = mSpanStarts[i]; 266174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne if (spanStart > mGapStart) 267174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne spanStart -= mGapLength; 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 269174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne int spanEnd = mSpanEnds[i]; 270174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne if (spanEnd > mGapStart) 271174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne spanEnd -= mGapLength; 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 273174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne if ((mSpanFlags[i] & SPAN_PARAGRAPH) == SPAN_PARAGRAPH) { 274174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne int ost = spanStart; 275174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne int oen = spanEnd; 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int clen = length(); 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 278174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne if (spanStart > start && spanStart <= end) { 279174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne for (spanStart = end; spanStart < clen; spanStart++) 280174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne if (spanStart > end && charAt(spanStart - 1) == '\n') 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 284174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne if (spanEnd > start && spanEnd <= end) { 285174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne for (spanEnd = end; spanEnd < clen; spanEnd++) 286174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne if (spanEnd > end && charAt(spanEnd - 1) == '\n') 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 290174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne if (spanStart != ost || spanEnd != oen) 291174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne setSpan(false, mSpans[i], spanStart, spanEnd, mSpanFlags[i]); 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 293174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne 294174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne int flags = 0; 295174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne if (spanStart == start) flags |= SPAN_START_AT_START; 296174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne else if (spanStart == end + nbNewChars) flags |= SPAN_START_AT_END; 297174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne if (spanEnd == start) flags |= SPAN_END_AT_START; 298174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne else if (spanEnd == end + nbNewChars) flags |= SPAN_END_AT_END; 299174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne mSpanFlags[i] |= flags; 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project moveGapTo(end); 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 304312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne if (nbNewChars >= mGapLength) { 305312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne resizeFor(mText.length + nbNewChars - mGapLength); 306312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne } 307312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne 308312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne mGapStart += nbNewChars; 309312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne mGapLength -= nbNewChars; 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mGapLength < 1) 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new Exception("mGapLength < 1").printStackTrace(); 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 314174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne TextUtils.getChars(cs, csStart, csEnd, mText, start); 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 316b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne if (end > start) { 317b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne // no need for span fixup on pure insertion 318b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne boolean atEnd = (mGapStart + mGapLength == mText.length); 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 320b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne for (int i = mSpanCount - 1; i >= 0; i--) { 3217c5f670bd698c984dcafea8125f4d3939bc42972Gilles Debunne if (mSpanStarts[i] >= start && mSpanStarts[i] < mGapStart + mGapLength) { 322b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne int flag = (mSpanFlags[i] & START_MASK) >> START_SHIFT; 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3247c5f670bd698c984dcafea8125f4d3939bc42972Gilles Debunne if (flag == POINT || (flag == PARAGRAPH && atEnd)) { 3257c5f670bd698c984dcafea8125f4d3939bc42972Gilles Debunne mSpanStarts[i] = mGapStart + mGapLength; 3267c5f670bd698c984dcafea8125f4d3939bc42972Gilles Debunne } else { 3277c5f670bd698c984dcafea8125f4d3939bc42972Gilles Debunne mSpanStarts[i] = start; 3287c5f670bd698c984dcafea8125f4d3939bc42972Gilles Debunne } 329b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne } 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3317c5f670bd698c984dcafea8125f4d3939bc42972Gilles Debunne if (mSpanEnds[i] >= start && mSpanEnds[i] < mGapStart + mGapLength) { 332b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne int flag = (mSpanFlags[i] & END_MASK); 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 334b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne if (flag == POINT || (flag == PARAGRAPH && atEnd)) 335b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne mSpanEnds[i] = mGapStart + mGapLength; 336b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne else 337b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne mSpanEnds[i] = start; 338b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne } 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3407c5f670bd698c984dcafea8125f4d3939bc42972Gilles Debunne // remove 0-length SPAN_EXCLUSIVE_EXCLUSIVE, which are POINT_MARK and could 3417c5f670bd698c984dcafea8125f4d3939bc42972Gilles Debunne // get their boundaries swapped by the above code 342b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne if (mSpanEnds[i] < mSpanStarts[i]) { 343b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne removeSpan(i); 344b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne } 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3470249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne 348174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne mSpanCountBeforeAdd = mSpanCount; 349174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne 350174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne if (cs instanceof Spanned) { 351174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne Spanned sp = (Spanned) cs; 352174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne Object[] spans = sp.getSpans(csStart, csEnd, Object.class); 3530249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne 3540249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne for (int i = 0; i < spans.length; i++) { 3550249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne int st = sp.getSpanStart(spans[i]); 3560249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne int en = sp.getSpanEnd(spans[i]); 3570249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne 358174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne if (st < csStart) st = csStart; 359174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne if (en > csEnd) en = csEnd; 3600249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne 3610249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne // Add span only if this object is not yet used as a span in this string 362174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne if (getSpanStart(spans[i]) < 0 && !(spans[i] instanceof SpanWatcher)) { 363174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne setSpan(false, spans[i], st - csStart + start, en - csStart + start, 364174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne sp.getSpanFlags(spans[i])); 3650249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne } 3660249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne } 3670249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne } 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 37075beb336f4b164c3bed5d4b91f0b9c6ea49a3437Gilles Debunne private void removeSpan(int i) { 3716435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne Object object = mSpans[i]; 3726435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne 3736435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne int start = mSpanStarts[i]; 3746435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne int end = mSpanEnds[i]; 3756435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne 3766435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne if (start > mGapStart) start -= mGapLength; 3776435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne if (end > mGapStart) end -= mGapLength; 3786435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne 3796435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne int count = mSpanCount - (i + 1); 3806435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne System.arraycopy(mSpans, i + 1, mSpans, i, count); 3816435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne System.arraycopy(mSpanStarts, i + 1, mSpanStarts, i, count); 3826435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne System.arraycopy(mSpanEnds, i + 1, mSpanEnds, i, count); 3836435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne System.arraycopy(mSpanFlags, i + 1, mSpanFlags, i, count); 38475beb336f4b164c3bed5d4b91f0b9c6ea49a3437Gilles Debunne 38575beb336f4b164c3bed5d4b91f0b9c6ea49a3437Gilles Debunne mSpanCount--; 3866435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne 3876435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne mSpans[mSpanCount] = null; 3886435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne 3896435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne sendSpanRemoved(object, start, end); 39075beb336f4b164c3bed5d4b91f0b9c6ea49a3437Gilles Debunne } 39175beb336f4b164c3bed5d4b91f0b9c6ea49a3437Gilles Debunne 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannableStringBuilder replace(int start, int end, CharSequence tb) { 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return replace(start, end, tb, 0, tb.length()); 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SpannableStringBuilder replace(final int start, final int end, 3990249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne CharSequence tb, int tbstart, int tbend) { 400174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne checkRange("replace", start, end); 401174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int filtercount = mFilters.length; 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < filtercount; i++) { 404b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne CharSequence repl = mFilters[i].filter(tb, tbstart, tbend, this, start, end); 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (repl != null) { 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tb = repl; 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tbstart = 0; 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tbend = repl.length(); 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 413b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne final int origLen = end - start; 414b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne final int newLen = tbend - tbstart; 415b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne 416b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne TextWatcher[] textWatchers = getSpans(start, start + origLen, TextWatcher.class); 417b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne sendBeforeTextChanged(textWatchers, start, origLen, newLen); 418b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne 4190249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne // Try to keep the cursor / selection at the same relative position during 4200249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne // a text replacement. If replaced or replacement text length is zero, this 4210249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne // is already taken care of. 4220249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne boolean adjustSelection = origLen != 0 && newLen != 0; 423174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne int selectionStart = 0; 424174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne int selectionEnd = 0; 4250249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne if (adjustSelection) { 426174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne selectionStart = Selection.getSelectionStart(this); 427174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne selectionEnd = Selection.getSelectionEnd(this); 4280249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne } 429bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne 4300249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne change(start, end, tb, tbstart, tbend); 431bc6862300fe5675addfe4ed5d0c7c345aad463aaGilles Debunne 4320249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne if (adjustSelection) { 433174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne if (selectionStart > start && selectionStart < end) { 434174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne final int offset = (selectionStart - start) * newLen / origLen; 435174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne selectionStart = start + offset; 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 437174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne setSpan(false, Selection.SELECTION_START, selectionStart, selectionStart, 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Spanned.SPAN_POINT_POINT); 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 440174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne if (selectionEnd > start && selectionEnd < end) { 441174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne final int offset = (selectionEnd - start) * newLen / origLen; 442174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne selectionEnd = start + offset; 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 444174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne setSpan(false, Selection.SELECTION_END, selectionEnd, selectionEnd, 445174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne Spanned.SPAN_POINT_POINT); 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4486435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne 449b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne sendTextChanged(textWatchers, start, origLen, newLen); 450b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne sendAfterTextChanged(textWatchers); 451b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne 452174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne // Span watchers need to be called after text watchers, which may update the layout 453174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne sendToSpanWatchers(start, end, newLen - origLen); 454174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return this; 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 458174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne private void sendToSpanWatchers(int replaceStart, int replaceEnd, int nbNewChars) { 459174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne for (int i = 0; i < mSpanCountBeforeAdd; i++) { 460174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne int spanStart = mSpanStarts[i]; 461174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne int spanEnd = mSpanEnds[i]; 462174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne if (spanStart > mGapStart) spanStart -= mGapLength; 463174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne if (spanEnd > mGapStart) spanEnd -= mGapLength; 464174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne int spanFlags = mSpanFlags[i]; 465174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne 466174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne int newReplaceEnd = replaceEnd + nbNewChars; 467174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne boolean spanChanged = false; 468174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne int previousSpanStart = spanStart; 469174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne if (spanStart > newReplaceEnd) { 470174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne if (nbNewChars != 0) { 471174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne previousSpanStart -= nbNewChars; 472174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne spanChanged = true; 473174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne } 474174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne } else if (spanStart >= replaceStart) { 475174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne // No change if span start was already at replace interval boundaries before replace 476174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne if ((spanStart != replaceStart || 477174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne ((spanFlags & SPAN_START_AT_START) != SPAN_START_AT_START)) && 478174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne (spanStart != newReplaceEnd || 479174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne ((spanFlags & SPAN_START_AT_END) != SPAN_START_AT_END))) { 480174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne // TODO previousSpanStart is incorrect, but we would need to save all the 481174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne // previous spans' positions before replace to provide it 482174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne spanChanged = true; 483174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne } 484174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne } 485174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne int previousSpanEnd = spanEnd; 486174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne if (spanEnd > newReplaceEnd) { 487174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne if (nbNewChars != 0) { 488174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne previousSpanEnd -= nbNewChars; 489174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne spanChanged = true; 490174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne } 491174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne } else if (spanEnd >= replaceStart) { 492174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne // No change if span start was already at replace interval boundaries before replace 493174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne if ((spanEnd != replaceStart || 494174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne ((spanFlags & SPAN_END_AT_START) != SPAN_END_AT_START)) && 495174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne (spanEnd != newReplaceEnd || 496174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne ((spanFlags & SPAN_END_AT_END) != SPAN_END_AT_END))) { 497174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne // TODO same as above for previousSpanEnd 498174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne spanChanged = true; 499174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne } 500174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne } 501174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne 502174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne if (spanChanged) { 503174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne sendSpanChanged(mSpans[i], previousSpanStart, previousSpanEnd, spanStart, spanEnd); 504174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne } 505174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne mSpanFlags[i] &= ~SPAN_START_END_MASK; 506174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne } 507174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne 508174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne // The spans starting at mIntermediateSpanCount were added from the replacement text 509174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne for (int i = mSpanCountBeforeAdd; i < mSpanCount; i++) { 510174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne int spanStart = mSpanStarts[i]; 511174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne int spanEnd = mSpanEnds[i]; 512174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne if (spanStart > mGapStart) spanStart -= mGapLength; 513174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne if (spanEnd > mGapStart) spanEnd -= mGapLength; 514174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne sendSpanAdded(mSpans[i], spanStart, spanEnd); 515174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne } 516174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne } 517174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Mark the specified range of text with the specified object. 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The flags determine how the span will behave when text is 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * inserted at the start or end of the span's range. 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setSpan(Object what, int start, int end, int flags) { 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSpan(true, what, start, end, flags); 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5276435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne private void setSpan(boolean send, Object what, int start, int end, int flags) { 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkRange("setSpan", start, end); 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5300249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne int flagsStart = (flags & START_MASK) >> START_SHIFT; 5310249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne if (flagsStart == PARAGRAPH) { 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (start != 0 && start != length()) { 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char c = charAt(start - 1); 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c != '\n') 5366435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne throw new RuntimeException("PARAGRAPH span must start at paragraph boundary"); 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5400249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne int flagsEnd = flags & END_MASK; 5410249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne if (flagsEnd == PARAGRAPH) { 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end != 0 && end != length()) { 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char c = charAt(end - 1); 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c != '\n') 5466435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne throw new RuntimeException("PARAGRAPH span must end at paragraph boundary"); 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5500249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne // 0-length Spanned.SPAN_EXCLUSIVE_EXCLUSIVE 5510249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne if (flagsStart == POINT && flagsEnd == MARK && start == end) { 55234ec2b54da52eeed39d9cf9e5f215650b447edd7Gilles Debunne if (send) Log.e("SpannableStringBuilder", 55334ec2b54da52eeed39d9cf9e5f215650b447edd7Gilles Debunne "SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length"); 55434ec2b54da52eeed39d9cf9e5f215650b447edd7Gilles Debunne // Silently ignore invalid spans when they are created from this class. 55534ec2b54da52eeed39d9cf9e5f215650b447edd7Gilles Debunne // This avoids the duplication of the above test code before all the 55634ec2b54da52eeed39d9cf9e5f215650b447edd7Gilles Debunne // calls to setSpan that are done in this class 55734ec2b54da52eeed39d9cf9e5f215650b447edd7Gilles Debunne return; 5587c5f670bd698c984dcafea8125f4d3939bc42972Gilles Debunne } 5597c5f670bd698c984dcafea8125f4d3939bc42972Gilles Debunne 5600249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne int nstart = start; 5610249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne int nend = end; 5620249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne 5636435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne if (start > mGapStart) { 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start += mGapLength; 5656435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne } else if (start == mGapStart) { 5660249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne if (flagsStart == POINT || (flagsStart == PARAGRAPH && start == length())) 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start += mGapLength; 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5706435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne if (end > mGapStart) { 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end += mGapLength; 5726435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne } else if (end == mGapStart) { 5730249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne if (flagsEnd == POINT || (flagsEnd == PARAGRAPH && end == length())) 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end += mGapLength; 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = mSpanCount; 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] spans = mSpans; 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spans[i] == what) { 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ostart = mSpanStarts[i]; 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int oend = mSpanEnds[i]; 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ostart > mGapStart) 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ostart -= mGapLength; 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (oend > mGapStart) 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project oend -= mGapLength; 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanStarts[i] = start; 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanEnds[i] = end; 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanFlags[i] = flags; 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 594fc1190b8f143bd00c825d4e52928c577e40e6c49Gilles Debunne if (send) sendSpanChanged(what, ostart, oend, nstart, nend); 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSpanCount + 1 >= mSpans.length) { 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int newsize = ArrayUtils.idealIntArraySize(mSpanCount + 1); 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] newspans = new Object[newsize]; 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] newspanstarts = new int[newsize]; 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] newspanends = new int[newsize]; 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] newspanflags = new int[newsize]; 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mSpans, 0, newspans, 0, mSpanCount); 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mSpanStarts, 0, newspanstarts, 0, mSpanCount); 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mSpanEnds, 0, newspanends, 0, mSpanCount); 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mSpanFlags, 0, newspanflags, 0, mSpanCount); 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpans = newspans; 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanStarts = newspanstarts; 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanEnds = newspanends; 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanFlags = newspanflags; 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpans[mSpanCount] = what; 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanStarts[mSpanCount] = start; 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanEnds[mSpanCount] = end; 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanFlags[mSpanCount] = flags; 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpanCount++; 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 624fc1190b8f143bd00c825d4e52928c577e40e6c49Gilles Debunne if (send) sendSpanAdded(what, nstart, nend); 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Remove the specified markup object from the buffer. 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void removeSpan(Object what) { 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = mSpanCount - 1; i >= 0; i--) { 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSpans[i] == what) { 6336435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne removeSpan(i); 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the buffer offset of the beginning of the specified 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * markup object, or -1 if it is not attached to this buffer. 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getSpanStart(Object what) { 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = mSpanCount; 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] spans = mSpans; 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = count - 1; i >= 0; i--) { 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spans[i] == what) { 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int where = mSpanStarts[i]; 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (where > mGapStart) 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project where -= mGapLength; 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return where; 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the buffer offset of the end of the specified 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * markup object, or -1 if it is not attached to this buffer. 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getSpanEnd(Object what) { 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = mSpanCount; 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] spans = mSpans; 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = count - 1; i >= 0; i--) { 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spans[i] == what) { 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int where = mSpanEnds[i]; 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (where > mGapStart) 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project where -= mGapLength; 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return where; 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the flags of the end of the specified 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * markup object, or 0 if it is not attached to this buffer. 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getSpanFlags(Object what) { 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = mSpanCount; 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] spans = mSpans; 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = count - 1; i >= 0; i--) { 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spans[i] == what) { 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mSpanFlags[i]; 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return an array of the spans of the specified type that overlap 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the specified range of the buffer. The kind may be Object.class to get 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * a list of all the spans regardless of type. 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 705312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne @SuppressWarnings("unchecked") 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public <T> T[] getSpans(int queryStart, int queryEnd, Class<T> kind) { 7076435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne if (kind == null) return ArrayUtils.emptyArray(kind); 7086435a56a8c02de98befcc8cd743b2b638cffb327Gilles Debunne 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int spanCount = mSpanCount; 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] spans = mSpans; 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] starts = mSpanStarts; 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] ends = mSpanEnds; 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] flags = mSpanFlags; 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int gapstart = mGapStart; 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int gaplen = mGapLength; 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = 0; 718312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne T[] ret = null; 719312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne T ret1 = null; 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < spanCount; i++) { 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int spanStart = starts[i]; 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spanStart > gapstart) { 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project spanStart -= gaplen; 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spanStart > queryEnd) { 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 729b062e81e3a16af43db3619d721aa522c137d1aa9Gilles Debunne 730b062e81e3a16af43db3619d721aa522c137d1aa9Gilles Debunne int spanEnd = ends[i]; 731b062e81e3a16af43db3619d721aa522c137d1aa9Gilles Debunne if (spanEnd > gapstart) { 732b062e81e3a16af43db3619d721aa522c137d1aa9Gilles Debunne spanEnd -= gaplen; 733b062e81e3a16af43db3619d721aa522c137d1aa9Gilles Debunne } 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spanEnd < queryStart) { 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spanStart != spanEnd && queryStart != queryEnd) { 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spanStart == queryEnd) 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (spanEnd == queryStart) 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 745945ee9b1661e60e0074d4f16f61fc147c728c6bfGilles Debunne // Expensive test, should be performed after the previous tests 746945ee9b1661e60e0074d4f16f61fc147c728c6bfGilles Debunne if (!kind.isInstance(spans[i])) continue; 747945ee9b1661e60e0074d4f16f61fc147c728c6bfGilles Debunne 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (count == 0) { 749312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne // Safe conversion thanks to the isInstance test above 750312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne ret1 = (T) spans[i]; 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project count++; 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (count == 1) { 754312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne // Safe conversion, but requires a suppressWarning 755312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne ret = (T[]) Array.newInstance(kind, spanCount - i + 1); 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret[0] = ret1; 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int prio = flags[i] & SPAN_PRIORITY; 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (prio != 0) { 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int j; 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (j = 0; j < count; j++) { 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int p = getSpanFlags(ret[j]) & SPAN_PRIORITY; 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (prio > p) { 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(ret, j, ret, j + 1, count - j); 772312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne // Safe conversion thanks to the isInstance test above 773312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne ret[j] = (T) spans[i]; 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project count++; 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 776312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne // Safe conversion thanks to the isInstance test above 777312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne ret[count++] = (T) spans[i]; 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (count == 0) { 783f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt return ArrayUtils.emptyArray(kind); 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (count == 1) { 786312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne // Safe conversion, but requires a suppressWarning 787312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne ret = (T[]) Array.newInstance(kind, 1); 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret[0] = ret1; 789312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne return ret; 7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (count == ret.length) { 792312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne return ret; 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 795312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne // Safe conversion, but requires a suppressWarning 796312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne T[] nret = (T[]) Array.newInstance(kind, count); 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(ret, 0, nret, 0, count); 798312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne return nret; 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return the next offset after <code>start</code> but less than or 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * equal to <code>limit</code> where a span of the specified type 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * begins or ends. 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int nextSpanTransition(int start, int limit, Class kind) { 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = mSpanCount; 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Object[] spans = mSpans; 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] starts = mSpanStarts; 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int[] ends = mSpanEnds; 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int gapstart = mGapStart; 8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int gaplen = mGapLength; 8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (kind == null) { 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project kind = Object.class; 8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int st = starts[i]; 8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int en = ends[i]; 8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (st > gapstart) 8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project st -= gaplen; 8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (en > gapstart) 8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project en -= gaplen; 8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (st > start && st < limit && kind.isInstance(spans[i])) 8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project limit = st; 8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (en > start && en < limit && kind.isInstance(spans[i])) 8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project limit = en; 8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return limit; 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return a new CharSequence containing a copy of the specified 8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * range of this buffer, including the overlapping spans. 8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public CharSequence subSequence(int start, int end) { 8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new SpannableStringBuilder(this, start, end); 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copy the specified range of chars from this buffer into the 8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * specified array, beginning at the specified offset. 8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void getChars(int start, int end, char[] dest, int destoff) { 8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkRange("getChars", start, end); 8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end <= mGapStart) { 8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.arraycopy(mText, start, dest, destoff, end - start); 8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (start >= mGapStart) { 854174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne System.arraycopy(mText, start + mGapLength, 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, 858174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne dest, destoff + (mGapStart - start), 859174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne 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 */ 866312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne @Override 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public String toString() { 8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = length(); 8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char[] buf = new char[len]; 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getChars(0, len, buf, 0); 8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new String(buf); 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 875653d3a27878d5358b4a91518a756f6b9b3407b07Gilles Debunne /** 876653d3a27878d5358b4a91518a756f6b9b3407b07Gilles Debunne * Return a String containing a copy of the chars in this buffer, limited to the 877653d3a27878d5358b4a91518a756f6b9b3407b07Gilles Debunne * [start, end[ range. 878653d3a27878d5358b4a91518a756f6b9b3407b07Gilles Debunne * @hide 879653d3a27878d5358b4a91518a756f6b9b3407b07Gilles Debunne */ 880653d3a27878d5358b4a91518a756f6b9b3407b07Gilles Debunne public String substring(int start, int end) { 881653d3a27878d5358b4a91518a756f6b9b3407b07Gilles Debunne char[] buf = new char[end - start]; 882653d3a27878d5358b4a91518a756f6b9b3407b07Gilles Debunne getChars(start, end, buf, 0); 883653d3a27878d5358b4a91518a756f6b9b3407b07Gilles Debunne return new String(buf); 884653d3a27878d5358b4a91518a756f6b9b3407b07Gilles Debunne } 885653d3a27878d5358b4a91518a756f6b9b3407b07Gilles Debunne 886b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne private void sendBeforeTextChanged(TextWatcher[] watchers, int start, int before, int after) { 887b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne int n = watchers.length; 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < n; i++) { 890b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne watchers[i].beforeTextChanged(this, start, before, after); 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 894b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne private void sendTextChanged(TextWatcher[] watchers, int start, int before, int after) { 895b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne int n = watchers.length; 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < n; i++) { 898b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne watchers[i].onTextChanged(this, start, before, after); 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 902b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne private void sendAfterTextChanged(TextWatcher[] watchers) { 903b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne int n = watchers.length; 9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < n; i++) { 906b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne watchers[i].afterTextChanged(this); 9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void sendSpanAdded(Object what, int start, int end) { 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SpanWatcher[] recip = getSpans(start, end, SpanWatcher.class); 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int n = recip.length; 9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < n; i++) { 9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project recip[i].onSpanAdded(this, what, start, end); 9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void sendSpanRemoved(Object what, int start, int end) { 9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SpanWatcher[] recip = getSpans(start, end, SpanWatcher.class); 9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int n = recip.length; 9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < n; i++) { 9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project recip[i].onSpanRemoved(this, what, start, end); 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 928174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne private void sendSpanChanged(Object what, int oldStart, int oldEnd, int start, int end) { 929174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne // The bounds of a possible SpanWatcher are guaranteed to be set before this method is 930174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne // called, so that the order of the span does not affect this broadcast. 931174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne SpanWatcher[] spanWatchers = getSpans(Math.min(oldStart, start), 932174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne Math.min(Math.max(oldEnd, end), length()), SpanWatcher.class); 933174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne int n = spanWatchers.length; 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < n; i++) { 935174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne spanWatchers[i].onSpanChanged(this, what, oldStart, oldEnd, start, end); 9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static String region(int start, int end) { 9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return "(" + start + " ... " + end + ")"; 9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void checkRange(final String operation, int start, int end) { 9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end < start) { 9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IndexOutOfBoundsException(operation + " " + 946174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne region(start, end) + " has end before start"); 9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = length(); 9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (start > len || end > len) { 9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IndexOutOfBoundsException(operation + " " + 953174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne region(start, end) + " ends beyond length " + len); 9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (start < 0 || end < 0) { 9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IndexOutOfBoundsException(operation + " " + 958174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne region(start, end) + " starts before 0"); 9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 962174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne /* 9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean isprint(char c) { // XXX 9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (c >= ' ' && c <= '~') 9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int startFlag(int flag) { 9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (flag >> 4) & 0x0F; 9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int endFlag(int flag) { 9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return flag & 0x0F; 9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void dump() { // XXX 9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < mGapStart; i++) { 9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print('|'); 9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print(' '); 9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print(isprint(mText[i]) ? mText[i] : '.'); 9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print(' '); 9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = mGapStart; i < mGapStart + mGapLength; i++) { 9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print('|'); 9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print('('); 9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print(isprint(mText[i]) ? mText[i] : '.'); 9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print(')'); 9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = mGapStart + mGapLength; i < mText.length; i++) { 9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print('|'); 9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print(' '); 9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print(isprint(mText[i]) ? mText[i] : '.'); 9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print(' '); 9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print('\n'); 10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < mText.length + 1; i++) { 10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int found = 0; 10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int wfound = 0; 10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int j = 0; j < mSpanCount; j++) { 10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSpanStarts[j] == i) { 10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project found = 1; 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 if (mSpanEnds[j] == i) { 10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project found = 2; 10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project wfound = j; 10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (found == 1) { 10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (startFlag(mSpanFlags[wfound]) == MARK) 10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print("( "); 10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (startFlag(mSpanFlags[wfound]) == PARAGRAPH) 10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print("< "); 10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print("[ "); 10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (found == 2) { 10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (endFlag(mSpanFlags[wfound]) == POINT) 10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print(") "); 10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (endFlag(mSpanFlags[wfound]) == PARAGRAPH) 10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print("> "); 10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print("] "); 10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print(" "); 10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project System.out.print("\n"); 10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1041174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne */ 10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Don't call this yourself -- exists for Canvas to use internally. 10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide} 10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1047b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne public void drawText(Canvas c, int start, int end, float x, float y, Paint p) { 10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkRange("drawText", start, end); 10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end <= mGapStart) { 10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c.drawText(mText, start, end - start, x, y, p); 10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (start >= mGapStart) { 10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c.drawText(mText, start + mGapLength, end - start, x, y, p); 10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char[] buf = TextUtils.obtain(end - start); 10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getChars(start, end, buf, 0); 10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project c.drawText(buf, 0, end - start, x, y, p); 10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextUtils.recycle(buf); 10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10630c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1065f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt * Don't call this yourself -- exists for Canvas to use internally. 1066f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt * {@hide} 1067f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt */ 1068b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne public void drawTextRun(Canvas c, int start, int end, int contextStart, int contextEnd, 10690c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt float x, float y, int flags, Paint p) { 1070f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt checkRange("drawTextRun", start, end); 1071f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt 10720c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt int contextLen = contextEnd - contextStart; 10730c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt int len = end - start; 10740c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt if (contextEnd <= mGapStart) { 10750c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt c.drawTextRun(mText, start, len, contextStart, contextLen, x, y, flags, p); 10760c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt } else if (contextStart >= mGapStart) { 10770c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt c.drawTextRun(mText, start + mGapLength, len, contextStart + mGapLength, 10780c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt contextLen, x, y, flags, p); 1079f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt } else { 10800c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt char[] buf = TextUtils.obtain(contextLen); 10810c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt getChars(contextStart, contextEnd, buf, 0); 10820c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt c.drawTextRun(buf, start - contextStart, len, 0, contextLen, x, y, flags, p); 1083f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt TextUtils.recycle(buf); 1084f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt } 1085f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt } 1086f47d7405bbcb25d7cdf89ebb059f41520fe9ab87Doug Felt 1087174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne /** 10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Don't call this yourself -- exists for Paint to use internally. 10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide} 10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public float measureText(int start, int end, Paint p) { 10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkRange("measureText", start, end); 10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float ret; 10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end <= mGapStart) { 10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = p.measureText(mText, start, end - start); 10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (start >= mGapStart) { 10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = p.measureText(mText, start + mGapLength, end - start); 11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char[] buf = TextUtils.obtain(end - start); 11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getChars(start, end, buf, 0); 11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = p.measureText(buf, 0, end - start); 11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextUtils.recycle(buf); 11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret; 11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Don't call this yourself -- exists for Paint to use internally. 11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide} 11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getTextWidths(int start, int end, float[] widths, Paint p) { 11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkRange("getTextWidths", start, end); 11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ret; 11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end <= mGapStart) { 11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = p.getTextWidths(mText, start, end - start, widths); 11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (start >= mGapStart) { 1123174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne ret = p.getTextWidths(mText, start + mGapLength, end - start, widths); 11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char[] buf = TextUtils.obtain(end - start); 11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getChars(start, end, buf, 0); 11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ret = p.getTextWidths(buf, 0, end - start, widths); 11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TextUtils.recycle(buf); 11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret; 11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11350c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt /** 11360c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt * Don't call this yourself -- exists for Paint to use internally. 11370c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt * {@hide} 11380c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt */ 11390c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt public float getTextRunAdvances(int start, int end, int contextStart, int contextEnd, int flags, 11400c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt float[] advances, int advancesPos, Paint p) { 11410c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 11420c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt float ret; 11430c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 11440c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt int contextLen = contextEnd - contextStart; 11450c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt int len = end - start; 11460c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 11470c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt if (end <= mGapStart) { 11480c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt ret = p.getTextRunAdvances(mText, start, len, contextStart, contextLen, 11490c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt flags, advances, advancesPos); 11500c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt } else if (start >= mGapStart) { 11510c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt ret = p.getTextRunAdvances(mText, start + mGapLength, len, 11520c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt contextStart + mGapLength, contextLen, flags, advances, advancesPos); 11530c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt } else { 11540c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt char[] buf = TextUtils.obtain(contextLen); 11550c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt getChars(contextStart, contextEnd, buf, 0); 11560c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt ret = p.getTextRunAdvances(buf, start - contextStart, len, 11570c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 0, contextLen, flags, advances, advancesPos); 11580c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt TextUtils.recycle(buf); 11590c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt } 11600c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 11610c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt return ret; 11620c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt } 11630c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 1164f09d510cd18854f41632433503ca46cc41362febGilles Debunne /** 1165eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio * Don't call this yourself -- exists for Paint to use internally. 1166eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio * {@hide} 1167eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio */ 11680a1413e4bf9dcda2a8abb2287e43f612a7fb2453Fabrice Di Meglio public float getTextRunAdvances(int start, int end, int contextStart, int contextEnd, int flags, 11690a1413e4bf9dcda2a8abb2287e43f612a7fb2453Fabrice Di Meglio float[] advances, int advancesPos, Paint p, int reserved) { 1170eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio 1171eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio float ret; 1172eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio 1173eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio int contextLen = contextEnd - contextStart; 1174eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio int len = end - start; 1175eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio 1176eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio if (end <= mGapStart) { 11770a1413e4bf9dcda2a8abb2287e43f612a7fb2453Fabrice Di Meglio ret = p.getTextRunAdvances(mText, start, len, contextStart, contextLen, 11780a1413e4bf9dcda2a8abb2287e43f612a7fb2453Fabrice Di Meglio flags, advances, advancesPos, reserved); 1179eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio } else if (start >= mGapStart) { 11800a1413e4bf9dcda2a8abb2287e43f612a7fb2453Fabrice Di Meglio ret = p.getTextRunAdvances(mText, start + mGapLength, len, 11810a1413e4bf9dcda2a8abb2287e43f612a7fb2453Fabrice Di Meglio contextStart + mGapLength, contextLen, flags, advances, advancesPos, reserved); 1182eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio } else { 1183eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio char[] buf = TextUtils.obtain(contextLen); 1184eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio getChars(contextStart, contextEnd, buf, 0); 11850a1413e4bf9dcda2a8abb2287e43f612a7fb2453Fabrice Di Meglio ret = p.getTextRunAdvances(buf, start - contextStart, len, 11860a1413e4bf9dcda2a8abb2287e43f612a7fb2453Fabrice Di Meglio 0, contextLen, flags, advances, advancesPos, reserved); 1187eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio TextUtils.recycle(buf); 1188eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio } 1189eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio 1190eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio return ret; 1191eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio } 1192eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio 1193eee49c699c035ffba188417489f40d34f587d65cFabrice Di Meglio /** 1194f09d510cd18854f41632433503ca46cc41362febGilles Debunne * Returns the next cursor position in the run. This avoids placing the cursor between 1195f09d510cd18854f41632433503ca46cc41362febGilles Debunne * surrogates, between characters that form conjuncts, between base characters and combining 1196f09d510cd18854f41632433503ca46cc41362febGilles Debunne * marks, or within a reordering cluster. 1197f09d510cd18854f41632433503ca46cc41362febGilles Debunne * 1198f09d510cd18854f41632433503ca46cc41362febGilles Debunne * <p>The context is the shaping context for cursor movement, generally the bounds of the metric 1199f09d510cd18854f41632433503ca46cc41362febGilles Debunne * span enclosing the cursor in the direction of movement. 1200f09d510cd18854f41632433503ca46cc41362febGilles Debunne * <code>contextStart</code>, <code>contextEnd</code> and <code>offset</code> are relative to 1201f09d510cd18854f41632433503ca46cc41362febGilles Debunne * the start of the string.</p> 1202f09d510cd18854f41632433503ca46cc41362febGilles Debunne * 1203616f3835a0a67328b378cb1cbc126f17478ab4a0Gilles Debunne * <p>If cursorOpt is CURSOR_AT and the offset is not a valid cursor position, 1204f09d510cd18854f41632433503ca46cc41362febGilles Debunne * this returns -1. Otherwise this will never return a value before contextStart or after 1205f09d510cd18854f41632433503ca46cc41362febGilles Debunne * contextEnd.</p> 1206f09d510cd18854f41632433503ca46cc41362febGilles Debunne * 1207f09d510cd18854f41632433503ca46cc41362febGilles Debunne * @param contextStart the start index of the context 1208f09d510cd18854f41632433503ca46cc41362febGilles Debunne * @param contextEnd the (non-inclusive) end index of the context 1209616f3835a0a67328b378cb1cbc126f17478ab4a0Gilles Debunne * @param flags either DIRECTION_RTL or DIRECTION_LTR 1210f09d510cd18854f41632433503ca46cc41362febGilles Debunne * @param offset the cursor position to move from 1211616f3835a0a67328b378cb1cbc126f17478ab4a0Gilles Debunne * @param cursorOpt how to move the cursor, one of CURSOR_AFTER, 1212616f3835a0a67328b378cb1cbc126f17478ab4a0Gilles Debunne * CURSOR_AT_OR_AFTER, CURSOR_BEFORE, 1213616f3835a0a67328b378cb1cbc126f17478ab4a0Gilles Debunne * CURSOR_AT_OR_BEFORE, or CURSOR_AT 1214f09d510cd18854f41632433503ca46cc41362febGilles Debunne * @param p the Paint object that is requesting this information 1215f09d510cd18854f41632433503ca46cc41362febGilles Debunne * @return the offset of the next position, or -1 1216b0b225602cc84e0602450a417a562e8f53f29c6bGilles Debunne * @deprecated This is an internal method, refrain from using it in your code 1217f09d510cd18854f41632433503ca46cc41362febGilles Debunne */ 1218b0b225602cc84e0602450a417a562e8f53f29c6bGilles Debunne @Deprecated 12190c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt public int getTextRunCursor(int contextStart, int contextEnd, int flags, int offset, 12200c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt int cursorOpt, Paint p) { 12210c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 12220c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt int ret; 12230c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 12240c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt int contextLen = contextEnd - contextStart; 12250c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt if (contextEnd <= mGapStart) { 12260c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt ret = p.getTextRunCursor(mText, contextStart, contextLen, 12270c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt flags, offset, cursorOpt); 12280c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt } else if (contextStart >= mGapStart) { 12290c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt ret = p.getTextRunCursor(mText, contextStart + mGapLength, contextLen, 1230312cd580391d70140eeb4080a4e195039172a6a6Gilles Debunne flags, offset + mGapLength, cursorOpt) - mGapLength; 12310c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt } else { 12320c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt char[] buf = TextUtils.obtain(contextLen); 12330c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt getChars(contextStart, contextEnd, buf, 0); 12340c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt ret = p.getTextRunCursor(buf, 0, contextLen, 12350c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt flags, offset - contextStart, cursorOpt) + contextStart; 12360c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt TextUtils.recycle(buf); 12370c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt } 12380c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 12390c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt return ret; 12400c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt } 12410c702b88c5d0d4380930b920f5be6e66dd95a0d8Doug Felt 12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setFilters(InputFilter[] filters) { 12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (filters == null) { 12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException(); 12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFilters = filters; 12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Documentation from interface 12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public InputFilter[] getFilters() { 12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mFilters; 12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final InputFilter[] NO_FILTERS = new InputFilter[0]; 12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private InputFilter[] mFilters = NO_FILTERS; 12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private char[] mText; 12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mGapStart; 12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mGapLength; 12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Object[] mSpans; 12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int[] mSpanStarts; 12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int[] mSpanEnds; 12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int[] mSpanFlags; 12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mSpanCount; 1268174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne private int mSpanCountBeforeAdd; 12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1270b51036f72aa69e56133fefbf2b56724768423512Gilles Debunne // TODO These value are tightly related to the public SPAN_MARK/POINT values in {@link Spanned} 12710249b43f6ce59bfec104f0fe606d9059244f8797Gilles Debunne private static final int MARK = 1; 12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int POINT = 2; 12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int PARAGRAPH = 3; 12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int START_MASK = 0xF0; 12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int END_MASK = 0x0F; 12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int START_SHIFT = 4; 1278174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne 1279174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne // These bits are not (currently) used by SPANNED flags 1280174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne private static final int SPAN_START_AT_START = 0x1000; 1281174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne private static final int SPAN_START_AT_END = 0x2000; 1282174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne private static final int SPAN_END_AT_START = 0x4000; 1283174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne private static final int SPAN_END_AT_END = 0x8000; 1284174c44c6cfeead714bb180d21332e712e8b0bbd8Gilles Debunne private static final int SPAN_START_END_MASK = 0xF000; 12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1286