private CharSequence recurseElement(Element element, int indexWithinParent, int numberOfSiblings,
			ImageGetter imageGetter) {

		Type type = element.getType();

		boolean isOrderedList = false;
		if (type == Type.LIST) {
			String flagsStr = element.getAttribute("flags");
			if (flagsStr != null) {
				int flags = Integer.parseInt(flagsStr);
				isOrderedList = (flags & Element.F_LIST_ORDERED) != 0;
				if (isOrderedList) {
					mOrderedListNumber.put(element, 1);
				}
			}
		}

		int size = element.size();
		CharSequence[] spans = new CharSequence[size];
		
		for (int i = 0; i < size; i++) {
			spans[i] = recurseElement(element.children[i], i, size, imageGetter);
		}

		// Clean up after we're done
		if (isOrderedList) {
			mOrderedListNumber.remove(this);
		}

		CharSequence concat = TextUtils.concat(spans);

		SpannableStringBuilder builder = new ReverseSpannableStringBuilder();

		String text = element.getText();
		if (element.size() == 0
			&& element.getParent() != null
			&& element.getParent().getType() != Type.BLOCK_CODE) {
			text = text.replace('\n', ' ');
		}

		// Retrieve the image now so we know whether we're going to have something to display later
		// If we don't, then show the alt text instead (if available).
		Drawable imageDrawable = null;
		if (type == Type.IMAGE && imageGetter != null && !TextUtils.isEmpty(element.getAttribute("link"))) {
			imageDrawable = imageGetter.getDrawable(element.getAttribute("link"));
		}

		switch (type) {
			case LIST:
				if (element.getParent() != null
					&& element.getParent().getType() == Type.LIST_ITEM) {
					builder.append("\n");
				}
				break;
			case LINEBREAK:
				builder.append("\n");
				break;
			case LIST_ITEM:
				builder.append(" ");
				if (mOrderedListNumber.containsKey(element.getParent())) {
					int number = mOrderedListNumber.get(element.getParent());
					builder.append(Integer.toString(number) + ".");
					mOrderedListNumber.put(element.getParent(), number + 1);
				}
				else {
					builder.append(mOptions.mUnorderedListItem);
				}
				builder.append("  ");
				break;
			case AUTOLINK:
				builder.append(element.getAttribute("link"));
				break;
			case HRULE:
				// This ultimately gets drawn over by the line span, but
				// we need something here or the span isn't even drawn.
				builder.append("-");
				break;
			case IMAGE:
				// Display alt text (or title text) if there is no image
				if (imageDrawable == null) {
					String show = element.getAttribute("alt");
					if (TextUtils.isEmpty(show)) {
						show = element.getAttribute("title");
					}
					if (!TextUtils.isEmpty(show)) {
						show = "[" + show + "]";
						builder.append(show);
					}
				}
				else {
					// Character to be replaced
					builder.append("\uFFFC");
				}
				break;
		}

		builder.append(text);
		builder.append(concat);
		
		// Don't auto-append whitespace after last item in document. The 'numberOfSiblings'
		// is the number of children the parent of the current element has (including the
		// element itself), hence subtracting a number from that count gives us the index
		// of the last child within the parent.
		if (element.getParent() != null || indexWithinParent < (numberOfSiblings - 1)) {
			if (type == Type.LIST_ITEM) {
				if (element.size() == 0 || !element.children[element.size() - 1].isBlockElement()) {
					builder.append("\n");
				}
			}
			else if (element.isBlockElement() && type != Type.BLOCK_QUOTE) {
				if (type == Type.LIST) {
					// If this is a nested list, don't include newlines
					if (element.getParent() == null || element.getParent().getType() != Type.LIST_ITEM) {
						builder.append("\n");
					}
				}
				else if (element.getParent() != null
					&& element.getParent().getType() == Type.LIST_ITEM) {
					// List items should never double-space their entries
					builder.append("\n");
				}
				else {
					builder.append("\n\n");
				}
			}
		}

		switch (type) {
			case HEADER:
				String levelStr = element.getAttribute("level");
				int level = Integer.parseInt(levelStr);
				setSpan(builder, new RelativeSizeSpan(mOptions.mHeaderSizes[level - 1]));
				setSpan(builder, new StyleSpan(Typeface.BOLD));
				break;
			case LIST:
				setBlockSpan(builder, new LeadingMarginSpan.Standard(mListItemIndent));
				break;
			case EMPHASIS:
				setSpan(builder, new StyleSpan(Typeface.ITALIC));
				break;
			case DOUBLE_EMPHASIS:
				setSpan(builder, new StyleSpan(Typeface.BOLD));
				break;
			case TRIPLE_EMPHASIS:
				setSpan(builder, new StyleSpan(Typeface.BOLD_ITALIC));
				break;
			case BLOCK_CODE:
				setSpan(builder, new LeadingMarginSpan.Standard(mCodeBlockIndent));
				setSpan(builder, new TypefaceSpan("monospace"));
				break;
			case CODE_SPAN:
				setSpan(builder, new TypefaceSpan("monospace"));
				break;
			case LINK:
			case AUTOLINK:
				String link = element.getAttribute("link");
				if (!TextUtils.isEmpty(link) && Patterns.EMAIL_ADDRESS.matcher(link).matches()) {
					link = "mailto:" + link;
				}
				setSpan(builder, new URLSpan(link));
				break;
			case BLOCK_QUOTE:
				// We add two leading margin spans so that when the order is reversed,
				// the QuoteSpan will always be in the same spot.
				setBlockSpan(builder, new LeadingMarginSpan.Standard(mBlockQuoteIndent));
				setBlockSpan(builder, new QuoteSpan(mOptions.mBlockQuoteColor));
				setBlockSpan(builder, new LeadingMarginSpan.Standard(mBlockQuoteIndent));
				setBlockSpan(builder, new StyleSpan(Typeface.ITALIC));
				break;
			case STRIKETHROUGH:
				setSpan(builder, new StrikethroughSpan());
				break;
			case HRULE:
				setSpan(builder, new HorizontalLineSpan(mOptions.mHruleColor, mHruleSize, mHruleTopBottomPadding));
				break;
			case IMAGE:
				if (imageDrawable != null) {
					setSpan(builder, new ImageSpan(imageDrawable));
				}
				break;
		}

		return builder;
	}
private CharSequence recurseElement(Element element, int indexWithinParent, int numberOfSiblings,
			ImageGetter imageGetter) {

		Type type = element.getType();

		boolean isOrderedList = false;
		if (type == Type.LIST) {
			String flagsStr = element.getAttribute("flags");
			if (flagsStr != null) {
				int flags = Integer.parseInt(flagsStr);
				isOrderedList = (flags & Element.F_LIST_ORDERED) != 0;
				if (isOrderedList) {
					mOrderedListNumber.put(element, 1);
				}
			}
		}

		int size = element.size();
		CharSequence[] spans = new CharSequence[size];
		
		for (int i = 0; i < size; i++) {
			spans[i] = recurseElement(element.children[i], i, size, imageGetter);
		}

		
		if (isOrderedList) {
			mOrderedListNumber.remove(this);
		}

		CharSequence concat = TextUtils.concat(spans);

		SpannableStringBuilder builder = new ReverseSpannableStringBuilder();

		String text = element.getText();
		if (element.size() == 0
			&& element.getParent() != null
			&& element.getParent().getType() != Type.BLOCK_CODE) {
			text = text.replace('\n', ' ');
		}

		
		
		Drawable imageDrawable = null;
		if (type == Type.IMAGE && imageGetter != null && !TextUtils.isEmpty(element.getAttribute("link"))) {
			imageDrawable = imageGetter.getDrawable(element.getAttribute("link"));
		}

		switch (type) {
			case LIST:
				if (element.getParent() != null
					&& element.getParent().getType() == Type.LIST_ITEM) {
					builder.append("\n");
				}
				break;
			case LINEBREAK:
				builder.append("\n");
				break;
			case LIST_ITEM:
				builder.append(" ");
				if (mOrderedListNumber.containsKey(element.getParent())) {
					int number = mOrderedListNumber.get(element.getParent());
					builder.append(Integer.toString(number) + ".");
					mOrderedListNumber.put(element.getParent(), number + 1);
				}
				else {
					builder.append(mOptions.mUnorderedListItem);
				}
				builder.append("  ");
				break;
			case AUTOLINK:
				builder.append(element.getAttribute("link"));
				break;
			case HRULE:
				
				
				builder.append("-");
				break;
			case IMAGE:
				
				if (imageDrawable == null) {
					String show = element.getAttribute("alt");
					if (TextUtils.isEmpty(show)) {
						show = element.getAttribute("title");
					}
					if (!TextUtils.isEmpty(show)) {
						show = "[" + show + "]";
						builder.append(show);
					}
				}
				else {
					
					builder.append("\uFFFC");
				}
				break;
		}

		builder.append(text);
		builder.append(concat);
		
		
		
		
		
		if (element.getParent() != null || indexWithinParent < (numberOfSiblings - 1)) {
			if (type == Type.LIST_ITEM) {
				if (element.size() == 0 || !element.children[element.size() - 1].isBlockElement()) {
					builder.append("\n");
				}
			}
			else if (element.isBlockElement() && type != Type.BLOCK_QUOTE) {
				if (type == Type.LIST) {
					
					if (element.getParent() == null || element.getParent().getType() != Type.LIST_ITEM) {
						builder.append("\n");
					}
				}
				else if (element.getParent() != null
					&& element.getParent().getType() == Type.LIST_ITEM) {
					
					builder.append("\n");
				}
				else {
					builder.append("\n\n");
				}
			}
		}

		switch (type) {
			case HEADER:
				String levelStr = element.getAttribute("level");
				int level = Integer.parseInt(levelStr);
				setSpan(builder, new RelativeSizeSpan(mOptions.mHeaderSizes[level - 1]));
				setSpan(builder, new StyleSpan(Typeface.BOLD));
				break;
			case LIST:
				setBlockSpan(builder, new LeadingMarginSpan.Standard(mListItemIndent));
				break;
			case EMPHASIS:
				setSpan(builder, new StyleSpan(Typeface.ITALIC));
				break;
			case DOUBLE_EMPHASIS:
				setSpan(builder, new StyleSpan(Typeface.BOLD));
				break;
			case TRIPLE_EMPHASIS:
				setSpan(builder, new StyleSpan(Typeface.BOLD_ITALIC));
				break;
			case BLOCK_CODE:
				setSpan(builder, new LeadingMarginSpan.Standard(mCodeBlockIndent));
				setSpan(builder, new TypefaceSpan("monospace"));
				break;
			case CODE_SPAN:
				setSpan(builder, new TypefaceSpan("monospace"));
				break;
			case LINK:
			case AUTOLINK:
				String link = element.getAttribute("link");
				if (!TextUtils.isEmpty(link) && Patterns.EMAIL_ADDRESS.matcher(link).matches()) {
					link = "mailto:" + link;
				}
				setSpan(builder, new URLSpan(link));
				break;
			case BLOCK_QUOTE:
				
				
				setBlockSpan(builder, new LeadingMarginSpan.Standard(mBlockQuoteIndent));
				setBlockSpan(builder, new QuoteSpan(mOptions.mBlockQuoteColor));
				setBlockSpan(builder, new LeadingMarginSpan.Standard(mBlockQuoteIndent));
				setBlockSpan(builder, new StyleSpan(Typeface.ITALIC));
				break;
			case STRIKETHROUGH:
				setSpan(builder, new StrikethroughSpan());
				break;
			case HRULE:
				setSpan(builder, new HorizontalLineSpan(mOptions.mHruleColor, mHruleSize, mHruleTopBottomPadding));
				break;
			case IMAGE:
				if (imageDrawable != null) {
					setSpan(builder, new ImageSpan(imageDrawable));
				}
				break;
		}

		return builder;
	}
private CharSequence recurseElement ( Element element , int indexWithinParent , int numberOfSiblings , ImageGetter imageGetter ) { Type type = element . getType ( ) ; boolean isOrderedList = false ; if ( type == Type . LIST ) { String flagsStr = element . getAttribute ( "flags" ) ; if ( flagsStr != null ) { int flags = Integer . parseInt ( flagsStr ) ; isOrderedList = ( flags & Element . F_LIST_ORDERED ) != 0 ; if ( isOrderedList ) { mOrderedListNumber . put ( element , 1 ) ; } } } int size = element . size ( ) ; CharSequence [ ] spans = new CharSequence [ size ] ; for ( int i = 0 ; i < size ; i ++ ) { spans [ i ] = recurseElement ( element . children [ i ] , i , size , imageGetter ) ; } // Clean up after we're done if ( isOrderedList ) { mOrderedListNumber . remove ( this ) ; } CharSequence concat = TextUtils . concat ( spans ) ; SpannableStringBuilder builder = new ReverseSpannableStringBuilder ( ) ; String text = element . getText ( ) ; if ( element . size ( ) == 0 && element . getParent ( ) != null && element . getParent ( ) . getType ( ) != Type . BLOCK_CODE ) { text = text . replace ( ' ' , ' ' ) ; } // Retrieve the image now so we know whether we're going to have something to display later // If we don't, then show the alt text instead (if available). Drawable imageDrawable = null ; if ( type == Type . IMAGE && imageGetter != null && ! TextUtils . isEmpty ( element . getAttribute ( "link" ) ) ) { imageDrawable = imageGetter . getDrawable ( element . getAttribute ( "link" ) ) ; } switch ( type ) { case LIST : if ( element . getParent ( ) != null && element . getParent ( ) . getType ( ) == Type . LIST_ITEM ) { builder . append ( "\n" ) ; } break ; case LINEBREAK : builder . append ( "\n" ) ; break ; case LIST_ITEM : builder . append ( " " ) ; if ( mOrderedListNumber . containsKey ( element . getParent ( ) ) ) { int number = mOrderedListNumber . get ( element . getParent ( ) ) ; builder . append ( Integer . toString ( number ) + "." ) ; mOrderedListNumber . put ( element . getParent ( ) , number + 1 ) ; } else { builder . append ( mOptions . mUnorderedListItem ) ; } builder . append ( "  " ) ; break ; case AUTOLINK : builder . append ( element . getAttribute ( "link" ) ) ; break ; case HRULE : // This ultimately gets drawn over by the line span, but // we need something here or the span isn't even drawn. builder . append ( "-" ) ; break ; case IMAGE : // Display alt text (or title text) if there is no image if ( imageDrawable == null ) { String show = element . getAttribute ( "alt" ) ; if ( TextUtils . isEmpty ( show ) ) { show = element . getAttribute ( "title" ) ; } if ( ! TextUtils . isEmpty ( show ) ) { show = "[" + show + "]" ; builder . append ( show ) ; } } else { // Character to be replaced builder . append ( "\uFFFC" ) ; } break ; } builder . append ( text ) ; builder . append ( concat ) ; // Don't auto-append whitespace after last item in document. The 'numberOfSiblings' // is the number of children the parent of the current element has (including the // element itself), hence subtracting a number from that count gives us the index // of the last child within the parent. if ( element . getParent ( ) != null || indexWithinParent < ( numberOfSiblings - 1 ) ) { if ( type == Type . LIST_ITEM ) { if ( element . size ( ) == 0 || ! element . children [ element . size ( ) - 1 ] . isBlockElement ( ) ) { builder . append ( "\n" ) ; } } else if ( element . isBlockElement ( ) && type != Type . BLOCK_QUOTE ) { if ( type == Type . LIST ) { // If this is a nested list, don't include newlines if ( element . getParent ( ) == null || element . getParent ( ) . getType ( ) != Type . LIST_ITEM ) { builder . append ( "\n" ) ; } } else if ( element . getParent ( ) != null && element . getParent ( ) . getType ( ) == Type . LIST_ITEM ) { // List items should never double-space their entries builder . append ( "\n" ) ; } else { builder . append ( "\n\n" ) ; } } } switch ( type ) { case HEADER : String levelStr = element . getAttribute ( "level" ) ; int level = Integer . parseInt ( levelStr ) ; setSpan ( builder , new RelativeSizeSpan ( mOptions . mHeaderSizes [ level - 1 ] ) ) ; setSpan ( builder , new StyleSpan ( Typeface . BOLD ) ) ; break ; case LIST : setBlockSpan ( builder , new LeadingMarginSpan . Standard ( mListItemIndent ) ) ; break ; case EMPHASIS : setSpan ( builder , new StyleSpan ( Typeface . ITALIC ) ) ; break ; case DOUBLE_EMPHASIS : setSpan ( builder , new StyleSpan ( Typeface . BOLD ) ) ; break ; case TRIPLE_EMPHASIS : setSpan ( builder , new StyleSpan ( Typeface . BOLD_ITALIC ) ) ; break ; case BLOCK_CODE : setSpan ( builder , new LeadingMarginSpan . Standard ( mCodeBlockIndent ) ) ; setSpan ( builder , new TypefaceSpan ( "monospace" ) ) ; break ; case CODE_SPAN : setSpan ( builder , new TypefaceSpan ( "monospace" ) ) ; break ; case LINK : case AUTOLINK : String link = element . getAttribute ( "link" ) ; if ( ! TextUtils . isEmpty ( link ) && Patterns . EMAIL_ADDRESS . matcher ( link ) . matches ( ) ) { link = "mailto:" + link ; } setSpan ( builder , new URLSpan ( link ) ) ; break ; case BLOCK_QUOTE : // We add two leading margin spans so that when the order is reversed, // the QuoteSpan will always be in the same spot. setBlockSpan ( builder , new LeadingMarginSpan . Standard ( mBlockQuoteIndent ) ) ; setBlockSpan ( builder , new QuoteSpan ( mOptions . mBlockQuoteColor ) ) ; setBlockSpan ( builder , new LeadingMarginSpan . Standard ( mBlockQuoteIndent ) ) ; setBlockSpan ( builder , new StyleSpan ( Typeface . ITALIC ) ) ; break ; case STRIKETHROUGH : setSpan ( builder , new StrikethroughSpan ( ) ) ; break ; case HRULE : setSpan ( builder , new HorizontalLineSpan ( mOptions . mHruleColor , mHruleSize , mHruleTopBottomPadding ) ) ; break ; case IMAGE : if ( imageDrawable != null ) { setSpan ( builder , new ImageSpan ( imageDrawable ) ) ; } break ; } return builder ; }
you have?".
you have? .