Java Code Examples for android.text.Spanned#getSpanStart()

The following examples show how to use android.text.Spanned#getSpanStart() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: ClonedSpannableString.java    From memoir with Apache License 2.0 6 votes vote down vote up
private void init(CharSequence source, int start, int end) {
    int initial = 20;
    mSpans = new Object[initial];
    mSpanData = new int[initial * 3];

    if (source instanceof Spanned) {
        Spanned sp = (Spanned) source;
        for (Object span : sp.getSpans(start, end, Object.class)) {
            if (span instanceof CharacterStyle || span instanceof ParagraphStyle) {
                int st = sp.getSpanStart(span);
                int en = sp.getSpanEnd(span);
                int fl = sp.getSpanFlags(span);

                if (st < start) st = start;
                if (en > end) en = end;

                setSpan(span, st - start, en - start, fl);
            }
        }
    }
}
 
Example 2
Source File: SpannableStringUtils.java    From openboard with GNU General Public License v3.0 6 votes vote down vote up
/**
 * Copies the spans from the region <code>start...end</code> in
 * <code>source</code> to the region
 * <code>destoff...destoff+end-start</code> in <code>dest</code>.
 * Spans in <code>source</code> that begin before <code>start</code>
 * or end after <code>end</code> but overlap this range are trimmed
 * as if they began at <code>start</code> or ended at <code>end</code>.
 * Only SuggestionSpans that don't have the SPAN_PARAGRAPH span are copied.
 *
 * This code is almost entirely taken from {@link TextUtils#copySpansFrom}, except for the
 * kind of span that is copied.
 *
 * @throws IndexOutOfBoundsException if any of the copied spans
 * are out of range in <code>dest</code>.
 */
public static void copyNonParagraphSuggestionSpansFrom(Spanned source, int start, int end,
        Spannable dest, int destoff) {
    Object[] spans = source.getSpans(start, end, SuggestionSpan.class);

    for (int i = 0; i < spans.length; i++) {
        int fl = source.getSpanFlags(spans[i]);
        // We don't care about the PARAGRAPH flag in LatinIME code. However, if this flag
        // is set, Spannable#setSpan will throw an exception unless the span is on the edge
        // of a word. But the spans have been split into two by the getText{Before,After}Cursor
        // methods, so after concatenation they may end in the middle of a word.
        // Since we don't use them, we can just remove them and avoid crashing.
        fl &= ~Spanned.SPAN_PARAGRAPH;

        int st = source.getSpanStart(spans[i]);
        int en = source.getSpanEnd(spans[i]);

        if (st < start)
            st = start;
        if (en > end)
            en = end;

        dest.setSpan(spans[i], st - start + destoff, en - start + destoff,
                     fl);
    }
}
 
Example 3
Source File: ClonedSpannableString.java    From Android-RTEditor with Apache License 2.0 6 votes vote down vote up
private void init(CharSequence source, int start, int end) {
    int initial = 20;
    mSpans = new Object[initial];
    mSpanData = new int[initial * 3];

    if (source instanceof Spanned) {
        Spanned sp = (Spanned) source;
        for (Object span : sp.getSpans(start, end, Object.class)) {
            if (span instanceof CharacterStyle || span instanceof ParagraphStyle) {
                int st = sp.getSpanStart(span);
                int en = sp.getSpanEnd(span);
                int fl = sp.getSpanFlags(span);

                if (st < start) st = start;
                if (en > end) en = end;

                setSpan(span, st - start, en - start, fl);
            }
        }
    }
}
 
Example 4
Source File: DisplayManager.java    From brailleback with Apache License 2.0 6 votes vote down vote up
private static int findCursorPosition(Content content) {
    Spanned spanned = content.getSpanned();
    if (spanned == null) {
        return -1;
    }
    DisplaySpans.SelectionSpan[] selectionSpans =
            spanned.getSpans(0, spanned.length(),
                    DisplaySpans.SelectionSpan.class);
    if (selectionSpans.length > 0) {
        return spanned.getSpanStart(selectionSpans[0]);
    }
    DisplaySpans.FocusSpan[] focusSpans =
            spanned.getSpans(0, spanned.length(),
                    DisplaySpans.FocusSpan.class);
    if (focusSpans.length > 0) {
        return spanned.getSpanStart(focusSpans[0]);
    }
    return -1;
}
 
Example 5
Source File: BulletSpan.java    From memoir with Apache License 2.0 6 votes vote down vote up
@Override
public void drawLeadingMargin(Canvas c, Paint p, int x, int dir, int top, int baseline, int bottom,
                              CharSequence text, int start, int end, boolean first, Layout l) {
    Spanned spanned = (Spanned) text;
    if (!mIgnoreSpan && spanned.getSpanStart(this) == start) {
        // set paint
        Paint.Style oldStyle = p.getStyle();
        p.setStyle(Paint.Style.FILL);

        // draw the bullet point
        int size = Math.max(Math.round((baseline - top) / 9f), 4);
        draw(c, p, x, dir, top, bottom, size);

        // restore paint
        p.setStyle(oldStyle);
    }
}
 
Example 6
Source File: SpoilerSpan.java    From mimi-reader with Apache License 2.0 6 votes vote down vote up
@Override
    public void onClick(View widget) {
//        hidden = !hidden;
//        widget.invalidate();

        if (widget instanceof TextView) {
            TextView tv = (TextView) widget;
            CharSequence text = tv.getText();

            if (text instanceof Spanned) {
                Spanned s = (Spanned) text;
                int start = s.getSpanStart(this);
                int end = s.getSpanEnd(this);

                new MaterialAlertDialogBuilder(widget.getContext())
                        .setTitle(R.string.spoiler)
                        .setMessage(s.subSequence(start, end).toString())
                        .setCancelable(true)
                        .show();
            }
        }
    }
 
Example 7
Source File: ACItemUtils.java    From Nimingban with Apache License 2.0 6 votes vote down vote up
public Spanned update(Spanned spanned, int hideColor) {
    if (spanned.getSpanStart(this) == -1) return spanned;

    ACItemUtils.Text text = new ACItemUtils.Text(spanned);

    BackgroundColorSpan oldHideSpan = updateHideSpan1(hideColor);
    if (oldHideSpan != null) text.removeSpan(oldHideSpan);

    if (hidden) {
        text.setSpan(hideSpan1, start, end);
        text.setSpan(hideSpan2, start, end);
    } else {
        text.removeSpan(hideSpan1);
        text.removeSpan(hideSpan2);
    }

    return text.getText();
}
 
Example 8
Source File: WordTokenizer.java    From Spyglass with Apache License 2.0 6 votes vote down vote up
/**
 * Returns the index of the beginning of the first span after the cursor or
 * length of the text if there are no spans after the cursor.
 *
 * @param text   the {@link Spanned} to examine
 * @param cursor position of the cursor in text
 *
 * @return the furthest behind the cursor to search for the current keywords
 */
protected int getSearchEndIndex(final @NonNull Spanned text, int cursor) {
    if (cursor < 0 || cursor > text.length()) {
        cursor = 0;
    }

    // Get index of the start of the first span after the cursor (or text.length() if does not exist)
    MentionSpan[] spans = text.getSpans(0, text.length(), MentionSpan.class);
    int closestAfterCursor = text.length();
    for (MentionSpan span : spans) {
        int start = text.getSpanStart(span);
        if (start < closestAfterCursor && start >= cursor) {
            closestAfterCursor = start;
        }
    }

    // Get the index of the end of the line
    String textString = text.toString().substring(cursor, text.length());
    int lineEndIndex = text.length();
    if (textString.contains(mConfig.LINE_SEPARATOR)) {
        lineEndIndex = cursor + textString.indexOf(mConfig.LINE_SEPARATOR);
    }

    // Return whichever is closest after the cursor
    return Math.min(closestAfterCursor, lineEndIndex);
}
 
Example 9
Source File: WordToSpan.java    From Android-WordToSpan with MIT License 5 votes vote down vote up
@Override
public void onClick(View textView) {
    Spanned s = (Spanned) tv.getText();
    int start = s.getSpanStart(this);
    int end = s.getSpanEnd(this);
    clickListener.onClick(type, s.subSequence(start, end).toString().trim());
}
 
Example 10
Source File: ConverterSpannedToHtml.java    From Android-RTEditor with Apache License 2.0 5 votes vote down vote up
private void convertText(Spanned text, int start, int end, SortedSet<CharacterStyle> spans) {
    while (start < end) {

        // get first CharacterStyle
        CharacterStyle span = spans.isEmpty() ? null : spans.first();
        int spanStart = span == null ? Integer.MAX_VALUE : text.getSpanStart(span);
        int spanEnd = span == null ? Integer.MAX_VALUE : text.getSpanEnd(span);

        if (start < spanStart) {

            // no paragraph, just plain text
            escape(text, start, Math.min(end, spanStart));
            start = spanStart;

        } else {

            // CharacterStyle found

            spans.remove(span);

            if (handleStartTag(span)) {
                convertText(text, Math.max(spanStart, start), Math.min(spanEnd, end), spans);
            }
            handleEndTag(span);

            start = spanEnd;
        }

    }
}
 
Example 11
Source File: CustomClickable.java    From redgram-for-reddit with GNU General Public License v3.0 5 votes vote down vote up
@Override
public void onClick(View widget) {

    if(widget instanceof TextView){
        TextView tv = (TextView) widget;
        if(tv.getText() instanceof Spanned){
            Spanned s = (Spanned) tv.getText();
            int start = s.getSpanStart(this);
            int end = s.getSpanEnd(this);
            clickableListener.onClickableEvent(s.subSequence(start, end));
        }
    }
}
 
Example 12
Source File: OpenLinkAction.java    From android-test with Apache License 2.0 5 votes vote down vote up
@Override
public void perform(UiController uiController, View view) {
  TextView textView = (TextView) view;
  String allText = textView.getText().toString();
  URLSpan[] urls = textView.getUrls();
  Spanned spanned = (Spanned) textView.getText();

  // TODO: what if we get more than one hit? For now, take the first one...
  // In the future, we may want to support a way to disambiguate (e.g using text around the link).
  List<String> allLinks = Lists.newArrayList();
  for (URLSpan url : urls) {
    int start = spanned.getSpanStart(url);
    checkState(start != -1, "Unable to get start of text associated with url: " + url);
    int end = spanned.getSpanEnd(url);
    checkState(end != -1, "Unable to get end of text associated with url: " + url);
    String linkText = allText.substring(start, end);
    allLinks.add(linkText);
    if (linkTextMatcher.matches(linkText) && uriMatcher.matches(Uri.parse(url.getURL()))) {
      url.onClick(view);
      return;
    }
  }
  throw new PerformException.Builder()
      .withActionDescription(this.getDescription())
      .withViewDescription(HumanReadables.describe(view))
      .withCause(
          new RuntimeException(
              String.format(
                  Locale.ROOT,
                  "Link with text '%s' and uri '%s' not found. List of links found in this view:"
                      + " %s\n"
                      + "List of uris: %s",
                  linkTextMatcher,
                  uriMatcher,
                  allLinks,
                  Arrays.asList(urls))))
      .build();
}
 
Example 13
Source File: BetterLinkMovementExtended.java    From mvvm-template with GNU General Public License v3.0 5 votes vote down vote up
static BetterLinkMovementExtended.ClickableSpanWithText ofSpan(TextView textView, ClickableSpan span) {
    Spanned s = (Spanned) textView.getText();
    String text;
    if (span instanceof URLSpan) {
        text = ((URLSpan) span).getURL();
    } else {
        int start = s.getSpanStart(span);
        int end = s.getSpanEnd(span);
        text = s.subSequence(start, end).toString();
    }
    return new BetterLinkMovementExtended.ClickableSpanWithText(span, text);
}
 
Example 14
Source File: ParseTreeResourceNode.java    From talkback with Apache License 2.0 5 votes vote down vote up
/**
 * Utility that copies spans from {@code fromSpan} to {@code toSpan}.
 *
 * @param toSpan Spannable that is supposed to contain fromSpan.
 * @param fromSpan Spannable that could contain spans that would be copied to toSpan.
 * @param toSpanStartIndex Starting index of occurrence fromSpan in toSpan.
 */
private static void copySpans(Spannable toSpan, Spanned fromSpan, int toSpanStartIndex) {
  if (toSpanStartIndex < 0 || toSpanStartIndex >= toSpan.length()) {
    LogUtils.e(
        TAG,
        "startIndex parameter (%d) is out of toSpan length %d",
        toSpanStartIndex,
        toSpan.length());
    return;
  }

  Object[] spans = fromSpan.getSpans(0, fromSpan.length(), Object.class);
  if (spans != null && spans.length > 0) {
    for (Object span : spans) {
      int spanStartIndex = fromSpan.getSpanStart(span);
      int spanEndIndex = fromSpan.getSpanEnd(span);
      if (spanStartIndex >= spanEndIndex) {
        continue;
      }
      int spanFlags = fromSpan.getSpanFlags(span);
      toSpan.setSpan(
          span,
          (toSpanStartIndex + spanStartIndex),
          (toSpanStartIndex + spanEndIndex),
          spanFlags);
    }
  }
}
 
Example 15
Source File: OverlineSpan.java    From Dashchan with Apache License 2.0 5 votes vote down vote up
public static void draw(TextView textView, Canvas canvas) {
	Layout layout = textView.getLayout();
	if (layout != null) {
		CharSequence text = textView.getText();
		if (text instanceof Spanned) {
			Spanned spanned = (Spanned) text;
			OverlineSpan[] spans = spanned.getSpans(0, spanned.length(), OverlineSpan.class);
			if (spans != null && spans.length > 0) {
				int paddingTop = textView.getTotalPaddingTop();
				int paddingLeft = textView.getPaddingLeft();
				int shift = (int) (textView.getTextSize() * 8f / 9f);
				float thickness = textView.getTextSize() / 15f - 0.25f;
				int color = textView.getCurrentTextColor();
				PAINT.setColor(color);
				PAINT.setStrokeWidth(thickness);
				for (OverlineSpan span : spans) {
					int start = spanned.getSpanStart(span);
					int end = spanned.getSpanEnd(span);
					int lineStart = layout.getLineForOffset(start);
					int lineEnd = layout.getLineForOffset(end);
					for (int i = lineStart; i <= lineEnd; i++) {
						float left = i == lineStart ? layout.getPrimaryHorizontal(start) : layout.getLineLeft(i);
						float right = i == lineEnd ? layout.getPrimaryHorizontal(end) : layout.getLineRight(i);
						float top = layout.getLineBaseline(i) - shift + 0.5f;
						canvas.drawLine(paddingLeft + left, paddingTop + top, paddingLeft + right,
								paddingTop + top, PAINT);
					}
				}
			}
		}
	}
}
 
Example 16
Source File: TextRange.java    From AOSP-Kayboard-7.1.2 with Apache License 2.0 4 votes vote down vote up
/**
 * Gets the suggestion spans that are put squarely on the word, with the exact start
 * and end of the span matching the boundaries of the word.
 * @return the list of spans.
 */
public SuggestionSpan[] getSuggestionSpansAtWord() {
    if (!(mTextAtCursor instanceof Spanned && mWord instanceof Spanned)) {
        return new SuggestionSpan[0];
    }
    final Spanned text = (Spanned)mTextAtCursor;
    // Note: it's fine to pass indices negative or greater than the length of the string
    // to the #getSpans() method. The reason we need to get from -1 to +1 is that, the
    // spans were cut at the cursor position, and #getSpans(start, end) does not return
    // spans that end at `start' or begin at `end'. Consider the following case:
    //              this| is          (The | symbolizes the cursor position
    //              ---- ---
    // In this case, the cursor is in position 4, so the 0~7 span has been split into
    // a 0~4 part and a 4~7 part.
    // If we called #getSpans(0, 4) in this case, we would only get the part from 0 to 4
    // of the span, and not the part from 4 to 7, so we would not realize the span actually
    // extends from 0 to 7. But if we call #getSpans(-1, 5) we'll get both the 0~4 and
    // the 4~7 spans and we can merge them accordingly.
    // Any span starting more than 1 char away from the word boundaries in any direction
    // does not touch the word, so we don't need to consider it. That's why requesting
    // -1 ~ +1 is enough.
    // Of course this is only relevant if the cursor is at one end of the word. If it's
    // in the middle, the -1 and +1 are not necessary, but they are harmless.
    final SuggestionSpan[] spans = text.getSpans(mWordAtCursorStartIndex - 1,
            mWordAtCursorEndIndex + 1, SuggestionSpan.class);
    int readIndex = 0;
    int writeIndex = 0;
    for (; readIndex < spans.length; ++readIndex) {
        final SuggestionSpan span = spans[readIndex];
        // The span may be null, as we null them when we find duplicates. Cf a few lines
        // down.
        if (null == span) continue;
        // Tentative span start and end. This may be modified later if we realize the
        // same span is also applied to other parts of the string.
        int spanStart = text.getSpanStart(span);
        int spanEnd = text.getSpanEnd(span);
        for (int i = readIndex + 1; i < spans.length; ++i) {
            if (span.equals(spans[i])) {
                // We found the same span somewhere else. Read the new extent of this
                // span, and adjust our values accordingly.
                spanStart = Math.min(spanStart, text.getSpanStart(spans[i]));
                spanEnd = Math.max(spanEnd, text.getSpanEnd(spans[i]));
                // ...and mark the span as processed.
                spans[i] = null;
            }
        }
        if (spanStart == mWordAtCursorStartIndex && spanEnd == mWordAtCursorEndIndex) {
            // If the span does not start and stop here, ignore it. It probably extends
            // past the start or end of the word, as happens in missing space correction
            // or EasyEditSpans put by voice input.
            spans[writeIndex++] = spans[readIndex];
        }
    }
    return writeIndex == readIndex ? spans : Arrays.copyOfRange(spans, 0, writeIndex);
}
 
Example 17
Source File: CodeTextView.java    From Markwon with Apache License 2.0 4 votes vote down vote up
private void draw(
        @NonNull View view,
        @NonNull Canvas canvas,
        @NonNull Layout layout
) {

    final CharSequence cs = layout.getText();
    if (!(cs instanceof Spanned)) {
        return;
    }
    final Spanned spanned = (Spanned) cs;

    final int save = canvas.save();
    try {
        canvas.translate(view.getPaddingLeft(), view.getPaddingTop());

        // TODO: block?
        // TODO: we must remove _original_ spans
        // TODO: cache (attach a listener?)
        // TODO: editor?

        final CodeSpan[] spans = spanned.getSpans(0, spanned.length(), CodeSpan.class);
        if (spans != null && spans.length > 0) {
            for (CodeSpan span : spans) {

                final int startOffset = spanned.getSpanStart(span);
                final int endOffset = spanned.getSpanEnd(span);

                final int startLine = layout.getLineForOffset(startOffset);
                final int endLine = layout.getLineForOffset(endOffset);

                // do we need to round them?
                final float left = layout.getPrimaryHorizontal(startOffset)
                        + (-1 * layout.getParagraphDirection(startLine) * paddingHorizontal);

                final float right = layout.getPrimaryHorizontal(endOffset)
                        + (layout.getParagraphDirection(endLine) * paddingHorizontal);

                final float top = getLineTop(layout, startLine, paddingVertical);
                final float bottom = getLineBottom(layout, endLine, paddingVertical);

                Debug.i(new RectF(left, top, right, bottom).toShortString());

                if (startLine == endLine) {
                    canvas.drawRect(left, top, right, bottom, paint);
                } else {
                    // draw first line (start until the lineEnd)
                    // draw everything in-between (startLine - endLine)
                    // draw last line (lineStart until the end

                    canvas.drawRect(
                            left,
                            top,
                            layout.getLineRight(startLine),
                            getLineBottom(layout, startLine, paddingVertical),
                            paint
                    );

                    for (int line = startLine + 1; line < endLine; line++) {
                        canvas.drawRect(
                                layout.getLineLeft(line),
                                getLineTop(layout, line, paddingVertical),
                                layout.getLineRight(line),
                                getLineBottom(layout, line, paddingVertical),
                                paint
                        );
                    }

                    canvas.drawRect(
                            layout.getLineLeft(endLine),
                            getLineTop(layout, endLine, paddingVertical),
                            right,
                            getLineBottom(layout, endLine, paddingVertical),
                            paint
                    );
                }
            }
        }
    } finally {
        canvas.restoreToCount(save);
    }
}
 
Example 18
Source File: SpannableStringBuilder.java    From JotaTextEditor with Apache License 2.0 4 votes vote down vote up
/**
 * Create a new SpannableStringBuilder containing a copy of the
 * specified slice of the specified text, including its spans if any.
 */
public SpannableStringBuilder(CharSequence text, int start, int end) {
    int srclen = end - start;

    int len = ArrayUtils.idealCharArraySize(srclen + 1);
    mText = new char[len];
    mGapStart = srclen;
    mGapLength = len - srclen;

    TextUtils.getChars(text, start, end, mText, 0);

    mSpanCount = 0;
    int alloc = ArrayUtils.idealIntArraySize(0);
    mSpans = new Object[alloc];
    mSpanStarts = new int[alloc];
    mSpanEnds = new int[alloc];
    mSpanFlags = new int[alloc];

    if (text instanceof Spanned) {
        Spanned sp = (Spanned) text;
        Object[] spans = sp.getSpans(start, end, Object.class);

        for (int i = 0; i < spans.length; i++) {
            if (spans[i] instanceof NoCopySpan) {
                continue;
            }

            int st = sp.getSpanStart(spans[i]) - start;
            int en = sp.getSpanEnd(spans[i]) - start;
            int fl = sp.getSpanFlags(spans[i]);

            if (st < 0)
                st = 0;
            if (st > end - start)
                st = end - start;

            if (en < 0)
                en = 0;
            if (en > end - start)
                en = end - start;

            if ( st <= en ) {
                setSpan(spans[i], st, en, fl);
            }
        }
    }
}
 
Example 19
Source File: ReactTextView.java    From react-native-GPay with MIT License 4 votes vote down vote up
@Override
public int reactTagForTouch(float touchX, float touchY) {
  CharSequence text = getText();
  int target = getId();

  int x = (int) touchX;
  int y = (int) touchY;

  Layout layout = getLayout();
  if (layout == null) {
    // If the layout is null, the view hasn't been properly laid out yet. Therefore, we can't find
    // the exact text tag that has been touched, and the correct tag to return is the default one.
    return target;
  }
  int line = layout.getLineForVertical(y);

  int lineStartX = (int) layout.getLineLeft(line);
  int lineEndX = (int) layout.getLineRight(line);

  // TODO(5966918): Consider extending touchable area for text spans by some DP constant
  if (text instanceof Spanned && x >= lineStartX && x <= lineEndX) {
    Spanned spannedText = (Spanned) text;
    int index = layout.getOffsetForHorizontal(line, x);

    // We choose the most inner span (shortest) containing character at the given index
    // if no such span can be found we will send the textview's react id as a touch handler
    // In case when there are more than one spans with same length we choose the last one
    // from the spans[] array, since it correspond to the most inner react element
    ReactTagSpan[] spans = spannedText.getSpans(index, index, ReactTagSpan.class);

    if (spans != null) {
      int targetSpanTextLength = text.length();
      for (int i = 0; i < spans.length; i++) {
        int spanStart = spannedText.getSpanStart(spans[i]);
        int spanEnd = spannedText.getSpanEnd(spans[i]);
        if (spanEnd > index && (spanEnd - spanStart) <= targetSpanTextLength) {
          target = spans[i].getReactTag();
          targetSpanTextLength = (spanEnd - spanStart);
        }
      }
    }
  }

  return target;
}
 
Example 20
Source File: SpannableStringBuilder.java    From PowerFileExplorer with GNU General Public License v3.0 4 votes vote down vote up
/**
 * Create a new SpannableStringBuilder containing a copy of the
 * specified slice of the specified text, including its spans if any.
 */
public SpannableStringBuilder(CharSequence text, int start, int end) {
    int srclen = end - start;

    int len = ArrayUtils.idealCharArraySize(srclen + 1);
    mText = new char[len];
    mGapStart = srclen;
    mGapLength = len - srclen;

    TextUtils.getChars(text, start, end, mText, 0);

    mSpanCount = 0;
    int alloc = ArrayUtils.idealIntArraySize(0);
    mSpans = new Object[alloc];
    mSpanStarts = new int[alloc];
    mSpanEnds = new int[alloc];
    mSpanFlags = new int[alloc];

    if (text instanceof Spanned) {
        Spanned sp = (Spanned) text;
        Object[] spans = sp.getSpans(start, end, Object.class);

        for (int i = 0; i < spans.length; i++) {
            if (spans[i] instanceof NoCopySpan) {
                continue;
            }

            int st = sp.getSpanStart(spans[i]) - start;
            int en = sp.getSpanEnd(spans[i]) - start;
            int fl = sp.getSpanFlags(spans[i]);

            if (st < 0)
                st = 0;
            if (st > end - start)
                st = end - start;

            if (en < 0)
                en = 0;
            if (en > end - start)
                en = end - start;

            if ( st <= en ) {
                setSpan(spans[i], st, en, fl);
            }
        }
    }
}