Input: Returns true if the specified <code > String< / code > matches any IANA - defined generic top - level domain . Leading dots are ignored if present . The search is case - insensitive . [CODESPLIT] public boolean isValidGenericTld ( String gTld ) { gTld = unicodeToASCII ( gTld ) ; return Arrays . binarySearch ( GENERIC_TLDS , chompLeadingDot ( gTld . toLowerCase ( Locale . ENGLISH ) ) ) >= 0 ; }


Input: Returns true if the specified <code > String< / code > matches any IANA - defined country code top - level domain . Leading dots are ignored if present . The search is case - insensitive . [CODESPLIT] public boolean isValidCountryCodeTld ( String ccTld ) { ccTld = unicodeToASCII ( ccTld ) ; return Arrays . binarySearch ( COUNTRY_CODE_TLDS , chompLeadingDot ( ccTld . toLowerCase ( Locale . ENGLISH ) ) ) >= 0 ; }


Input: Returns true if the specified <code > String< / code > matches any widely used local domains ( localhost or localdomain ) . Leading dots are ignored if present . The search is case - insensitive . [CODESPLIT] public boolean isValidLocalTld ( String lTld ) { lTld = unicodeToASCII ( lTld ) ; return Arrays . binarySearch ( LOCAL_TLDS , chompLeadingDot ( lTld . toLowerCase ( Locale . ENGLISH ) ) ) >= 0 ; }


Input: / * Helper method to invoke java . net . IDN . toAscii ( String ) . Allows code to be compiled with Java 1 . 4 and 1 . 5 [CODESPLIT] private static final String toASCII ( String line ) throws IllegalArgumentException { //        java.net.IDN.toASCII(line); // Java 1.6+ // implementation for Java 1.4 and 1.5 // effectively this is done by IDN.toASCII but we want to skip the entire call if ( isOnlyASCII ( line ) ) { return line ; } Method m = IDNHolder . JAVA_NET_IDN_TO_ASCII ; if ( m == null ) { // avoid NPE return line ; } try { return ( String ) m . invoke ( null , new String [ ] { line . toLowerCase ( Locale . ENGLISH ) } ) ; } catch ( IllegalAccessException e ) { throw new RuntimeException ( e ) ; // Should not happen } catch ( InvocationTargetException e ) { Throwable t = e . getCause ( ) ; if ( t instanceof IllegalArgumentException ) { // this is expected from toASCII method throw ( IllegalArgumentException ) t ; } throw new RuntimeException ( e ) ; // Should not happen } }


Input: ****************************************** Lifecycle Methods ******************************************* [CODESPLIT] @ Override protected void onCreate ( Bundle savedInstanceState ) { super . onCreate ( savedInstanceState ) ; // set theme setTheme ( RTApi . useDarkTheme ( ) ? R . style . RTE_BaseThemeDark : R . style . RTE_BaseThemeLight ) ; if ( ! isFinishing ( ) ) { mHandler = new Handler ( ) ; for ( LifeCycleListener listener : mListeners ) { listener . onActivityCreated ( this ) ; } } }


Input: Start a foreground job showing a progress bar as long as the job runs . A foreground job shows a modal dialog that can t be cancelled while the app does some processing . This should be used for short jobs only that block the ui . Of course this contradicts many of the Android guidelines but with short jobs we mean < 1 second and only in rare cases should it me more ( e . g . when the garbage collector kicks in which would normally lead to stuttering ) . Using foreground jobs gives a better user experience in these rare cases . The user has to wait but he / she knows it because there s a progess bar . [CODESPLIT] public < T > T startForegroundJob ( int msgId , ForegroundJob < T > job ) { // make the progress dialog uncancelable, so that we can guarantee // that the thread is done before the activity gets destroyed ProgressDialog dialog = ProgressDialog . show ( this , null , getString ( msgId ) , true , false ) ; Job < T > managedJob = new Job < T > ( job , dialog ) ; return managedJob . runForegroundJob ( ) ; }


Input: Start a background job showing a progress bar as long as the job runs . This seems contradictory but with background job we mean one that runs off the ui thread to prevent an ANR . We still have to wait for the processing to be done because we need the result . [CODESPLIT] public void startBackgroundJob ( int msgId , Runnable runnable ) { // make the progress dialog uncancelable, so that we can guarantee // that the thread is done before the activity gets destroyed ProgressDialog dialog = ProgressDialog . show ( this , null , getString ( msgId ) , true , false ) ; Job < Object > managedJob = new Job < Object > ( runnable , dialog ) ; managedJob . runBackgroundJob ( ) ; }


Input: ****************************************** Handle Tags ******************************************* [CODESPLIT] private void handleStartTag ( String tag , Attributes attributes ) { if ( tag . equalsIgnoreCase ( "br" ) ) { // We don't need to handle this. TagSoup will ensure that there's a </br> for each <br> // so we can safely omit the line breaks when we handle the close tag. } else if ( tag . equalsIgnoreCase ( "p" ) ) { handleP ( ) ; } else if ( tag . equalsIgnoreCase ( "div" ) ) { startDiv ( attributes ) ; } else if ( tag . equalsIgnoreCase ( "ul" ) ) { startList ( false , attributes ) ; } else if ( tag . equalsIgnoreCase ( "ol" ) ) { startList ( true , attributes ) ; } else if ( tag . equalsIgnoreCase ( "li" ) ) { startList ( attributes ) ; } else if ( tag . equalsIgnoreCase ( "strong" ) ) { start ( new Bold ( ) ) ; } else if ( tag . equalsIgnoreCase ( "b" ) ) { start ( new Bold ( ) ) ; } else if ( tag . equalsIgnoreCase ( "em" ) ) { start ( new Italic ( ) ) ; } else if ( tag . equalsIgnoreCase ( "cite" ) ) { start ( new Italic ( ) ) ; } else if ( tag . equalsIgnoreCase ( "dfn" ) ) { start ( new Italic ( ) ) ; } else if ( tag . equalsIgnoreCase ( "i" ) ) { start ( new Italic ( ) ) ; } else if ( tag . equalsIgnoreCase ( "strike" ) ) { start ( new Strikethrough ( ) ) ; } else if ( tag . equalsIgnoreCase ( "del" ) ) { start ( new Strikethrough ( ) ) ; } else if ( tag . equalsIgnoreCase ( "big" ) ) { start ( new Big ( ) ) ; } else if ( tag . equalsIgnoreCase ( "small" ) ) { start ( new Small ( ) ) ; } else if ( tag . equalsIgnoreCase ( "font" ) ) { startFont ( attributes ) ; } else if ( tag . equalsIgnoreCase ( "blockquote" ) ) { handleP ( ) ; start ( new Blockquote ( ) ) ; } else if ( tag . equalsIgnoreCase ( "tt" ) ) { start ( new Monospace ( ) ) ; } else if ( tag . equalsIgnoreCase ( "a" ) ) { startAHref ( attributes ) ; } else if ( tag . equalsIgnoreCase ( "u" ) ) { start ( new Underline ( ) ) ; } else if ( tag . equalsIgnoreCase ( "sup" ) ) { start ( new Super ( ) ) ; } else if ( tag . equalsIgnoreCase ( "sub" ) ) { start ( new Sub ( ) ) ; } else if ( tag . length ( ) == 2 && Character . toLowerCase ( tag . charAt ( 0 ) ) == ' ' && tag . charAt ( 1 ) >= ' ' && tag . charAt ( 1 ) <= ' ' ) { handleP ( ) ; start ( new Header ( tag . charAt ( 1 ) - ' ' ) ) ; } else if ( tag . equalsIgnoreCase ( "img" ) ) { startImg ( attributes ) ; } else if ( tag . equalsIgnoreCase ( "video" ) ) { startVideo ( attributes ) ; } else if ( tag . equalsIgnoreCase ( "embed" ) ) { startAudio ( attributes ) ; } else if ( sIgnoreTags . contains ( tag . toLowerCase ( Locale . getDefault ( ) ) ) ) { mIgnoreContent = true ; } }


Input: Handles OL and UL start tags [CODESPLIT] private void startList ( boolean isOrderedList , Attributes attributes ) { boolean isIndentation = isIndentation ( attributes ) ; ParagraphType newType = isIndentation && isOrderedList ? ParagraphType . INDENTATION_OL : isIndentation && ! isOrderedList ? ParagraphType . INDENTATION_UL : isOrderedList ? ParagraphType . NUMBERING : ParagraphType . BULLET ; AccumulatedParagraphStyle currentStyle = mParagraphStyles . isEmpty ( ) ? null : mParagraphStyles . peek ( ) ; if ( currentStyle == null ) { // no previous style found -> create new AccumulatedParagraphStyle with indentations of 1 AccumulatedParagraphStyle newStyle = new AccumulatedParagraphStyle ( newType , 1 , 1 ) ; mParagraphStyles . push ( newStyle ) ; } else if ( currentStyle . getType ( ) == newType ) { // same style found -> increase indentations by 1 currentStyle . setAbsoluteIndent ( currentStyle . getAbsoluteIndent ( ) + 1 ) ; currentStyle . setRelativeIndent ( currentStyle . getRelativeIndent ( ) + 1 ) ; } else { // different style found -> create new AccumulatedParagraphStyle with incremented indentations AccumulatedParagraphStyle newStyle = new AccumulatedParagraphStyle ( newType , currentStyle . getAbsoluteIndent ( ) + 1 , 1 ) ; mParagraphStyles . push ( newStyle ) ; } }


Input: Handles OL and UL end tags [CODESPLIT] private void endList ( boolean orderedList ) { if ( ! mParagraphStyles . isEmpty ( ) ) { AccumulatedParagraphStyle style = mParagraphStyles . peek ( ) ; ParagraphType type = style . getType ( ) ; if ( ( orderedList && ( type . isNumbering ( ) || type == ParagraphType . INDENTATION_OL ) ) || ( ! orderedList && ( type . isBullet ( ) || type == ParagraphType . INDENTATION_UL ) ) ) { // the end tag matches the current style int indent = style . getRelativeIndent ( ) ; if ( indent > 1 ) { style . setRelativeIndent ( indent - 1 ) ; style . setAbsoluteIndent ( style . getAbsoluteIndent ( ) - 1 ) ; } else { mParagraphStyles . pop ( ) ; } } else { // the end tag doesn't match the current style mParagraphStyles . pop ( ) ; endList ( orderedList ) ; // find the next matching style } } }


Input: Handles LI tags [CODESPLIT] private void startList ( Attributes attributes ) { List listTag = null ; if ( ! mParagraphStyles . isEmpty ( ) ) { AccumulatedParagraphStyle currentStyle = mParagraphStyles . peek ( ) ; ParagraphType type = currentStyle . getType ( ) ; int indent = currentStyle . getAbsoluteIndent ( ) ; boolean isIndentation = isIndentation ( attributes ) ; if ( type . isIndentation ( ) || isIndentation ) { listTag = new UL ( indent , true ) ; } else if ( type . isNumbering ( ) ) { listTag = new OL ( indent , false ) ; } else if ( type . isBullet ( ) ) { listTag = new UL ( indent , false ) ; } } else { listTag = new UL ( 0 , false ) ; } if ( listTag != null ) start ( listTag ) ; }


Input: Handles LI tags [CODESPLIT] private void endList ( ) { List list = ( List ) getLast ( List . class ) ; if ( list != null ) { if ( mResult . length ( ) == 0 || mResult . charAt ( mResult . length ( ) - 1 ) != ' ' ) { mResult . append ( ' ' ) ; } int start = mResult . getSpanStart ( list ) ; int end = mResult . length ( ) ; int nrOfIndents = list . mNrOfIndents ; if ( ! list . mIsIndentation ) { nrOfIndents -- ; int margin = Helper . getLeadingMarging ( ) ; // use SPAN_EXCLUSIVE_EXCLUSIVE here, will be replaced later anyway when the cleanup function is called Object span = list instanceof UL ? new BulletSpan ( margin , start == end , false , false ) : new NumberSpan ( 1 , margin , start == end , false , false ) ; mResult . setSpan ( span , start , end , Spanned . SPAN_EXCLUSIVE_EXCLUSIVE ) ; } if ( nrOfIndents > 0 ) { int margin = nrOfIndents * Helper . getLeadingMarging ( ) ; // use SPAN_EXCLUSIVE_EXCLUSIVE here, will be replaced later anyway when the cleanup function is called IndentationSpan span = new IndentationSpan ( margin , start == end , false , false ) ; mResult . setSpan ( span , start , end , Spanned . SPAN_EXCLUSIVE_EXCLUSIVE ) ; } mResult . removeSpan ( list ) ; } }


Input: Converts an HTML color ( named or numeric ) to an integer RGB value . [CODESPLIT] @ SuppressLint ( "DefaultLocale" ) private static int getHtmlColor ( String color ) { Integer i = COLORS . get ( color . toLowerCase ( ) ) ; if ( i != null ) { return i ; } else { try { return convertValueToInt ( color , - 1 ) ; } catch ( NumberFormatException nfe ) { return - 1 ; } } }


Input: Determines which edges are hit by touching at ( x y ) . [CODESPLIT] public int getHit ( float x , float y ) { Rect r = computeLayout ( ) ; final float hysteresis = 20F ; int retval = GROW_NONE ; if ( mCircle ) { float distX = x - r . centerX ( ) ; float distY = y - r . centerY ( ) ; int distanceFromCenter = ( int ) Math . sqrt ( distX * distX + distY * distY ) ; int radius = mDrawRect . width ( ) / 2 ; int delta = distanceFromCenter - radius ; if ( Math . abs ( delta ) <= hysteresis ) { if ( Math . abs ( distY ) > Math . abs ( distX ) ) { if ( distY < 0 ) { retval = GROW_TOP_EDGE ; } else { retval = GROW_BOTTOM_EDGE ; } } else { if ( distX < 0 ) { retval = GROW_LEFT_EDGE ; } else { retval = GROW_RIGHT_EDGE ; } } } else if ( distanceFromCenter < radius ) { retval = MOVE ; } else { retval = GROW_NONE ; } } else { // verticalCheck makes sure the position is between the top and // the bottom edge (with some tolerance). Similar for horizCheck. boolean verticalCheck = ( y >= r . top - hysteresis ) && ( y < r . bottom + hysteresis ) ; boolean horizCheck = ( x >= r . left - hysteresis ) && ( x < r . right + hysteresis ) ; // Check whether the position is near some edge(s). if ( ( Math . abs ( r . left - x ) < hysteresis ) && verticalCheck ) { retval |= GROW_LEFT_EDGE ; } if ( ( Math . abs ( r . right - x ) < hysteresis ) && verticalCheck ) { retval |= GROW_RIGHT_EDGE ; } if ( ( Math . abs ( r . top - y ) < hysteresis ) && horizCheck ) { retval |= GROW_TOP_EDGE ; } if ( ( Math . abs ( r . bottom - y ) < hysteresis ) && horizCheck ) { retval |= GROW_BOTTOM_EDGE ; } // Not near any edge but inside the rectangle: move. if ( retval == GROW_NONE && r . contains ( ( int ) x , ( int ) y ) ) { retval = MOVE ; } } return retval ; }


Input: The edge parameter specifies which edges the user is dragging . [CODESPLIT] void handleMotion ( int edge , float dx , float dy ) { Rect r = computeLayout ( ) ; if ( edge == GROW_NONE ) { return ; } else if ( edge == MOVE ) { // Convert to image space before sending to moveBy(). moveBy ( dx * ( mCropRect . width ( ) / r . width ( ) ) , dy * ( mCropRect . height ( ) / r . height ( ) ) ) ; } else { if ( ( ( GROW_LEFT_EDGE | GROW_RIGHT_EDGE ) & edge ) == 0 ) { dx = 0 ; } if ( ( ( GROW_TOP_EDGE | GROW_BOTTOM_EDGE ) & edge ) == 0 ) { dy = 0 ; } // Convert to image space before sending to growBy(). float xDelta = dx * ( mCropRect . width ( ) / r . width ( ) ) ; float yDelta = dy * ( mCropRect . height ( ) / r . height ( ) ) ; growBy ( ( ( ( edge & GROW_LEFT_EDGE ) != 0 ) ? - 1 : 1 ) * xDelta , ( ( ( edge & GROW_TOP_EDGE ) != 0 ) ? - 1 : 1 ) * yDelta ) ; } }


Input: Grows the cropping rectange by ( dx dy ) in image space . [CODESPLIT] void moveBy ( float dx , float dy ) { Rect invalRect = new Rect ( mDrawRect ) ; mCropRect . offset ( dx , dy ) ; // Put the cropping rectangle inside image rectangle. mCropRect . offset ( Math . max ( 0 , mImageRect . left - mCropRect . left ) , Math . max ( 0 , mImageRect . top - mCropRect . top ) ) ; mCropRect . offset ( Math . min ( 0 , mImageRect . right - mCropRect . right ) , Math . min ( 0 , mImageRect . bottom - mCropRect . bottom ) ) ; mDrawRect = computeLayout ( ) ; invalRect . union ( mDrawRect ) ; invalRect . inset ( - 10 , - 10 ) ; mContext . invalidate ( invalRect ) ; }


Input: Grows the cropping rectange by ( dx dy ) in image space . [CODESPLIT] void growBy ( float dx , float dy ) { if ( mMaintainAspectRatio ) { if ( dx != 0 ) { dy = dx / mInitialAspectRatio ; } else if ( dy != 0 ) { dx = dy * mInitialAspectRatio ; } } // Don't let the cropping rectangle grow too fast. // Grow at most half of the difference between the image rectangle and // the cropping rectangle. RectF r = new RectF ( mCropRect ) ; if ( dx > 0F && r . width ( ) + 2 * dx > mImageRect . width ( ) ) { float adjustment = ( mImageRect . width ( ) - r . width ( ) ) / 2F ; dx = adjustment ; if ( mMaintainAspectRatio ) { dy = dx / mInitialAspectRatio ; } } if ( dy > 0F && r . height ( ) + 2 * dy > mImageRect . height ( ) ) { float adjustment = ( mImageRect . height ( ) - r . height ( ) ) / 2F ; dy = adjustment ; if ( mMaintainAspectRatio ) { dx = dy * mInitialAspectRatio ; } } r . inset ( - dx , - dy ) ; // Don't let the cropping rectangle shrink too fast. final float widthCap = 25F ; if ( r . width ( ) < widthCap ) { r . inset ( - ( widthCap - r . width ( ) ) / 2F , 0F ) ; } float heightCap = mMaintainAspectRatio ? ( widthCap / mInitialAspectRatio ) : widthCap ; if ( r . height ( ) < heightCap ) { r . inset ( 0F , - ( heightCap - r . height ( ) ) / 2F ) ; } // Put the cropping rectangle inside the image rectangle. if ( r . left < mImageRect . left ) { r . offset ( mImageRect . left - r . left , 0F ) ; } else if ( r . right > mImageRect . right ) { r . offset ( - ( r . right - mImageRect . right ) , 0 ) ; } if ( r . top < mImageRect . top ) { r . offset ( 0F , mImageRect . top - r . top ) ; } else if ( r . bottom > mImageRect . bottom ) { r . offset ( 0F , - ( r . bottom - mImageRect . bottom ) ) ; } mCropRect . set ( r ) ; mDrawRect = computeLayout ( ) ; mContext . invalidate ( ) ; }


Input: Returns the cropping rectangle in image space . [CODESPLIT] public Rect getCropRect ( ) { return new Rect ( ( int ) mCropRect . left , ( int ) mCropRect . top , ( int ) mCropRect . right , ( int ) mCropRect . bottom ) ; }


Input: Maps the cropping rectangle from image space to screen space . [CODESPLIT] private Rect computeLayout ( ) { RectF r = new RectF ( mCropRect . left , mCropRect . top , mCropRect . right , mCropRect . bottom ) ; mMatrix . mapRect ( r ) ; return new Rect ( Math . round ( r . left ) , Math . round ( r . top ) , Math . round ( r . right ) , Math . round ( r . bottom ) ) ; }


Input: This needs to be called before anything else because we need the media factory . [CODESPLIT] void register ( RTEditTextListener listener , RTMediaFactory < RTImage , RTAudio , RTVideo > mediaFactory ) { mListener = listener ; mMediaFactory = mediaFactory ; }


Input: Find the start and end of the paragraph ( s ) encompassing the current selection . A paragraph spans from one \ n ( exclusive ) to the next one ( inclusive ) [CODESPLIT] public Selection getParagraphsInSelection ( ) { RTLayout layout = getRTLayout ( ) ; Selection selection = new Selection ( this ) ; int firstLine = layout . getLineForOffset ( selection . start ( ) ) ; int end = selection . isEmpty ( ) ? selection . end ( ) : selection . end ( ) - 1 ; int lastLine = layout . getLineForOffset ( end ) ; return new Selection ( layout . getLineStart ( firstLine ) , layout . getLineEnd ( lastLine ) ) ; }


Input: Sets the edit mode to plain or rich text . The text will be converted automatically to rich / plain text if autoConvert is True . [CODESPLIT] public void setRichTextEditing ( boolean useRTFormatting , boolean autoConvert ) { assertRegistration ( ) ; if ( useRTFormatting != mUseRTFormatting ) { mUseRTFormatting = useRTFormatting ; if ( autoConvert ) { RTFormat targetFormat = useRTFormatting ? RTFormat . PLAIN_TEXT : RTFormat . HTML ; setText ( getRichText ( targetFormat ) ) ; } if ( mListener != null ) { mListener . onRichTextEditingChanged ( this , mUseRTFormatting ) ; } } }


Input: Sets the edit mode to plain or rich text and updates the content at the same time . The caller needs to make sure the content matches the correct format ( if you pass in html code as plain text the editor will show the html code ) . [CODESPLIT] public void setRichTextEditing ( boolean useRTFormatting , String content ) { assertRegistration ( ) ; if ( useRTFormatting != mUseRTFormatting ) { mUseRTFormatting = useRTFormatting ; if ( mListener != null ) { mListener . onRichTextEditingChanged ( this , mUseRTFormatting ) ; } } RTText rtText = useRTFormatting ? new RTHtml < RTImage , RTAudio , RTVideo > ( RTFormat . HTML , content ) : new RTPlainText ( content ) ; setText ( rtText ) ; }


Input: Set the text for this editor . <p > It will convert the text from rich text to plain text if the editor s mode is set to use plain text . or to a spanned text ( only supported formatting ) if the editor s mode is set to use rich text <p > We need to prevent onSelectionChanged () to do anything as long as setText () hasn t finished because the Layout doesn t seem to update before setText has finished but onSelectionChanged will still be called during setText and will receive the out - dated Layout which doesn t allow us to apply styles and such . [CODESPLIT] public void setText ( RTText rtText ) { assertRegistration ( ) ; if ( rtText . getFormat ( ) instanceof RTFormat . Html ) { if ( mUseRTFormatting ) { RTText rtSpanned = rtText . convertTo ( RTFormat . SPANNED , mMediaFactory ) ; super . setText ( rtSpanned . getText ( ) , TextView . BufferType . EDITABLE ) ; addSpanWatcher ( ) ; // collect all current media Spannable text = getText ( ) ; for ( MediaSpan span : text . getSpans ( 0 , text . length ( ) , MediaSpan . class ) ) { mOriginalMedia . add ( span . getMedia ( ) ) ; } Effects . cleanupParagraphs ( this ) ; } else { RTText rtPlainText = rtText . convertTo ( RTFormat . PLAIN_TEXT , mMediaFactory ) ; super . setText ( rtPlainText . getText ( ) ) ; } } else if ( rtText . getFormat ( ) instanceof RTFormat . PlainText ) { CharSequence text = rtText . getText ( ) ; super . setText ( text == null ? "" : text . toString ( ) ) ; } onSelectionChanged ( 0 , 0 ) ; }


Input: Same as String getText ( RTFormat format ) but this method returns the RTText instead of just the actual text . [CODESPLIT] public RTText getRichText ( RTFormat format ) { assertRegistration ( ) ; RTEditable rtEditable = new RTEditable ( this ) ; return rtEditable . convertTo ( format , mMediaFactory ) ; }


Input: Add a SpanWatcher for the Changeable implementation [CODESPLIT] private void addSpanWatcher ( ) { Spannable spannable = getText ( ) ; if ( spannable . getSpans ( 0 , spannable . length ( ) , getClass ( ) ) != null ) { spannable . setSpan ( this , 0 , spannable . length ( ) , Spanned . SPAN_INCLUSIVE_INCLUSIVE ) ; } }


Input: Call this to have an effect applied to the current selection . You get the Effect object via the static data members ( e . g . RTEditText . BOLD ) . The value for most effects is a Boolean indicating whether to add or remove the effect . [CODESPLIT] public < V extends Object , C extends RTSpan < V > > void applyEffect ( Effect < V , C > effect , V value ) { if ( mUseRTFormatting && ! mIsSelectionChanging && ! mIsSaving ) { Spannable oldSpannable = mIgnoreTextChanges ? null : cloneSpannable ( ) ; effect . applyToSelection ( this , value ) ; synchronized ( this ) { if ( mListener != null && ! mIgnoreTextChanges ) { Spannable newSpannable = cloneSpannable ( ) ; mListener . onTextChanged ( this , oldSpannable , newSpannable , getSelectionStart ( ) , getSelectionEnd ( ) , getSelectionStart ( ) , getSelectionEnd ( ) ) ; } mLayoutChanged = true ; } } }


Input: space [CODESPLIT] public static RTPlainText convert ( RTHtml < ? extends RTImage , ? extends RTAudio , ? extends RTVideo > input ) { String result = Html . fromHtml ( input . getText ( ) , null , new HtmlToTextTagHandler ( ) ) . toString ( ) . replace ( PREVIEW_OBJECT_CHARACTER , PREVIEW_OBJECT_REPLACEMENT ) . replace ( NBSP_CHARACTER , NBSP_REPLACEMENT ) ; return new RTPlainText ( result ) ; }


Input: Converts this rich text to another rich text . The default implementation doesn t support any conversion except the one to itself ( which is technically no conversion ) . <p > The method has to make sure that the original rich text isn t modified . It does however not make sure that the returned RTText isn t referencing the original RTText meaning modifying the resulting object might also modify the original object . [CODESPLIT] public RTText convertTo ( RTFormat destFormat , RTMediaFactory < RTImage , RTAudio , RTVideo > mediaFactory ) { if ( destFormat == mRTFormat ) { return this ; } throw new UnsupportedOperationException ( "Can't convert from " + mRTFormat . getClass ( ) . getSimpleName ( ) + " to " + destFormat . getClass ( ) . getSimpleName ( ) ) ; }


Input: ****************************************** SpannableString Methods ******************************************* [CODESPLIT] @ Override public void setSpan ( Object what , int start , int end , int flags ) { if ( mSpanCount + 1 >= mSpans . length ) { int newsize = mSpanCount + 10 ; Object [ ] newtags = new Object [ newsize ] ; int [ ] newdata = new int [ newsize * 3 ] ; System . arraycopy ( mSpans , 0 , newtags , 0 , mSpanCount ) ; System . arraycopy ( mSpanData , 0 , newdata , 0 , mSpanCount * 3 ) ; mSpans = newtags ; mSpanData = newdata ; } mSpans [ mSpanCount ] = what ; mSpanData [ mSpanCount * COLUMNS + START ] = start ; mSpanData [ mSpanCount * COLUMNS + END ] = end ; mSpanData [ mSpanCount * COLUMNS + FLAGS ] = flags ; mSpanCount ++ ; }


Input: This method returns the spinner view [CODESPLIT] @ SuppressLint ( "ViewHolder" ) @ Override public final View getView ( int position , View convertView , ViewGroup parent ) { View spinnerView = mInflater . inflate ( mSpinnerId , parent , false ) ; mParent = parent ; TextView spinnerTitleView = ( TextView ) spinnerView . findViewById ( R . id . title ) ; updateSpinnerTitle ( spinnerTitleView ) ; return spinnerView ; }


Input: Returns the spinner entry view [CODESPLIT] @ SuppressLint ( "InlinedApi" ) @ Override public View getDropDownView ( int position , View convertView , ViewGroup parent ) { SpinnerItem spinnerItem = mItems . get ( position ) ; spinnerItem . setOnChangedListener ( this , position ) ; // we can't use the convertView because it keeps handing us spinner layouts (mSpinnerId) View spinnerItemView = mInflater . inflate ( mSpinnerItemId , parent , false ) ; int key = ( position << 16 ) + getItemViewType ( position ) ; mViewCache . put ( key , spinnerItemView ) ; bindView ( position , spinnerItemView , spinnerItem ) ; return spinnerItemView ; }


Input: Converts a spanned text to HTML [CODESPLIT] public RTHtml < RTImage , RTAudio , RTVideo > convert ( final Spanned text , RTFormat . Html rtFormat ) { mText = text ; mRTFormat = rtFormat ; mOut = new StringBuilder ( ) ; mImages = new ArrayList <> ( ) ; mParagraphStyles . clear ( ) ; // convert paragraphs convertParagraphs ( ) ; return new RTHtml <> ( rtFormat , mOut . toString ( ) , mImages ) ; }


Input:
****************************************** Process Paragraphs ******************************************* [CODESPLIT] private void convertParagraphs ( ) { RTLayout rtLayout = new RTLayout ( mText ) ; // a manual for loop is faster than the for-each loop for an ArrayList: // see https://developer.android.com/training/articles/perf-tips.html#Loops ArrayList < Paragraph > paragraphs = rtLayout . getParagraphs ( ) ; for ( int i = 0 , size = paragraphs . size ( ) ; i < size ; i ++ ) { Paragraph paragraph = paragraphs . get ( i ) ; // retrieve all spans for this paragraph Set < SingleParagraphStyle > styles = getParagraphStyles ( mText , paragraph ) ; // get the alignment span if there is any ParagraphType alignmentType = null ; for ( SingleParagraphStyle style : styles ) { if ( style . getType ( ) . isAlignment ( ) ) { alignmentType = style . getType ( ) ; break ; } } /*
             * start tag: bullet points, numbering and indentation
             */ int newIndent = 0 ; ParagraphType newType = ParagraphType . NONE ; for ( SingleParagraphStyle style : styles ) { newIndent += style . getIndentation ( ) ; ParagraphType type = style . getType ( ) ; newType = type . isBullet ( ) ? ParagraphType . BULLET : type . isNumbering ( ) ? ParagraphType . NUMBERING : type . isIndentation ( ) && newType . isUndefined ( ) ? ParagraphType . INDENTATION_UL : newType ; } // process leading margin style processLeadingMarginStyle ( new AccumulatedParagraphStyle ( newType , newIndent , 0 ) ) ; // add start list tag mOut . append ( newType . getListStartTag ( ) ) ; /*
             * start tag: alignment (left, center, right)
             */ if ( alignmentType != null ) { mOut . append ( alignmentType . getStartTag ( ) ) ; } /*
             * Convert the plain text
             */ withinParagraph ( mText , paragraph . start ( ) , paragraph . end ( ) ) ; /*
             * end tag: alignment (left, center, right)
             */ if ( alignmentType != null ) { removeTrailingLineBreak ( alignmentType ) ; mOut . append ( alignmentType . getEndTag ( ) ) ; } // add end list tag removeTrailingLineBreak ( newType ) ; mOut . append ( newType . getListEndTag ( ) ) ; } /*
         * end tag: bullet points and indentation
         */ while ( ! mParagraphStyles . isEmpty ( ) ) { removeParagraph ( ) ; } }


Input: Convert a spanned text within a paragraph [CODESPLIT] private void withinParagraph ( final Spanned text , int start , int end ) { // create sorted set of CharacterStyles SortedSet < CharacterStyle > sortedSpans = new TreeSet <> ( ( s1 , s2 ) -> { int start1 = text . getSpanStart ( s1 ) ; int start2 = text . getSpanStart ( s2 ) ; if ( start1 != start2 ) return start1 - start2 ; // span which starts first comes first int end1 = text . getSpanEnd ( s1 ) ; int end2 = text . getSpanEnd ( s2 ) ; if ( end1 != end2 ) return end2 - end1 ; // longer span comes first // if the paragraphs have the same span [start, end] we compare their name // compare the name only because local + anonymous classes have no canonical name return s1 . getClass ( ) . getName ( ) . compareTo ( s2 . getClass ( ) . getName ( ) ) ; } ) ; List < CharacterStyle > spanList = Arrays . asList ( text . getSpans ( start , end , CharacterStyle . class ) ) ; sortedSpans . addAll ( spanList ) ; // process paragraphs/divs convertText ( text , start , end , sortedSpans ) ; }


Input: Escape plain text parts : < > & Space -- > ^lt ; &gt ; etc . [CODESPLIT] private void escape ( CharSequence text , int start , int end ) { for ( int i = start ; i < end ; i ++ ) { char c = text . charAt ( i ) ; if ( c == ' ' ) { mOut . append ( BR ) ; } else if ( c == ' ' ) { mOut . append ( LT ) ; } else if ( c == ' ' ) { mOut . append ( GT ) ; } else if ( c == ' ' ) { mOut . append ( AMP ) ; } else if ( c == ' ' ) { while ( i + 1 < end && text . charAt ( i + 1 ) == ' ' ) { mOut . append ( NBSP ) ; i ++ ; } mOut . append ( ' ' ) ; } // removed the c > 0x7E check to leave emoji unaltered else if ( /*c > 0x7E || */ c < ' ' ) { mOut . append ( "&#" + ( ( int ) c ) + ";" ) ; } else { mOut . append ( c ) ; } } }


Input: Creates a file with a non - conflicting file name in a specified folder based on an existing file name . [CODESPLIT] public static File createUniqueFile ( File targetFolder , String originalFile , boolean keepOriginal ) { String mimeType = MimeTypeMap . getSingleton ( ) . getMimeTypeFromExtension ( originalFile ) ; return createUniqueFile ( targetFolder , originalFile , mimeType , keepOriginal ) ; }


Input: Creates a file Uri for a file defined by its absolute path . The method can handle the case of an absolute path ( e . g . / data / data .... ) and a Uri path containing the file : // scheme ( e . g . file : /// data / data ... ) [CODESPLIT] public static Uri createFileUri ( String path ) { if ( path . startsWith ( "file://" ) ) { return Uri . parse ( path ) ; } return Uri . fromFile ( new File ( path ) ) ; }


Input: Retrieve local file path for an arbitrary Uri [CODESPLIT] public static String determineOriginalFile ( Context context , Uri uri ) throws IllegalArgumentException { String originalFile = null ; if ( uri != null ) { // Picasa on Android >= 3.0 or other files using content providers if ( uri . getScheme ( ) . startsWith ( "content" ) ) { originalFile = getPathFromUri ( context , uri ) ; } // Picasa on Android < 3.0 if ( uri . toString ( ) . matches ( "https?://\\w+\\.googleusercontent\\.com/.+" ) ) { originalFile = uri . toString ( ) ; } // local storage if ( uri . getScheme ( ) . startsWith ( "file" ) ) { originalFile = uri . toString ( ) . substring ( 7 ) ; } if ( isNullOrEmpty ( originalFile ) ) { throw new IllegalArgumentException ( "File path was null" ) ; } } else { throw new IllegalArgumentException ( "Image Uri was null!" ) ; } return originalFile ; }


Input: Return a namespace name from a Qname . The attribute flag tells us whether to return an empty namespace name if there is no prefix or use the schema default instead . [CODESPLIT] public String namespace ( String name , boolean attribute ) { int colon = name . indexOf ( ' ' ) ; if ( colon == - 1 ) { return attribute ? "" : theSchema . getURI ( ) ; } String prefix = name . substring ( 0 , colon ) ; if ( prefix . equals ( "xml" ) ) { return "http://www.w3.org/XML/1998/namespace" ; } else { return ( "urn:x-prefix:" + prefix ) . intern ( ) ; } }


Input: Return a local name from a Qname . [CODESPLIT] public String localName ( String name ) { int colon = name . indexOf ( ' ' ) ; if ( colon == - 1 ) { return name ; } else { return name . substring ( colon + 1 ) . intern ( ) ; } }


Input: Sets an attribute and its value into an AttributesImpl object . Attempts to set a namespace declaration are ignored . [CODESPLIT] public void setAttribute ( AttributesImpl atts , String name , String type , String value ) { if ( name . equals ( "xmlns" ) || name . startsWith ( "xmlns:" ) ) { return ; } ; String namespace = namespace ( name , true ) ; String localName = localName ( name ) ; int i = atts . getIndex ( name ) ; if ( i == - 1 ) { name = name . intern ( ) ; if ( type == null ) type = "CDATA" ; if ( ! type . equals ( "CDATA" ) ) value = normalize ( value ) ; atts . addAttribute ( namespace , localName , name , type , value ) ; } else { if ( type == null ) type = atts . getType ( i ) ; if ( ! type . equals ( "CDATA" ) ) value = normalize ( value ) ; atts . setAttribute ( i , namespace , localName , name , type , value ) ; } }


Input: Normalize an attribute value ( ID - style ) . CDATA - style attribute normalization is already done . [CODESPLIT] public static String normalize ( String value ) { if ( value == null ) return value ; value = value . trim ( ) ; if ( value . indexOf ( "  " ) == - 1 ) return value ; boolean space = false ; int len = value . length ( ) ; StringBuffer b = new StringBuffer ( len ) ; for ( int i = 0 ; i < len ; i ++ ) { char v = value . charAt ( i ) ; if ( v == ' ' ) { if ( ! space ) b . append ( v ) ; space = true ; } else { b . append ( v ) ; space = false ; } } return b . toString ( ) ; }


Input: Sets an attribute and its value into this element type . [CODESPLIT] public void setAttribute ( String name , String type , String value ) { setAttribute ( theAtts , name , type , value ) ; }


Input: Append a portion of a character sequence to the { @link StringBuilder } . [CODESPLIT] @ Override public Writer append ( CharSequence value , int start , int end ) { builder . append ( value , start , end ) ; return this ; }


Input: Write a portion of a character array to the { @link StringBuilder } . [CODESPLIT] @ Override public void write ( char [ ] value , int offset , int length ) { if ( value != null ) { builder . append ( value , offset , length ) ; } }


Input: Retrieve the file name for a system font . [CODESPLIT] static String getFontName ( String filePath ) { TTFRandomAccessFile in = null ; try { RandomAccessFile file = new RandomAccessFile ( filePath , "r" ) ; in = new TTFRandomAccessFile ( file ) ; return getTTFFontName ( in , filePath ) ; } catch ( IOException e ) { return null ; // Missing permissions or corrupted font file? } finally { IOUtils . closeQuietly ( in ) ; } }


Input: Retrieve the file name for a font in the asset folder . [CODESPLIT] static String getFontName ( AssetManager assets , String filePath ) { TTFAssetInputStream in = null ; try { InputStream file = assets . open ( filePath , AssetManager . ACCESS_RANDOM ) ; in = new TTFAssetInputStream ( file ) ; return getTTFFontName ( in , filePath ) ; } catch ( FileNotFoundException e ) { return null ; // Missing permissions? } catch ( IOException e ) { return null ; // Corrupted font file? } finally { IOUtils . closeQuietly ( in ) ; } }


Input: Makes a new buffer available either by allocating a new one or re - cycling an existing one . [CODESPLIT] private void needNewBuffer ( int newcount ) { if ( currentBufferIndex < buffers . size ( ) - 1 ) { //Recycling old buffer filledBufferSum += currentBuffer . length ; currentBufferIndex ++ ; currentBuffer = buffers . get ( currentBufferIndex ) ; } else { //Creating new buffer int newBufferSize ; if ( currentBuffer == null ) { newBufferSize = newcount ; filledBufferSum = 0 ; } else { newBufferSize = Math . max ( currentBuffer . length << 1 , newcount - filledBufferSum ) ; filledBufferSum += currentBuffer . length ; } currentBufferIndex ++ ; currentBuffer = new byte [ newBufferSize ] ; buffers . add ( currentBuffer ) ; } }


Input: Write the bytes to byte array . [CODESPLIT] @ Override public void write ( byte [ ] b , int off , int len ) { if ( ( off < 0 ) || ( off > b . length ) || ( len < 0 ) || ( ( off + len ) > b . length ) || ( ( off + len ) < 0 ) ) { throw new IndexOutOfBoundsException ( ) ; } else if ( len == 0 ) { return ; } synchronized ( this ) { int newcount = count + len ; int remaining = len ; int inBufferPos = count - filledBufferSum ; while ( remaining > 0 ) { int part = Math . min ( remaining , currentBuffer . length - inBufferPos ) ; System . arraycopy ( b , off + len - remaining , currentBuffer , inBufferPos , part ) ; remaining -= part ; if ( remaining > 0 ) { needNewBuffer ( newcount ) ; inBufferPos = 0 ; } } count = newcount ; } }


Input: Write a byte to byte array . [CODESPLIT] @ Override public synchronized void write ( int b ) { int inBufferPos = count - filledBufferSum ; if ( inBufferPos == currentBuffer . length ) { needNewBuffer ( count + 1 ) ; inBufferPos = 0 ; } currentBuffer [ inBufferPos ] = ( byte ) b ; count ++ ; }


Input: Writes the entire contents of the specified input stream to this byte stream . Bytes from the input stream are read directly into the internal buffers of this streams . [CODESPLIT] public synchronized int write ( InputStream in ) throws IOException { int readCount = 0 ; int inBufferPos = count - filledBufferSum ; int n = in . read ( currentBuffer , inBufferPos , currentBuffer . length - inBufferPos ) ; while ( n != - 1 ) { readCount += n ; inBufferPos += n ; count += n ; if ( inBufferPos == currentBuffer . length ) { needNewBuffer ( currentBuffer . length ) ; inBufferPos = 0 ; } n = in . read ( currentBuffer , inBufferPos , currentBuffer . length - inBufferPos ) ; } return readCount ; }


Input: Writes the entire contents of this byte stream to the specified output stream . [CODESPLIT] public synchronized void writeTo ( OutputStream out ) throws IOException { int remaining = count ; for ( byte [ ] buf : buffers ) { int c = Math . min ( buf . length , remaining ) ; out . write ( buf , 0 , c ) ; remaining -= c ; if ( remaining == 0 ) { break ; } } }


Input: Fetches entire contents of an <code > InputStream< / code > and represent same data as result InputStream . <p > This method is useful where <ul > <li > Source InputStream is slow . < / li > <li > It has network resources associated so we cannot keep it open for long time . < / li > <li > It has network timeout associated . < / li > < / ul > It can be used in favor of { @link #toByteArray () } since it avoids unnecessary allocation and copy of byte [] . <br > This method buffers the input internally so there is no need to use a <code > BufferedInputStream< / code > . [CODESPLIT] public static InputStream toBufferedInputStream ( InputStream input ) throws IOException { ByteArrayOutputStream output = new ByteArrayOutputStream ( ) ; output . write ( input ) ; return output . toBufferedInputStream ( ) ; }


Input: Gets the current contents of this byte stream as a Input Stream . The returned stream is backed by buffers of <code > this< / code > stream avoiding memory allocation and copy thus saving space and time . <br > [CODESPLIT] private InputStream toBufferedInputStream ( ) { int remaining = count ; if ( remaining == 0 ) { return new ClosedInputStream ( ) ; } List < ByteArrayInputStream > list = new ArrayList < ByteArrayInputStream > ( buffers . size ( ) ) ; for ( byte [ ] buf : buffers ) { int c = Math . min ( buf . length , remaining ) ; list . add ( new ByteArrayInputStream ( buf , 0 , c ) ) ; remaining -= c ; if ( remaining == 0 ) { break ; } } return new SequenceInputStream ( Collections . enumeration ( list ) ) ; }


Input: Gets the curent contents of this byte stream as a byte array . The result is independent of this stream . [CODESPLIT] public synchronized byte [ ] toByteArray ( ) { int remaining = count ; if ( remaining == 0 ) { return EMPTY_BYTE_ARRAY ; } byte newbuf [ ] = new byte [ remaining ] ; int pos = 0 ; for ( byte [ ] buf : buffers ) { int c = Math . min ( buf . length , remaining ) ; System . arraycopy ( buf , 0 , newbuf , pos , c ) ; pos += c ; remaining -= c ; if ( remaining == 0 ) { break ; } } return newbuf ; }


Input: Set the text size . [CODESPLIT] @ Override public void setFontSize ( int size ) { if ( mFontSize != null ) { if ( size <= 0 ) { mFontSizeAdapter . updateSpinnerTitle ( "" ) ; mFontSizeAdapter . setSelectedItem ( 0 ) ; mFontSize . setSelection ( 0 ) ; } else { size = Helper . convertSpToPx ( size ) ; mFontSizeAdapter . updateSpinnerTitle ( Integer . toString ( size ) ) ; for ( int pos = 0 ; pos < mFontSizeAdapter . getCount ( ) ; pos ++ ) { FontSizeSpinnerItem item = mFontSizeAdapter . getItem ( pos ) ; if ( size == item . getFontSize ( ) ) { mFontSizeAdapter . setSelectedItem ( pos ) ; mFontSize . setSelection ( pos ) ; break ; } } } } }


Input: Normalizes a path removing double and single dot path steps and removing any final directory separator . <p > This method normalizes a path to a standard format . The input may contain separators in either Unix or Windows format . The output will contain separators in the format specified . <p > A trailing slash will be removed . A double slash will be merged to a single slash ( but UNC names are handled ) . A single dot path segment will be removed . A double dot will cause that path segment and the one before to be removed . If the double dot has no parent path segment to work with { @code null } is returned . <p > The output will be the same on both Unix and Windows including the separator character . <pre > / foo // -- > / foo / foo / . / -- > / foo / foo / .. / bar -- > / bar / foo / .. / bar / -- > / bar / foo / .. / bar / .. / baz -- > / baz // foo // . / bar -- > / foo / bar / .. / -- > null .. / foo -- > null foo / bar / .. -- > foo foo / .. / .. / bar -- > null foo / .. / bar -- > bar // server / foo / .. / bar -- > // server / bar // server / .. / bar -- > null C : \ foo \ .. \ bar -- > C : \ bar C : \ .. \ bar -- > null ~ / foo / .. / bar / -- > ~ / bar ~ / .. / bar -- > null < / pre > [CODESPLIT] public static String normalizeNoEndSeparator ( String filename , boolean unixSeparator ) { char separator = unixSeparator ? UNIX_SEPARATOR : WINDOWS_SEPARATOR ; return doNormalize ( filename , separator , false ) ; }


Input: Internal method to perform the normalization . [CODESPLIT] private static String doNormalize ( String filename , char separator , boolean keepSeparator ) { if ( filename == null ) { return null ; } int size = filename . length ( ) ; if ( size == 0 ) { return filename ; } int prefix = getPrefixLength ( filename ) ; if ( prefix < 0 ) { return null ; } char [ ] array = new char [ size + 2 ] ; // +1 for possible extra slash, +2 for arraycopy filename . getChars ( 0 , filename . length ( ) , array , 0 ) ; // fix separators throughout char otherSeparator = separator == SYSTEM_SEPARATOR ? OTHER_SEPARATOR : SYSTEM_SEPARATOR ; for ( int i = 0 ; i < array . length ; i ++ ) { if ( array [ i ] == otherSeparator ) { array [ i ] = separator ; } } // add extra separator on the end to simplify code below boolean lastIsDirectory = true ; if ( array [ size - 1 ] != separator ) { array [ size ++ ] = separator ; lastIsDirectory = false ; } // adjoining slashes for ( int i = prefix + 1 ; i < size ; i ++ ) { if ( array [ i ] == separator && array [ i - 1 ] == separator ) { System . arraycopy ( array , i , array , i - 1 , size - i ) ; size -- ; i -- ; } } // dot slash for ( int i = prefix + 1 ; i < size ; i ++ ) { if ( array [ i ] == separator && array [ i - 1 ] == ' ' && ( i == prefix + 1 || array [ i - 2 ] == separator ) ) { if ( i == size - 1 ) { lastIsDirectory = true ; } System . arraycopy ( array , i + 1 , array , i - 1 , size - i ) ; size -= 2 ; i -- ; } } // double dot slash outer : for ( int i = prefix + 2 ; i < size ; i ++ ) { if ( array [ i ] == separator && array [ i - 1 ] == ' ' && array [ i - 2 ] == ' ' && ( i == prefix + 2 || array [ i - 3 ] == separator ) ) { if ( i == prefix + 2 ) { return null ; } if ( i == size - 1 ) { lastIsDirectory = true ; } int j ; for ( j = i - 4 ; j >= prefix ; j -- ) { if ( array [ j ] == separator ) { // remove b/../ from a/b/../c System . arraycopy ( array , i + 1 , array , j + 1 , size - i ) ; size -= i - j ; i = j + 1 ; continue outer ; } } // remove a/../ from a/../c System . arraycopy ( array , i + 1 , array , prefix , size - i ) ; size -= i + 1 - prefix ; i = prefix + 1 ; } } if ( size <= 0 ) { // should never be less than 0 return "" ; } if ( size <= prefix ) { // should never be less than prefix return new String ( array , 0 , size ) ; } if ( lastIsDirectory && keepSeparator ) { return new String ( array , 0 , size ) ; // keep trailing separator } return new String ( array , 0 , size - 1 ) ; // lose trailing separator }


Input: Converts all separators to the Unix separator of forward slash . [CODESPLIT] public static String separatorsToUnix ( String path ) { if ( path == null || path . indexOf ( WINDOWS_SEPARATOR ) == - 1 ) { return path ; } return path . replace ( WINDOWS_SEPARATOR , UNIX_SEPARATOR ) ; }


Input: Returns the index of the last extension separator character which is a dot . <p > This method also checks that there is no directory separator after the last dot . To do this it uses { @link #indexOfLastSeparator ( String ) } which will handle a file in either Unix or Windows format . <p > The output will be the same irrespective of the machine that the code is running on . [CODESPLIT] public static int indexOfExtension ( String filename ) { if ( filename == null ) { return - 1 ; } int extensionPos = filename . lastIndexOf ( EXTENSION_SEPARATOR ) ; int lastSeparator = indexOfLastSeparator ( filename ) ; return lastSeparator > extensionPos ? - 1 : extensionPos ; }


Input: Return an array of the markup objects attached to the specified slice of a Spannable and whose type is the specified type or a subclass of it ( see Spanned . getSpans ( int int Class<T > )) . [CODESPLIT] final protected RTSpan < V > [ ] getSpansAndroid ( Spannable str , int selStart , int selEnd ) { RTSpan < V > [ ] spans = str . getSpans ( selStart , selEnd , mSpanClazz ) ; return spans == null ? ( RTSpan < V > [ ] ) Array . newInstance ( mSpanClazz ) : spans ; }


Input: hitting cropping rectangle . [CODESPLIT] private void recomputeFocus ( MotionEvent event ) { for ( int i = 0 ; i < mHighlightViews . size ( ) ; i ++ ) { HighlightView hv = mHighlightViews . get ( i ) ; hv . setFocus ( false ) ; hv . invalidate ( ) ; } for ( int i = 0 ; i < mHighlightViews . size ( ) ; i ++ ) { HighlightView hv = mHighlightViews . get ( i ) ; int edge = hv . getHit ( event . getX ( ) , event . getY ( ) ) ; if ( edge != HighlightView . GROW_NONE ) { if ( ! hv . hasFocus ( ) ) { hv . setFocus ( true ) ; hv . invalidate ( ) ; } break ; } } invalidate ( ) ; }


Input: Pan the displayed image to make sure the cropping rectangle is visible . [CODESPLIT] private void ensureVisible ( HighlightView hv ) { Rect r = hv . mDrawRect ; int panDeltaX1 = Math . max ( 0 , mLeft - r . left ) ; int panDeltaX2 = Math . min ( 0 , mRight - r . right ) ; int panDeltaY1 = Math . max ( 0 , mTop - r . top ) ; int panDeltaY2 = Math . min ( 0 , mBottom - r . bottom ) ; int panDeltaX = panDeltaX1 != 0 ? panDeltaX1 : panDeltaX2 ; int panDeltaY = panDeltaY1 != 0 ? panDeltaY1 : panDeltaY2 ; if ( panDeltaX != 0 || panDeltaY != 0 ) { panBy ( panDeltaX , panDeltaY ) ; } }


Input: view s center and scale according to the cropping rectangle . [CODESPLIT] private void centerBasedOnHighlightView ( HighlightView hv ) { Rect drawRect = hv . mDrawRect ; float width = drawRect . width ( ) ; float height = drawRect . height ( ) ; float thisWidth = getWidth ( ) ; float thisHeight = getHeight ( ) ; float z1 = thisWidth / width * .8F ; float z2 = thisHeight / height * .8F ; float zoom = Math . min ( z1 , z2 ) ; zoom = zoom * this . getScale ( ) ; zoom = Math . max ( 1F , zoom ) ; if ( ( Math . abs ( zoom - getScale ( ) ) / zoom ) > .1 ) { float [ ] coordinates = new float [ ] { hv . mCropRect . centerX ( ) , hv . mCropRect . centerY ( ) } ; getImageMatrix ( ) . mapPoints ( coordinates ) ; zoomTo ( zoom , coordinates [ 0 ] , coordinates [ 1 ] , 300F ) ; } ensureVisible ( hv ) ; }


Input: Reset document locator supplying systemid and publicid . [CODESPLIT] public void resetDocumentLocator ( String publicid , String systemid ) { thePublicid = publicid ; theSystemid = systemid ; theLastLine = theLastColumn = theCurrentLine = theCurrentColumn = 0 ; }


Input: Scan HTML source reporting lexical events . [CODESPLIT] public void scan ( Reader r0 , ScanHandler h ) throws IOException , SAXException { theState = S_PCDATA ; PushbackReader r ; if ( r0 instanceof PushbackReader ) { r = ( PushbackReader ) r0 ; } else if ( r0 instanceof BufferedReader ) { r = new PushbackReader ( r0 ) ; } else { r = new PushbackReader ( new BufferedReader ( r0 , 200 ) ) ; } int firstChar = r . read ( ) ; // Remove any leading BOM if ( firstChar != ' ' ) unread ( r , firstChar ) ; while ( theState != S_DONE ) { int c1 = r . read ( ) ; char c = ( char ) c1 ; boolean is32BitChar = Character . isHighSurrogate ( c ) ; int c2 = is32BitChar ? r . read ( ) : - 1 ; String s = is32BitChar ? new StringBuffer ( ) . append ( c ) . append ( ( char ) c2 ) . toString ( ) : null ; // Process control characters if ( ! is32BitChar && c1 >= 0x80 && c1 <= 0x9F ) c1 = theWinMap [ c1 - 0x80 ] ; if ( ! is32BitChar && c1 == ' ' ) { c1 = r . read ( ) ; // expect LF next if ( c1 != ' ' ) { unread ( r , c1 ) ; // nope c1 = ' ' ; } } if ( ! is32BitChar && c1 == ' ' ) { theCurrentLine ++ ; theCurrentColumn = 0 ; } else { theCurrentColumn ++ ; } if ( ! ! is32BitChar && ! ( c1 >= 0x20 || c1 == ' ' || c1 == ' ' || c1 == - 1 ) ) continue ; // Search state table int action = 0 ; for ( int i = 0 ; i < statetable . length ; i += 4 ) { if ( theState != statetable [ i ] ) { if ( action != 0 ) break ; continue ; } if ( statetable [ i + 1 ] == 0 ) { action = statetable [ i + 2 ] ; theNextState = statetable [ i + 3 ] ; } else if ( ! is32BitChar && statetable [ i + 1 ] == c1 ) { action = statetable [ i + 2 ] ; theNextState = statetable [ i + 3 ] ; break ; } } switch ( action ) { case 0 : throw new Error ( "HTMLScanner can't cope with " + Integer . toString ( c1 ) + " in state " + Integer . toString ( theState ) ) ; case A_ADUP : h . adup ( theOutputBuffer , 0 , theSize ) ; theSize = 0 ; break ; case A_ADUP_SAVE : h . adup ( theOutputBuffer , 0 , theSize ) ; theSize = 0 ; if ( s != null ) save ( s , c1 , h ) ; break ; case A_ADUP_STAGC : h . adup ( theOutputBuffer , 0 , theSize ) ; theSize = 0 ; h . stagc ( theOutputBuffer , 0 , theSize ) ; break ; case A_ANAME : h . aname ( theOutputBuffer , 0 , theSize ) ; theSize = 0 ; break ; case A_ANAME_ADUP : h . aname ( theOutputBuffer , 0 , theSize ) ; theSize = 0 ; h . adup ( theOutputBuffer , 0 , theSize ) ; break ; case A_ANAME_ADUP_STAGC : h . aname ( theOutputBuffer , 0 , theSize ) ; theSize = 0 ; h . adup ( theOutputBuffer , 0 , theSize ) ; h . stagc ( theOutputBuffer , 0 , theSize ) ; break ; case A_AVAL : h . aval ( theOutputBuffer , 0 , theSize ) ; theSize = 0 ; break ; case A_AVAL_STAGC : h . aval ( theOutputBuffer , 0 , theSize ) ; theSize = 0 ; h . stagc ( theOutputBuffer , 0 , theSize ) ; break ; case A_CDATA : mark ( ) ; // suppress the final "]]" in the buffer if ( theSize > 1 ) theSize -= 2 ; h . pcdata ( theOutputBuffer , 0 , theSize ) ; theSize = 0 ; break ; case A_ENTITY_START : h . pcdata ( theOutputBuffer , 0 , theSize ) ; theSize = 0 ; save ( s , c1 , h ) ; break ; case A_ENTITY : mark ( ) ; if ( theState == S_ENT && c == ' ' ) { theNextState = S_NCR ; save ( s , c1 , h ) ; break ; } else if ( theState == S_NCR && ( c == ' ' || c == ' ' ) ) { theNextState = S_XNCR ; save ( s , c1 , h ) ; break ; } else if ( theState == S_ENT && Character . isLetterOrDigit ( c ) ) { save ( s , c1 , h ) ; break ; } else if ( theState == S_NCR && Character . isDigit ( c ) ) { save ( s , c1 , h ) ; break ; } else if ( theState == S_XNCR && ( Character . isDigit ( c ) || "abcdefABCDEF" . indexOf ( c ) != - 1 ) ) { save ( s , c1 , h ) ; break ; } // The whole entity reference has been collected h . entity ( theOutputBuffer , 1 , theSize - 1 ) ; int ent = h . getEntity ( ) ; if ( ent != 0 ) { theSize = 0 ; if ( ent >= 0x80 && ent <= 0x9F ) { ent = theWinMap [ ent - 0x80 ] ; } if ( ent < 0x20 ) { // Control becomes space ent = 0x20 ; } else if ( ent >= 0xD800 && ent <= 0xDFFF ) { // Surrogates get dropped ent = 0 ; } else if ( ent <= 0xFFFF ) { // BMP character save ( ent , h ) ; } else { // Astral converted to two surrogates ent -= 0x10000 ; save ( ( ent >> 10 ) + 0xD800 , h ) ; save ( ( ent & 0x3FF ) + 0xDC00 , h ) ; } if ( is32BitChar || c1 != ' ' ) { if ( is32BitChar ) { unread ( r , c2 ) ; theCurrentColumn -- ; } unread ( r , c1 ) ; theCurrentColumn -- ; } } else { if ( is32BitChar ) { unread ( r , c2 ) ; theCurrentColumn -- ; } unread ( r , c1 ) ; theCurrentColumn -- ; } theNextState = S_PCDATA ; break ; case A_ETAG : h . etag ( theOutputBuffer , 0 , theSize ) ; theSize = 0 ; break ; case A_DECL : h . decl ( theOutputBuffer , 0 , theSize ) ; theSize = 0 ; break ; case A_GI : h . gi ( theOutputBuffer , 0 , theSize ) ; theSize = 0 ; break ; case A_GI_STAGC : h . gi ( theOutputBuffer , 0 , theSize ) ; theSize = 0 ; h . stagc ( theOutputBuffer , 0 , theSize ) ; break ; case A_LT : mark ( ) ; save ( ' ' , h ) ; save ( s , c1 , h ) ; break ; case A_LT_PCDATA : mark ( ) ; save ( ' ' , h ) ; h . pcdata ( theOutputBuffer , 0 , theSize ) ; theSize = 0 ; break ; case A_PCDATA : mark ( ) ; h . pcdata ( theOutputBuffer , 0 , theSize ) ; theSize = 0 ; break ; case A_CMNT : mark ( ) ; h . cmnt ( theOutputBuffer , 0 , theSize ) ; theSize = 0 ; break ; case A_MINUS3 : save ( ' ' , h ) ; save ( ' ' , h ) ; break ; case A_MINUS2 : save ( ' ' , h ) ; save ( ' ' , h ) ; // fall through into A_MINUS case A_MINUS : save ( ' ' , h ) ; save ( s , c1 , h ) ; break ; case A_PI : mark ( ) ; h . pi ( theOutputBuffer , 0 , theSize ) ; theSize = 0 ; break ; case A_PITARGET : h . pitarget ( theOutputBuffer , 0 , theSize ) ; theSize = 0 ; break ; case A_PITARGET_PI : h . pitarget ( theOutputBuffer , 0 , theSize ) ; theSize = 0 ; h . pi ( theOutputBuffer , 0 , theSize ) ; break ; case A_SAVE : save ( s , c1 , h ) ; break ; case A_SKIP : break ; case A_SP : save ( ' ' , h ) ; break ; case A_STAGC : h . stagc ( theOutputBuffer , 0 , theSize ) ; theSize = 0 ; break ; case A_EMPTYTAG : mark ( ) ; if ( theSize > 0 ) h . gi ( theOutputBuffer , 0 , theSize ) ; theSize = 0 ; h . stage ( theOutputBuffer , 0 , theSize ) ; break ; case A_UNGET : unread ( r , c1 ) ; theCurrentColumn -- ; break ; case A_UNSAVE_PCDATA : if ( theSize > 0 ) theSize -- ; h . pcdata ( theOutputBuffer , 0 , theSize ) ; theSize = 0 ; break ; default : throw new Error ( "Can't process state " + action ) ; } theState = theNextState ; } h . eof ( theOutputBuffer , 0 , 0 ) ; }


Input: Validate a value against the set of regular expressions returning a String value of the aggregated groups . [CODESPLIT] public String validate ( String value ) { if ( value == null ) { return null ; } for ( int i = 0 ; i < patterns . length ; i ++ ) { Matcher matcher = patterns [ i ] . matcher ( value ) ; if ( matcher . matches ( ) ) { int count = matcher . groupCount ( ) ; if ( count == 1 ) { return matcher . group ( 1 ) ; } StringBuffer buffer = new StringBuffer ( ) ; for ( int j = 0 ; j < count ; j ++ ) { String component = matcher . group ( j + 1 ) ; if ( component != null ) { buffer . append ( component ) ; } } return buffer . toString ( ) ; } } return null ; }


Input: The paragraph is selected by the Selection if : <p > - they have at least one character in common - the selection is a point within the paragraph ( 01 \ n - > 0 till 2 intersects while the span is [ 0 3 ] ) - the selection is a point within or at the end of the LAST paragraph ( 01 - > 0 till 2 intersects while the span is [ 0 2 ] ) e . g . [ 10 10 ] will intersect the paragraph [ 0 10 ] only if it s the last paragraph [CODESPLIT] public boolean isSelected ( Selection sel ) { if ( sel == null ) { return false ; } if ( sel . isEmpty ( ) ) { // selection is a point boolean isCompletelyWithin = sel . start ( ) >= start ( ) && sel . end ( ) < end ( ) ; // selection is completely within paragraph (not at the end) boolean isWithin = sel . start ( ) >= start ( ) && sel . end ( ) <= end ( ) ; // selection is within or at the end of the paragraph return isCompletelyWithin || ( isWithin && mIsLast ) ; } else { // selection is a range --> at least one character in common int start = Math . max ( start ( ) , sel . start ( ) ) ; int end = Math . min ( end ( ) , sel . end ( ) ) ; return start < end ; } }


Input: Indicates whether the <code > Reader< / code > has more lines . If there is an <code > IOException< / code > then { @link #close () } will be called on this instance . [CODESPLIT] public boolean hasNext ( ) { if ( cachedLine != null ) { return true ; } else if ( finished ) { return false ; } else { try { while ( true ) { String line = bufferedReader . readLine ( ) ; if ( line == null ) { finished = true ; return false ; } else if ( isValidLine ( line ) ) { cachedLine = line ; return true ; } } } catch ( IOException ioe ) { close ( ) ; throw new IllegalStateException ( ioe ) ; } } }


Input: Returns the next line in the wrapped <code > Reader< / code > . [CODESPLIT] public String nextLine ( ) { if ( ! hasNext ( ) ) { throw new NoSuchElementException ( "No more lines" ) ; } String currentLine = cachedLine ; cachedLine = null ; return currentLine ; }


Input: Add or replace an element type for this schema . [CODESPLIT] @ SuppressLint ( "DefaultLocale" ) public void elementType ( String name , int model , int memberOf , int flags ) { ElementType e = new ElementType ( name , model , memberOf , flags , this ) ; theElementTypes . put ( name . toLowerCase ( ) , e ) ; if ( memberOf == M_ROOT ) theRoot = e ; }


Input: Add or replace a default attribute for an element type in this schema . [CODESPLIT] public void attribute ( String elemName , String attrName , String type , String value ) { ElementType e = getElementType ( elemName ) ; if ( e == null ) { throw new Error ( "Attribute " + attrName + " specified for unknown element type " + elemName ) ; } e . setAttribute ( attrName , type , value ) ; }


Input: Specify natural parent of an element in this schema . [CODESPLIT] public void parent ( String name , String parentName ) { ElementType child = getElementType ( name ) ; ElementType parent = getElementType ( parentName ) ; if ( child == null ) { throw new Error ( "No child " + name + " for parent " + parentName ) ; } if ( parent == null ) { throw new Error ( "No parent " + parentName + " for child " + name ) ; } child . setParent ( parent ) ; }


Input: Get an ElementType by name . [CODESPLIT] @ SuppressLint ( "DefaultLocale" ) public ElementType getElementType ( String name ) { return ( ElementType ) ( theElementTypes . get ( name . toLowerCase ( ) ) ) ; }


Input: Get an entity value by name . [CODESPLIT] public int getEntity ( String name ) { // System.err.println("%% Looking up entity " + name); Integer ch = ( Integer ) theEntities . get ( name ) ; if ( ch == null ) return 0 ; return ch . intValue ( ) ; }


Input: TODO : on Android M we need to ask the WRITE_EXTERNAL_STORAGE permission explicitly [CODESPLIT] private boolean takePicture ( ) { try { // Create an image file name (must be in "public area" or the camera app might not be able to access the file) File imagePath = Environment . getExternalStoragePublicDirectory ( Environment . DIRECTORY_PICTURES ) ; File imageFile = MediaUtils . createUniqueFile ( imagePath , CAPTURED_IMAGE_TEMPLATE , false ) ; imagePath . mkdirs ( ) ; if ( imagePath . exists ( ) && imageFile . createNewFile ( ) ) { setOriginalFile ( imageFile . getAbsolutePath ( ) ) ; Uri uriForCamera ; if ( Build . VERSION . SDK_INT < Build . VERSION_CODES . LOLLIPOP ) { // There are compatibility issues with FileProvider Uris on lower versions uriForCamera = Uri . fromFile ( imageFile ) ; } else { uriForCamera = FileProvider . getUriForFile ( mActivity , "com.onegravity.rteditor.fileprovider" , imageFile ) ; } Intent intent = new Intent ( MediaStore . ACTION_IMAGE_CAPTURE ) . putExtra ( MediaStore . EXTRA_OUTPUT , uriForCamera ) ; startActivity ( intent ) ; } else { Toast . makeText ( mActivity , "Can't take picture without an sdcard" , Toast . LENGTH_SHORT ) . show ( ) ; return false ; } } catch ( Exception e ) { Log . e ( getClass ( ) . getSimpleName ( ) , e . getMessage ( ) , e ) ; } return true ; }


Input: Returns true if the authority is properly formatted . An authority is the combination of hostname and port . A <code > null< / code > authority value is considered invalid . Note : this implementation validates the domain unless a RegexValidator was provided . If a RegexValidator was supplied and it matches then the authority is regarded as valid with no further checks otherwise the method checks against the AUTHORITY_PATTERN and the DomainValidator ( ALLOW_LOCAL_URLS ) [CODESPLIT] protected boolean isValidAuthority ( String authority ) { if ( authority == null ) { return false ; } // check manual authority validation if specified if ( authorityValidator != null && authorityValidator . isValid ( authority ) ) { return true ; } // convert to ASCII if possible final String authorityASCII = DomainValidator . unicodeToASCII ( authority ) ; Matcher authorityMatcher = AUTHORITY_PATTERN . matcher ( authorityASCII ) ; if ( ! authorityMatcher . matches ( ) ) { return false ; } String hostLocation = authorityMatcher . group ( PARSE_AUTHORITY_HOST_IP ) ; // check if authority is hostname or IP address: // try a hostname first since that's much more likely DomainValidator domainValidator = DomainValidator . getInstance ( isOn ( ALLOW_LOCAL_URLS ) ) ; if ( ! domainValidator . isValid ( hostLocation ) ) { // try an IP address InetAddressValidator inetAddressValidator = InetAddressValidator . getInstance ( ) ; if ( ! inetAddressValidator . isValid ( hostLocation ) ) { // isn't either one, so the URL is invalid return false ; } } String port = authorityMatcher . group ( PARSE_AUTHORITY_PORT ) ; if ( port != null && ! PORT_PATTERN . matcher ( port ) . matches ( ) ) { return false ; } String extra = authorityMatcher . group ( PARSE_AUTHORITY_EXTRA ) ; if ( extra != null && extra . trim ( ) . length ( ) > 0 ) { return false ; } return true ; }


Input: Returns true if the path is valid . A <code > null< / code > value is considered invalid . [CODESPLIT] protected boolean isValidPath ( String path ) { if ( path == null ) { return false ; } if ( ! PATH_PATTERN . matcher ( path ) . matches ( ) ) { return false ; } int slash2Count = countToken ( "//" , path ) ; if ( isOff ( ALLOW_2_SLASHES ) && ( slash2Count > 0 ) ) { return false ; } int slashCount = countToken ( "/" , path ) ; int dot2Count = countToken ( ".." , path ) ; if ( dot2Count > 0 && ( slashCount - slash2Count - 1 ) <= dot2Count ) { return false ; } return true ; }


Input: This important method makes sure that all paragraph effects are applied to whole paragraphs . While it s optimized for performance it s still an expensive operation so it shouldn t be called too often . [CODESPLIT] public static void cleanupParagraphs ( RTEditText editor , Effect ... exclude ) { cleanupParagraphs ( editor , Effects . ALIGNMENT , exclude ) ; cleanupParagraphs ( editor , Effects . INDENTATION , exclude ) ; cleanupParagraphs ( editor , Effects . BULLET , exclude ) ; cleanupParagraphs ( editor , Effects . NUMBER , exclude ) ; }


Input: Returns the absolute file path for a certain RTMediaType . <p > The media type specific path as provided by RTMediaType is appended to the storage path ( e . g . <storage area > / images for image files ) . [CODESPLIT] protected String getAbsolutePath ( RTMediaType mediaType ) { File mediaPath = new File ( mStoragePath . getAbsolutePath ( ) , mediaType . mediaPath ( ) ) ; if ( ! mediaPath . exists ( ) ) { mediaPath . mkdirs ( ) ; } return mediaPath . getAbsolutePath ( ) ; }


Input: / * Use case 1 : Inserting media objects into the rich text editor . [CODESPLIT] @ Override /* @inheritDoc */ public RTImage createImage ( RTMediaSource mediaSource ) { File targetFile = loadMedia ( mediaSource ) ; return targetFile == null ? null : new RTImageImpl ( targetFile . getAbsolutePath ( ) ) ; }


Input: Apply this effect to the selection . If value is Null then the effect will be removed from the current selection . [CODESPLIT] public void applyToSelection ( RTEditText editor , V value ) { Selection selection = getSelection ( editor ) ; // SPAN_INCLUSIVE_INCLUSIVE is default for empty spans int flags = selection . isEmpty ( ) ? Spanned . SPAN_INCLUSIVE_INCLUSIVE : Spanned . SPAN_EXCLUSIVE_INCLUSIVE ; Spannable str = editor . getText ( ) ; for ( RTSpan < V > span : getSpans ( str , selection , SpanCollectMode . SPAN_FLAGS ) ) { boolean sameSpan = span . getValue ( ) . equals ( value ) ; int spanStart = str . getSpanStart ( span ) ; if ( spanStart < selection . start ( ) ) { // process preceding spans if ( sameSpan ) { // we have a preceding span --> use SPAN_EXCLUSIVE_INCLUSIVE instead of SPAN_INCLUSIVE_INCLUSIVE flags = Spanned . SPAN_EXCLUSIVE_INCLUSIVE ; selection . offset ( selection . start ( ) - spanStart , 0 ) ; } else { str . setSpan ( newSpan ( span . getValue ( ) ) , spanStart , selection . start ( ) , Spanned . SPAN_EXCLUSIVE_EXCLUSIVE ) ; } } int spanEnd = str . getSpanEnd ( span ) ; if ( spanEnd > selection . end ( ) ) { // process succeeding spans if ( sameSpan ) { selection . offset ( 0 , spanEnd - selection . end ( ) ) ; } else { str . setSpan ( newSpan ( span . getValue ( ) ) , selection . end ( ) , spanEnd , Spanned . SPAN_EXCLUSIVE_INCLUSIVE ) ; } } str . removeSpan ( span ) ; } if ( value != null ) { RTSpan < V > newSpan = newSpan ( value ) ; if ( newSpan != null ) { str . setSpan ( newSpan , selection . start ( ) , selection . end ( ) , flags ) ; } } }


Input: <p > Checks if a field has a valid e - mail address . < / p > [CODESPLIT] public boolean isValid ( String email ) { if ( email == null ) { return false ; } if ( email . endsWith ( "." ) ) { // check this first - it's cheap! return false ; } // Check the whole email address structure Matcher emailMatcher = EMAIL_PATTERN . matcher ( email ) ; if ( ! emailMatcher . matches ( ) ) { return false ; } if ( ! isValidUser ( emailMatcher . group ( 1 ) ) ) { return false ; } if ( ! isValidDomain ( emailMatcher . group ( 2 ) ) ) { return false ; } return true ; }


Input: Returns true if the domain component of an email address is valid . [CODESPLIT] protected boolean isValidDomain ( String domain ) { // see if domain is an IP address in brackets Matcher ipDomainMatcher = IP_DOMAIN_PATTERN . matcher ( domain ) ; if ( ipDomainMatcher . matches ( ) ) { InetAddressValidator inetAddressValidator = InetAddressValidator . getInstance ( ) ; return inetAddressValidator . isValid ( ipDomainMatcher . group ( 1 ) ) ; } // Domain is symbolic name DomainValidator domainValidator = DomainValidator . getInstance ( allowLocal ) ; return domainValidator . isValid ( domain ) || domainValidator . isValidTld ( domain ) ; }


Input:
TODO finding links doesn t work with right alignment and potentially other formatting options [CODESPLIT] private int getCharIndexAt ( TextView textView , MotionEvent event ) { // get coordinates int x = ( int ) event . getX ( ) ; int y = ( int ) event . getY ( ) ; x -= textView . getTotalPaddingLeft ( ) ; y -= textView . getTotalPaddingTop ( ) ; x += textView . getScrollX ( ) ; y += textView . getScrollY ( ) ; /*
         * Fail-fast check of the line bound.
         * If we're not within the line bound no character was touched
         */ Layout layout = textView . getLayout ( ) ; int line = layout . getLineForVertical ( y ) ; synchronized ( sLineBounds ) { layout . getLineBounds ( line , sLineBounds ) ; if ( ! sLineBounds . contains ( x , y ) ) { return - 1 ; } } // retrieve line text Spanned text = ( Spanned ) textView . getText ( ) ; int lineStart = layout . getLineStart ( line ) ; int lineEnd = layout . getLineEnd ( line ) ; int lineLength = lineEnd - lineStart ; if ( lineLength == 0 ) { return - 1 ; } Spanned lineText = ( Spanned ) text . subSequence ( lineStart , lineEnd ) ; // compute leading margin and subtract it from the x coordinate int margin = 0 ; LeadingMarginSpan [ ] marginSpans = lineText . getSpans ( 0 , lineLength , LeadingMarginSpan . class ) ; if ( marginSpans != null ) { for ( LeadingMarginSpan span : marginSpans ) { margin += span . getLeadingMargin ( true ) ; } } x -= margin ; // retrieve text widths float [ ] widths = new float [ lineLength ] ; TextPaint paint = textView . getPaint ( ) ; paint . getTextWidths ( lineText , 0 , lineLength , widths ) ; // scale text widths by relative font size (absolute size / default size) final float defaultSize = textView . getTextSize ( ) ; float scaleFactor = 1f ; AbsoluteSizeSpan [ ] absSpans = lineText . getSpans ( 0 , lineLength , AbsoluteSizeSpan . class ) ; if ( absSpans != null ) { for ( AbsoluteSizeSpan span : absSpans ) { int spanStart = lineText . getSpanStart ( span ) ; int spanEnd = lineText . getSpanEnd ( span ) ; scaleFactor = span . getSize ( ) / defaultSize ; int start = Math . max ( lineStart , spanStart ) ; int end = Math . min ( lineEnd , spanEnd ) ; for ( int i = start ; i < end ; i ++ ) { widths [ i ] *= scaleFactor ; } } } // find index of touched character float startChar = 0 ; float endChar = 0 ; for ( int i = 0 ; i < lineLength ; i ++ ) { startChar = endChar ; endChar += widths [ i ] ; if ( endChar >= x ) { // which "end" is closer to x, the start or the end of the character? int index = lineStart + ( x - startChar < endChar - x ? i : i + 1 ) ; //Logger.e(Logger.LOG_TAG, "Found character: " + (text.length()>index ? text.charAt(index) : "")); return index ; } } return - 1 ; }


Input: Call this when an operation is performed to add it to the undo stack . [CODESPLIT] synchronized void executed ( RTEditText editor , Operation op ) { Stack < Operation > undoStack = getUndoStack ( editor ) ; Stack < Operation > redoStack = getRedoStack ( editor ) ; // if operations are executed in a quick succession we "merge" them to have but one // -> saves memory and makes more sense from a user perspective (each key stroke an undo? -> no way) while ( ! undoStack . empty ( ) && op . canMerge ( undoStack . peek ( ) ) ) { Operation previousOp = undoStack . pop ( ) ; op . merge ( previousOp ) ; } push ( op , undoStack ) ; redoStack . clear ( ) ; }


Input: Re - do the last undone operation for a specific rich text editor [CODESPLIT] synchronized void redo ( RTEditText editor ) { Stack < Operation > redoStack = getRedoStack ( editor ) ; if ( ! redoStack . empty ( ) ) { Stack < Operation > undoStack = getUndoStack ( editor ) ; Operation op = redoStack . pop ( ) ; push ( op , undoStack ) ; op . redo ( editor ) ; while ( ! redoStack . empty ( ) && op . canMerge ( redoStack . peek ( ) ) ) { op = redoStack . pop ( ) ; push ( op , undoStack ) ; op . redo ( editor ) ; } } }


Input: Flush all operations for a specific rich text editor ( method unused at the moment ) [CODESPLIT] synchronized void flushOperations ( RTEditText editor ) { Stack < Operation > undoStack = getUndoStack ( editor ) ; Stack < Operation > redoStack = getRedoStack ( editor ) ; undoStack . clear ( ) ; redoStack . clear ( ) ; }


Input: ****************************************** Private Methods ******************************************* [CODESPLIT] private void push ( Operation op , Stack < Operation > stack ) { if ( stack . size ( ) >= MAX_NR_OF_OPERATIONS ) { stack . remove ( 0 ) ; } stack . push ( op ) ; }


Input: A memory optimized algorithm for String . replaceAll [CODESPLIT] private static String replaceAll ( String source , String search , String replace ) { if ( USE_REPLACE_ALL ) { return source . replaceAll ( search , replace ) ; } else { Pattern p = Pattern . compile ( search ) ; Matcher m = p . matcher ( source ) ; StringBuffer sb = new StringBuffer ( ) ; boolean atLeastOneFound = false ; while ( m . find ( ) ) { m . appendReplacement ( sb , replace ) ; atLeastOneFound = true ; } if ( atLeastOneFound ) { m . appendTail ( sb ) ; return sb . toString ( ) ; } else { return source ; } } }


Input: Get thread status and create one if specified . [CODESPLIT] private synchronized ThreadStatus getOrCreateThreadStatus ( Thread t ) { ThreadStatus status = mThreadStatus . get ( t ) ; if ( status == null ) { status = new ThreadStatus ( ) ; mThreadStatus . put ( t , status ) ; } return status ; }


Input: The following three methods are used to keep track of BitmapFaction . Options used for decoding and cancelling . [CODESPLIT] private synchronized void setDecodingOptions ( Thread t , BitmapFactory . Options options ) { getOrCreateThreadStatus ( t ) . mOptions = options ; }


Input: The following three methods are used to keep track of which thread is being disabled for bitmap decoding . [CODESPLIT] public synchronized boolean canThreadDecoding ( Thread t ) { ThreadStatus status = mThreadStatus . get ( t ) ; if ( status == null ) { // allow decoding by default return true ; } return ( status . mState != State . CANCEL ) ; }


Input: The real place to delegate bitmap decoding to BitmapFactory . [CODESPLIT] public Bitmap decodeFileDescriptor ( FileDescriptor fd , BitmapFactory . Options options ) { if ( options . mCancel ) { return null ; } Thread thread = Thread . currentThread ( ) ; if ( ! canThreadDecoding ( thread ) ) { return null ; } setDecodingOptions ( thread , options ) ; Bitmap b = BitmapFactory . decodeFileDescriptor ( fd , null , options ) ; removeDecodingOptions ( thread ) ; return b ; }


Input: Use this method to preload fonts asynchronously e . g . when the app starts up . [CODESPLIT] public static void preLoadFonts ( final Context context ) { new Thread ( ( ) -> { synchronized ( ASSET_FONTS_BY_NAME ) { getAssetFonts ( context ) ; } synchronized ( SYSTEM_FONTS_BY_NAME ) { getSystemFonts ( ) ; } } ) . start ( ) ; }


Input:
Retrieve the fonts from the asset and the system folder . [CODESPLIT] public static SortedSet < RTTypeface > getFonts ( Context context ) { /*
         * Fonts from the assets folder
         */ Map < String , String > assetFonts = getAssetFonts ( context ) ; AssetManager assets = context . getResources ( ) . getAssets ( ) ; for ( String fontName : assetFonts . keySet ( ) ) { String filePath = assetFonts . get ( fontName ) ; if ( ! ALL_FONTS . contains ( fontName ) ) { try { Typeface typeface = Typeface . createFromAsset ( assets , filePath ) ; ALL_FONTS . add ( new RTTypeface ( fontName , typeface ) ) ; } catch ( Exception e ) { // this can happen if we don't have access to the font or it's not a font or... } } } /*
         * Fonts from the system
         */ Map < String , String > systemFonts = getSystemFonts ( ) ; for ( String fontName : systemFonts . keySet ( ) ) { String filePath = systemFonts . get ( fontName ) ; if ( ! ALL_FONTS . contains ( fontName ) ) { try { Typeface typeface = Typeface . createFromFile ( filePath ) ; ALL_FONTS . add ( new RTTypeface ( fontName , typeface ) ) ; } catch ( Exception e ) { // this can happen if we don't have access to the font or it's not a font or... } } } return ALL_FONTS ; }


Input:
Retrieve the fonts from the asset folder . [CODESPLIT] private static Map < String , String > getAssetFonts ( Context context ) { synchronized ( ASSET_FONTS_BY_NAME ) { /*
             * Let's do this only once because it's expensive and the result won't change in any case.
             */ if ( ASSET_FONTS_BY_NAME . isEmpty ( ) ) { AssetManager assets = context . getResources ( ) . getAssets ( ) ; Collection < String > fontFiles = AssetIndex . getAssetIndex ( context ) ; if ( fontFiles == null || fontFiles . isEmpty ( ) ) { fontFiles = listFontFiles ( context . getResources ( ) ) ; } for ( String filePath : fontFiles ) { if ( filePath . toLowerCase ( Locale . getDefault ( ) ) . endsWith ( "ttf" ) ) { String fontName = TTFAnalyzer . getFontName ( assets , filePath ) ; if ( fontName == null ) { fontName = getFileName ( filePath ) ; } ASSET_FONTS_BY_NAME . put ( fontName , filePath ) ; } } } return ASSET_FONTS_BY_NAME ; } }


Input: Retrieve the fonts from the system folders . [CODESPLIT] private static Map < String , String > getSystemFonts ( ) { synchronized ( SYSTEM_FONTS_BY_NAME ) { for ( String fontDir : FONT_DIRS ) { File dir = new File ( fontDir ) ; if ( ! dir . exists ( ) ) continue ; File [ ] files = dir . listFiles ( ) ; if ( files == null ) continue ; for ( File file : files ) { String filePath = file . getAbsolutePath ( ) ; if ( ! SYSTEM_FONTS_BY_PATH . containsKey ( filePath ) ) { String fontName = TTFAnalyzer . getFontName ( file . getAbsolutePath ( ) ) ; if ( fontName == null ) { fontName = getFileName ( filePath ) ; } SYSTEM_FONTS_BY_PATH . put ( filePath , fontName ) ; SYSTEM_FONTS_BY_NAME . put ( fontName , filePath ) ; } } } return SYSTEM_FONTS_BY_NAME ; } }


Input: Get contents of an <code > InputStream< / code > as a <code > byte [] < / code > . Use this method instead of <code > toByteArray ( InputStream ) < / code > when <code > InputStream< / code > size is known . <b > NOTE : < / b > the method checks that the length can safely be cast to an int without truncation before using { @link IOUtils#toByteArray ( java . io . InputStream int ) } to read into the byte array . ( Arrays can have no more than Integer . MAX_VALUE entries anyway ) [CODESPLIT] public static byte [ ] toByteArray ( InputStream input , long size ) throws IOException { if ( size > Integer . MAX_VALUE ) { throw new IllegalArgumentException ( "Size cannot be greater than Integer max value: " + size ) ; } return toByteArray ( input , ( int ) size ) ; }


Input: Get the contents of an <code > InputStream< / code > as a <code > byte [] < / code > . Use this method instead of <code > toByteArray ( InputStream ) < / code > when <code > InputStream< / code > size is known [CODESPLIT] public static byte [ ] toByteArray ( InputStream input , int size ) throws IOException { if ( size < 0 ) { throw new IllegalArgumentException ( "Size must be equal or greater than zero: " + size ) ; } if ( size == 0 ) { return new byte [ 0 ] ; } byte [ ] data = new byte [ size ] ; int offset = 0 ; int readed ; while ( offset < size && ( readed = input . read ( data , offset , size - offset ) ) != EOF ) { offset += readed ; } if ( offset != size ) { throw new IOException ( "Unexpected readed size. current: " + offset + ", excepted: " + size ) ; } return data ; }


Input: Get the contents of a <code > Reader< / code > as a <code > byte [] < / code > using the specified character encoding . <p / > This method buffers the input internally so there is no need to use a <code > BufferedReader< / code > . [CODESPLIT] public static byte [ ] toByteArray ( Reader input , Charset encoding ) throws IOException { ByteArrayOutputStream output = new ByteArrayOutputStream ( ) ; copy ( input , output , encoding ) ; return output . toByteArray ( ) ; }


Input: Get the contents of a <code > Reader< / code > as a <code > byte [] < / code > using the specified character encoding . <p / > Character encoding names can be found at <a href = http : // www . iana . org / assignments / character - sets > IANA< / a > . <p / > This method buffers the input internally so there is no need to use a <code > BufferedReader< / code > . [CODESPLIT] public static byte [ ] toByteArray ( Reader input , String encoding ) throws IOException { return toByteArray ( input , Charsets . toCharset ( encoding ) ) ; }


Input: Get the contents of a <code > URL< / code > as a <code > byte [] < / code > . [CODESPLIT] public static byte [ ] toByteArray ( URL url ) throws IOException { URLConnection conn = url . openConnection ( ) ; try { return IOUtils . toByteArray ( conn ) ; } finally { close ( conn ) ; } }


Input: Get the contents of a <code > URLConnection< / code > as a <code > byte [] < / code > . [CODESPLIT] public static byte [ ] toByteArray ( URLConnection urlConn ) throws IOException { InputStream inputStream = urlConn . getInputStream ( ) ; try { return IOUtils . toByteArray ( inputStream ) ; } finally { inputStream . close ( ) ; } }


Input: Get the contents of an <code > InputStream< / code > as a character array using the specified character encoding . <p / > This method buffers the input internally so there is no need to use a <code > BufferedInputStream< / code > . [CODESPLIT] public static char [ ] toCharArray ( InputStream is , Charset encoding ) throws IOException { CharArrayWriter output = new CharArrayWriter ( ) ; copy ( is , output , encoding ) ; return output . toCharArray ( ) ; }


Input: Get the contents of an <code > InputStream< / code > as a character array using the specified character encoding . <p / > Character encoding names can be found at <a href = http : // www . iana . org / assignments / character - sets > IANA< / a > . <p / > This method buffers the input internally so there is no need to use a <code > BufferedInputStream< / code > . [CODESPLIT] public static char [ ] toCharArray ( InputStream is , String encoding ) throws IOException { return toCharArray ( is , Charsets . toCharset ( encoding ) ) ; }


Input: Get the contents of a <code > Reader< / code > as a character array . <p / > This method buffers the input internally so there is no need to use a <code > BufferedReader< / code > . [CODESPLIT] public static char [ ] toCharArray ( Reader input ) throws IOException { CharArrayWriter sw = new CharArrayWriter ( ) ; copy ( input , sw ) ; return sw . toCharArray ( ) ; }


Input: Get the contents of an <code > InputStream< / code > as a list of Strings one entry per line using the specified character encoding . <p / > This method buffers the input internally so there is no need to use a <code > BufferedInputStream< / code > . [CODESPLIT] public static List < String > readLines ( InputStream input , Charset encoding ) throws IOException { InputStreamReader reader = new InputStreamReader ( input , Charsets . toCharset ( encoding ) ) ; return readLines ( reader ) ; }


Input: Get the contents of an <code > InputStream< / code > as a list of Strings one entry per line using the specified character encoding . <p / > Character encoding names can be found at <a href = http : // www . iana . org / assignments / character - sets > IANA< / a > . <p / > This method buffers the input internally so there is no need to use a <code > BufferedInputStream< / code > . [CODESPLIT] public static List < String > readLines ( InputStream input , String encoding ) throws IOException { return readLines ( input , Charsets . toCharset ( encoding ) ) ; }


Input: Return an Iterator for the lines in an <code > InputStream< / code > using the character encoding specified ( or default encoding if null ) . <p / > <code > LineIterator< / code > holds a reference to the open <code > InputStream< / code > specified here . When you have finished with the iterator you should close the stream to free internal resources . This can be done by closing the stream directly or by calling <p / > The recommended usage pattern is : <pre > try { LineIterator it = IOUtils . lineIterator ( stream charset ) ; while ( it . hasNext () ) { String line = it . nextLine () ; /// do something with line } } finally { IOUtils . closeQuietly ( stream ) ; } < / pre > [CODESPLIT] public static LineIterator lineIterator ( InputStream input , Charset encoding ) throws IOException { return new LineIterator ( new InputStreamReader ( input , Charsets . toCharset ( encoding ) ) ) ; }


Input: Return an Iterator for the lines in an <code > InputStream< / code > using the character encoding specified ( or default encoding if null ) . <p / > <code > LineIterator< / code > holds a reference to the open <code > InputStream< / code > specified here . When you have finished with the iterator you should close the stream to free internal resources . This can be done by closing the stream directly or by calling { @link LineIterator#close () } or { @link LineIterator#closeQuietly ( LineIterator ) } . <p / > The recommended usage pattern is : <pre > try { LineIterator it = IOUtils . lineIterator ( stream UTF - 8 ) ; while ( it . hasNext () ) { String line = it . nextLine () ; /// do something with line } } finally { IOUtils . closeQuietly ( stream ) ; } < / pre > [CODESPLIT] public static LineIterator lineIterator ( InputStream input , String encoding ) throws IOException { return lineIterator ( input , Charsets . toCharset ( encoding ) ) ; }


Input: Writes bytes from a <code > byte [] < / code > to chars on a <code > Writer< / code > using the default character encoding of the platform . <p / > This method uses { @link String#String ( byte [] ) } . [CODESPLIT] public static void write ( byte [ ] data , Writer output ) throws IOException { write ( data , output , Charset . defaultCharset ( ) ) ; }


Input: Writes bytes from a <code > byte [] < / code > to chars on a <code > Writer< / code > using the specified character encoding . <p / > This method uses { @link String#String ( byte [] String ) } . [CODESPLIT] public static void write ( byte [ ] data , Writer output , Charset encoding ) throws IOException { if ( data != null ) { output . write ( new String ( data , Charsets . toCharset ( encoding ) ) ) ; } }


Input: Writes chars from a <code > char [] < / code > to bytes on an <code > OutputStream< / code > using the specified character encoding . <p / > This method uses { @link String#String ( char [] ) } and { @link String#getBytes ( String ) } . [CODESPLIT] public static void write ( char [ ] data , OutputStream output , Charset encoding ) throws IOException { if ( data != null ) { output . write ( new String ( data ) . getBytes ( Charsets . toCharset ( encoding ) ) ) ; } }


Input: Writes chars from a <code > CharSequence< / code > to bytes on an <code > OutputStream< / code > using the default character encoding of the platform . <p / > This method uses { @link String#getBytes () } . [CODESPLIT] public static void write ( CharSequence data , OutputStream output ) throws IOException { write ( data , output , Charset . defaultCharset ( ) ) ; }


Input: Writes chars from a <code > CharSequence< / code > to bytes on an <code > OutputStream< / code > using the specified character encoding . <p / > This method uses { @link String#getBytes ( String ) } . [CODESPLIT] public static void write ( CharSequence data , OutputStream output , Charset encoding ) throws IOException { if ( data != null ) { write ( data . toString ( ) , output , encoding ) ; } }


Input: Writes chars from a <code > StringBuffer< / code > to a <code > Writer< / code > . [CODESPLIT] @ Deprecated public static void write ( StringBuffer data , Writer output ) throws IOException { if ( data != null ) { output . write ( data . toString ( ) ) ; } }


Input: Writes chars from a <code > StringBuffer< / code > to bytes on an <code > OutputStream< / code > using the default character encoding of the platform . <p / > This method uses { @link String#getBytes () } . [CODESPLIT] @ Deprecated public static void write ( StringBuffer data , OutputStream output ) throws IOException { write ( data , output , ( String ) null ) ; }


Input: Writes chars from a <code > StringBuffer< / code > to bytes on an <code > OutputStream< / code > using the specified character encoding . <p / > Character encoding names can be found at <a href = http : // www . iana . org / assignments / character - sets > IANA< / a > . <p / > This method uses { @link String#getBytes ( String ) } . [CODESPLIT] @ Deprecated public static void write ( StringBuffer data , OutputStream output , String encoding ) throws IOException { if ( data != null ) { output . write ( data . toString ( ) . getBytes ( Charsets . toCharset ( encoding ) ) ) ; } }


Input: Writes the <code > toString () < / code > value of each item in a collection to an <code > OutputStream< / code > line by line using the default character encoding of the platform and the specified line ending . [CODESPLIT] public static void writeLines ( Collection < ? > lines , String lineEnding , OutputStream output ) throws IOException { writeLines ( lines , lineEnding , output , Charset . defaultCharset ( ) ) ; }


Input: Writes the <code > toString () < / code > value of each item in a collection to an <code > OutputStream< / code > line by line using the specified character encoding and the specified line ending . [CODESPLIT] public static void writeLines ( Collection < ? > lines , String lineEnding , OutputStream output , Charset encoding ) throws IOException { if ( lines == null ) { return ; } if ( lineEnding == null ) { lineEnding = LINE_SEPARATOR ; } Charset cs = Charsets . toCharset ( encoding ) ; for ( Object line : lines ) { if ( line != null ) { output . write ( line . toString ( ) . getBytes ( cs ) ) ; } output . write ( lineEnding . getBytes ( cs ) ) ; } }


Input: Writes the <code > toString () < / code > value of each item in a collection to an <code > OutputStream< / code > line by line using the specified character encoding and the specified line ending . <p / > Character encoding names can be found at <a href = http : // www . iana . org / assignments / character - sets > IANA< / a > . [CODESPLIT] public static void writeLines ( Collection < ? > lines , String lineEnding , OutputStream output , String encoding ) throws IOException { writeLines ( lines , lineEnding , output , Charsets . toCharset ( encoding ) ) ; }


Input: Writes the <code > toString () < / code > value of each item in a collection to a <code > Writer< / code > line by line using the specified line ending . [CODESPLIT] public static void writeLines ( Collection < ? > lines , String lineEnding , Writer writer ) throws IOException { if ( lines == null ) { return ; } if ( lineEnding == null ) { lineEnding = LINE_SEPARATOR ; } for ( Object line : lines ) { if ( line != null ) { writer . write ( line . toString ( ) ) ; } writer . write ( lineEnding ) ; } }


Input: Copy some or all chars from a large ( over 2GB ) <code > InputStream< / code > to an <code > OutputStream< / code > optionally skipping input chars . <p / > This method uses the provided buffer so there is no need to use a <code > BufferedReader< / code > . <p / > [CODESPLIT] public static long copyLarge ( Reader input , Writer output , final long inputOffset , final long length , char [ ] buffer ) throws IOException { if ( inputOffset > 0 ) { skipFully ( input , inputOffset ) ; } if ( length == 0 ) { return 0 ; } int bytesToRead = buffer . length ; if ( length > 0 && length < buffer . length ) { bytesToRead = ( int ) length ; } int read ; long totalRead = 0 ; while ( bytesToRead > 0 && EOF != ( read = input . read ( buffer , 0 , bytesToRead ) ) ) { output . write ( buffer , 0 , read ) ; totalRead += read ; if ( length > 0 ) { // only adjust length if not reading to the end // Note the cast must work because buffer.length is an integer bytesToRead = ( int ) Math . min ( length - totalRead , buffer . length ) ; } } return totalRead ; }


Input: Compare the contents of two Readers to determine if they are equal or not . <p / > This method buffers the input internally using <code > BufferedReader< / code > if they are not already buffered . [CODESPLIT] public static boolean contentEquals ( Reader input1 , Reader input2 ) throws IOException { input1 = toBufferedReader ( input1 ) ; input2 = toBufferedReader ( input2 ) ; int ch = input1 . read ( ) ; while ( EOF != ch ) { int ch2 = input2 . read ( ) ; if ( ch != ch2 ) { return false ; } ch = input1 . read ( ) ; } int ch2 = input2 . read ( ) ; return ch2 == EOF ; }


Input: Compare the contents of two Readers to determine if they are equal or not ignoring EOL characters . <p / > This method buffers the input internally using <code > BufferedReader< / code > if they are not already buffered . [CODESPLIT] public static boolean contentEqualsIgnoreEOL ( Reader input1 , Reader input2 ) throws IOException { BufferedReader br1 = toBufferedReader ( input1 ) ; BufferedReader br2 = toBufferedReader ( input2 ) ; String line1 = br1 . readLine ( ) ; String line2 = br2 . readLine ( ) ; while ( line1 != null && line2 != null && line1 . equals ( line2 ) ) { line1 = br1 . readLine ( ) ; line2 = br2 . readLine ( ) ; } return line1 == null ? line2 == null ? true : false : line1 . equals ( line2 ) ; }


Input: { [CODESPLIT] @ Override public boolean translate ( final int codepoint , final Writer out ) throws IOException { if ( between ) { if ( codepoint < below || codepoint > above ) { return false ; } } else { if ( codepoint >= below && codepoint <= above ) { return false ; } } out . write ( "&#" ) ; out . write ( Integer . toString ( codepoint , 10 ) ) ; out . write ( ' ' ) ; return true ; }


Input: Sets up instance variables that haven t been set by setFeature [CODESPLIT] private void setup ( ) { if ( theSchema == null ) theSchema = new HTMLSchema ( ) ; if ( theScanner == null ) theScanner = new HTMLScanner ( ) ; if ( theAutoDetector == null ) { theAutoDetector = new AutoDetector ( ) { public Reader autoDetectingReader ( InputStream i ) { return new InputStreamReader ( i ) ; } } ; } theStack = new Element ( theSchema . getElementType ( "<root>" ) , defaultAttributes ) ; thePCDATA = new Element ( theSchema . getElementType ( "<pcdata>" ) , defaultAttributes ) ; theNewElement = null ; theAttributeName = null ; thePITarget = null ; theSaved = null ; theEntity = 0 ; virginStack = true ; theDoctypeName = theDoctypePublicId = theDoctypeSystemId = null ; }


Input: Buffer both the InputStream and the Reader [CODESPLIT] private Reader getReader ( InputSource s ) throws SAXException , IOException { Reader r = s . getCharacterStream ( ) ; InputStream i = s . getByteStream ( ) ; String encoding = s . getEncoding ( ) ; String publicid = s . getPublicId ( ) ; String systemid = s . getSystemId ( ) ; if ( r == null ) { if ( i == null ) i = getInputStream ( publicid , systemid ) ; // i = new BufferedInputStream(i); if ( encoding == null ) { r = theAutoDetector . autoDetectingReader ( i ) ; } else { try { r = new InputStreamReader ( i , encoding ) ; } catch ( UnsupportedEncodingException e ) { r = new InputStreamReader ( i ) ; } } } // r = new BufferedReader(r); return r ; }


Input: Get an InputStream based on a publicid and a systemid [CODESPLIT] private InputStream getInputStream ( String publicid , String systemid ) throws IOException , SAXException { URL basis = new URL ( "file" , "" , System . getProperty ( "user.dir" ) + "/." ) ; URL url = new URL ( basis , systemid ) ; URLConnection c = url . openConnection ( ) ; return c . getInputStream ( ) ; }


Input: needs to support chars past U + FFFF [CODESPLIT] @ Override public void adup ( char [ ] buff , int offset , int length ) throws SAXException { if ( theNewElement != null && theAttributeName != null ) { theNewElement . setAttribute ( theAttributeName , null , theAttributeName ) ; theAttributeName = null ; } }


Input: with a semicolon . [CODESPLIT] private String expandEntities ( String src ) { int refStart = - 1 ; int len = src . length ( ) ; char [ ] dst = new char [ len ] ; int dstlen = 0 ; for ( int i = 0 ; i < len ; i ++ ) { char ch = src . charAt ( i ) ; dst [ dstlen ++ ] = ch ; if ( ch == ' ' && refStart == - 1 ) { // start of a ref excluding & refStart = dstlen ; } else if ( refStart == - 1 ) { // not in a ref } else if ( Character . isLetter ( ch ) || Character . isDigit ( ch ) || ch == ' ' ) { // valid entity char } else if ( ch == ' ' ) { // properly terminated ref int ent = lookupEntity ( dst , refStart , dstlen - refStart - 1 ) ; if ( ent > 0xFFFF ) { ent -= 0x10000 ; dst [ refStart - 1 ] = ( char ) ( ( ent >> 10 ) + 0xD800 ) ; dst [ refStart ] = ( char ) ( ( ent & 0x3FF ) + 0xDC00 ) ; dstlen = refStart + 1 ; } else if ( ent != 0 ) { dst [ refStart - 1 ] = ( char ) ent ; dstlen = refStart ; } refStart = - 1 ; } else { // improperly terminated ref refStart = - 1 ; } } return new String ( dst , 0 , dstlen ) ; }


Input: deferring to the schema for named ones . [CODESPLIT] private int lookupEntity ( char [ ] buff , int offset , int length ) { int result = 0 ; if ( length < 1 ) return result ; // length) + "]"); if ( buff [ offset ] == ' ' ) { if ( length > 1 && ( buff [ offset + 1 ] == ' ' || buff [ offset + 1 ] == ' ' ) ) { try { return Integer . parseInt ( new String ( buff , offset + 2 , length - 2 ) , 16 ) ; } catch ( NumberFormatException e ) { return 0 ; } } try { return Integer . parseInt ( new String ( buff , offset + 1 , length - 1 ) , 10 ) ; } catch ( NumberFormatException e ) { return 0 ; } } return theSchema . getEntity ( new String ( buff , offset , length ) ) ; }


Input: e is the next element to be started if we know what it is [CODESPLIT] private void restart ( Element e ) throws SAXException { while ( theSaved != null && theStack . canContain ( theSaved ) && ( e == null || theSaved . canContain ( e ) ) ) { Element next = theSaved . next ( ) ; push ( theSaved ) ; theSaved = next ; } }


Input: Pop the stack irrevocably [CODESPLIT] private void pop ( ) throws SAXException { if ( theStack == null ) return ; // empty stack String name = theStack . name ( ) ; String localName = theStack . localName ( ) ; String namespace = theStack . namespace ( ) ; String prefix = prefixOf ( name ) ; if ( ! namespaces ) namespace = localName = "" ; theContentHandler . endElement ( namespace , localName , name ) ; if ( foreign ( prefix , namespace ) ) { theContentHandler . endPrefixMapping ( prefix ) ; // "] for elements to " + namespace); } Attributes atts = theStack . atts ( ) ; for ( int i = atts . getLength ( ) - 1 ; i >= 0 ; i -- ) { String attNamespace = atts . getURI ( i ) ; String attPrefix = prefixOf ( atts . getQName ( i ) ) ; if ( foreign ( attPrefix , attNamespace ) ) { theContentHandler . endPrefixMapping ( attPrefix ) ; // "] for attributes to " + attNamespace); } } theStack = theStack . next ( ) ; }


Input: Pop the stack restartably [CODESPLIT] private void restartablyPop ( ) throws SAXException { Element popped = theStack ; pop ( ) ; if ( restartElements && ( popped . flags ( ) & Schema . F_RESTART ) != 0 ) { popped . anonymize ( ) ; popped . setNext ( theSaved ) ; theSaved = popped ; } }


Input: Get the prefix from a QName [CODESPLIT] private String prefixOf ( String name ) { int i = name . indexOf ( ' ' ) ; String prefix = "" ; if ( i != - 1 ) prefix = name . substring ( 0 , i ) ; return prefix ; }


Input: Return true if we have a foreign name [CODESPLIT] private boolean foreign ( String prefix , String namespace ) { // " for foreignness -- "); boolean foreign = ! ( prefix . equals ( "" ) || namespace . equals ( "" ) || namespace . equals ( theSchema . getURI ( ) ) ) ; return foreign ; }