@@ -262,19 +262,8 @@ public SpannableStringBuilder append(char text) {
262262 return append (String .valueOf (text ));
263263 }
264264
265- private int change (int start , int end , CharSequence tb , int tbstart , int tbend ) {
266- return change (true , start , end , tb , tbstart , tbend );
267- }
268-
269- private int change (boolean notify , int start , int end ,
270- CharSequence tb , int tbstart , int tbend ) {
265+ private void change (int start , int end , CharSequence tb , int tbstart , int tbend ) {
271266 checkRange ("replace" , start , end );
272- int ret = tbend - tbstart ;
273- TextWatcher [] recipients = null ;
274-
275- if (notify ) {
276- recipients = sendTextWillChange (start , end - start , tbend - tbstart );
277- }
278267
279268 for (int i = mSpanCount - 1 ; i >= 0 ; i --) {
280269 if ((mSpanFlags [i ] & SPAN_PARAGRAPH ) == SPAN_PARAGRAPH ) {
@@ -338,59 +327,45 @@ private int change(boolean notify, int start, int end,
338327 en = tbend ;
339328
340329 if (getSpanStart (spans [i ]) < 0 ) {
341- setSpan (true , spans [i ],
330+ setSpan (false , spans [i ],
342331 st - tbstart + start ,
343332 en - tbstart + start ,
344333 sp .getSpanFlags (spans [i ]));
345334 }
346335 }
347336 }
348337
349- // no need for span fixup on pure insertion
350- if (tbend > tbstart && end - start == 0 ) {
351- if (notify ) {
352- sendTextChange (recipients , start , end - start , tbend - tbstart );
353- sendTextHasChanged (recipients );
354- }
355-
356- return ret ;
357- }
358-
359- boolean atend = (mGapStart + mGapLength == mText .length );
338+ if (end > start ) {
339+ // no need for span fixup on pure insertion
340+ boolean atEnd = (mGapStart + mGapLength == mText .length );
360341
361- for (int i = mSpanCount - 1 ; i >= 0 ; i --) {
362- if (mSpanStarts [i ] >= start &&
363- mSpanStarts [i ] < mGapStart + mGapLength ) {
364- int flag = (mSpanFlags [i ] & START_MASK ) >> START_SHIFT ;
342+ for (int i = mSpanCount - 1 ; i >= 0 ; i --) {
343+ if (mSpanStarts [i ] >= start &&
344+ mSpanStarts [i ] < mGapStart + mGapLength ) {
345+ int flag = (mSpanFlags [i ] & START_MASK ) >> START_SHIFT ;
365346
366- if (flag == POINT || (flag == PARAGRAPH && atend ))
347+ if (flag == POINT || (flag == PARAGRAPH && atEnd ))
367348 mSpanStarts [i ] = mGapStart + mGapLength ;
368349 else
369350 mSpanStarts [i ] = start ;
370- }
351+ }
371352
372- if (mSpanEnds [i ] >= start &&
373- mSpanEnds [i ] < mGapStart + mGapLength ) {
374- int flag = (mSpanFlags [i ] & END_MASK );
353+ if (mSpanEnds [i ] >= start &&
354+ mSpanEnds [i ] < mGapStart + mGapLength ) {
355+ int flag = (mSpanFlags [i ] & END_MASK );
375356
376- if (flag == POINT || (flag == PARAGRAPH && atend ))
377- mSpanEnds [i ] = mGapStart + mGapLength ;
378- else
379- mSpanEnds [i ] = start ;
380- }
357+ if (flag == POINT || (flag == PARAGRAPH && atEnd ))
358+ mSpanEnds [i ] = mGapStart + mGapLength ;
359+ else
360+ mSpanEnds [i ] = start ;
361+ }
381362
382- // remove 0-length SPAN_EXCLUSIVE_EXCLUSIVE
383- if (mSpanEnds [i ] < mSpanStarts [i ]) {
384- removeSpan (i );
363+ // remove 0-length SPAN_EXCLUSIVE_EXCLUSIVE
364+ if (mSpanEnds [i ] < mSpanStarts [i ]) {
365+ removeSpan (i );
366+ }
385367 }
386368 }
387-
388- if (notify ) {
389- sendTextChange (recipients , start , end - start , tbend - tbstart );
390- sendTextHasChanged (recipients );
391- }
392-
393- return ret ;
394369 }
395370
396371 private void removeSpan (int i ) {
@@ -425,8 +400,7 @@ public SpannableStringBuilder replace(final int start, final int end,
425400 CharSequence tb , int tbstart , int tbend ) {
426401 int filtercount = mFilters .length ;
427402 for (int i = 0 ; i < filtercount ; i ++) {
428- CharSequence repl = mFilters [i ].filter (tb , tbstart , tbend ,
429- this , start , end );
403+ CharSequence repl = mFilters [i ].filter (tb , tbstart , tbend , this , start , end );
430404
431405 if (repl != null ) {
432406 tb = repl ;
@@ -435,11 +409,17 @@ public SpannableStringBuilder replace(final int start, final int end,
435409 }
436410 }
437411
438- if (end == start && tbstart == tbend ) {
412+ final int origLen = end - start ;
413+ final int newLen = tbend - tbstart ;
414+
415+ if (origLen == 0 && newLen == 0 ) {
439416 return this ;
440417 }
441418
442- if (end == start || tbstart == tbend ) {
419+ TextWatcher [] textWatchers = getSpans (start , start + origLen , TextWatcher .class );
420+ sendBeforeTextChanged (textWatchers , start , origLen , newLen );
421+
422+ if (origLen == 0 || newLen == 0 ) {
443423 change (start , end , tb , tbstart , tbend );
444424 } else {
445425 int selstart = Selection .getSelectionStart (this );
@@ -450,11 +430,6 @@ public SpannableStringBuilder replace(final int start, final int end,
450430
451431 checkRange ("replace" , start , end );
452432 moveGapTo (end );
453- TextWatcher [] recipients ;
454-
455- int origlen = end - start ;
456-
457- recipients = sendTextWillChange (start , origlen , tbend - tbstart );
458433
459434 if (mGapLength < 2 )
460435 resizeFor (length () + 1 );
@@ -475,9 +450,9 @@ public SpannableStringBuilder replace(final int start, final int end,
475450 new Exception ("mGapLength < 1" ).printStackTrace ();
476451 }
477452
478- int inserted = change (false , start + 1 , start + 1 , tb , tbstart , tbend );
479- change (false , start , start + 1 , "" , 0 , 0 );
480- change (false , start + inserted , start + inserted + origlen , "" , 0 , 0 );
453+ change (start + 1 , start + 1 , tb , tbstart , tbend );
454+ change (start , start + 1 , "" , 0 , 0 );
455+ change (start + newLen , start + newLen + origLen , "" , 0 , 0 );
481456
482457 /*
483458 * Special case to keep the cursor in the same position
@@ -490,7 +465,7 @@ public SpannableStringBuilder replace(final int start, final int end,
490465 if (selstart > start && selstart < end ) {
491466 long off = selstart - start ;
492467
493- off = off * inserted / (end - start );
468+ off = off * newLen / (end - start );
494469 selstart = (int ) off + start ;
495470
496471 setSpan (false , Selection .SELECTION_START , selstart , selstart ,
@@ -499,15 +474,16 @@ public SpannableStringBuilder replace(final int start, final int end,
499474 if (selend > start && selend < end ) {
500475 long off = selend - start ;
501476
502- off = off * inserted / (end - start );
477+ off = off * newLen / (end - start );
503478 selend = (int ) off + start ;
504479
505480 setSpan (false , Selection .SELECTION_END , selend , selend , Spanned .SPAN_POINT_POINT );
506481 }
507- sendTextChange (recipients , start , origlen , inserted );
508- sendTextHasChanged (recipients );
509482 }
510483
484+ sendTextChanged (textWatchers , start , origLen , newLen );
485+ sendAfterTextChanged (textWatchers );
486+
511487 return this ;
512488 }
513489
@@ -872,30 +848,27 @@ public String substring(int start, int end) {
872848 return new String (buf );
873849 }
874850
875- private TextWatcher [] sendTextWillChange (int start , int before , int after ) {
876- TextWatcher [] recip = getSpans (start , start + before , TextWatcher .class );
877- int n = recip .length ;
851+ private void sendBeforeTextChanged (TextWatcher [] watchers , int start , int before , int after ) {
852+ int n = watchers .length ;
878853
879854 for (int i = 0 ; i < n ; i ++) {
880- recip [i ].beforeTextChanged (this , start , before , after );
855+ watchers [i ].beforeTextChanged (this , start , before , after );
881856 }
882-
883- return recip ;
884857 }
885858
886- private void sendTextChange (TextWatcher [] recip , int start , int before , int after ) {
887- int n = recip .length ;
859+ private void sendTextChanged (TextWatcher [] watchers , int start , int before , int after ) {
860+ int n = watchers .length ;
888861
889862 for (int i = 0 ; i < n ; i ++) {
890- recip [i ].onTextChanged (this , start , before , after );
863+ watchers [i ].onTextChanged (this , start , before , after );
891864 }
892865 }
893866
894- private void sendTextHasChanged (TextWatcher [] recip ) {
895- int n = recip .length ;
867+ private void sendAfterTextChanged (TextWatcher [] watchers ) {
868+ int n = watchers .length ;
896869
897870 for (int i = 0 ; i < n ; i ++) {
898- recip [i ].afterTextChanged (this );
871+ watchers [i ].afterTextChanged (this );
899872 }
900873 }
901874
@@ -1037,8 +1010,7 @@ public void dump() { // XXX
10371010 * Don't call this yourself -- exists for Canvas to use internally.
10381011 * {@hide}
10391012 */
1040- public void drawText (Canvas c , int start , int end ,
1041- float x , float y , Paint p ) {
1013+ public void drawText (Canvas c , int start , int end , float x , float y , Paint p ) {
10421014 checkRange ("drawText" , start , end );
10431015
10441016 if (end <= mGapStart ) {
@@ -1059,8 +1031,7 @@ public void drawText(Canvas c, int start, int end,
10591031 * Don't call this yourself -- exists for Canvas to use internally.
10601032 * {@hide}
10611033 */
1062- public void drawTextRun (Canvas c , int start , int end ,
1063- int contextStart , int contextEnd ,
1034+ public void drawTextRun (Canvas c , int start , int end , int contextStart , int contextEnd ,
10641035 float x , float y , int flags , Paint p ) {
10651036 checkRange ("drawTextRun" , start , end );
10661037
@@ -1262,6 +1233,7 @@ public InputFilter[] getFilters() {
12621233 private int [] mSpanFlags ;
12631234 private int mSpanCount ;
12641235
1236+ // TODO These value are tightly related to the public SPAN_MARK/POINT values in {@link Spanned}
12651237 private static final int POINT = 2 ;
12661238 private static final int PARAGRAPH = 3 ;
12671239
0 commit comments