All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.adobe.xfa.text.TextRange Maven / Gradle / Ivy

There is a newer version: 2024.11.18598.20241113T125352Z-241000
Show newest version
package com.adobe.xfa.text;

import java.util.List;

import com.adobe.xfa.ut.Rect;
import com.adobe.xfa.text.markup.MarkupIn;
import com.adobe.xfa.text.markup.MarkupOut;

/**
 *
 * @exclude from published api -- Mike Tardif, May 2006.
 */
public class TextRange {
	public final static int POSN_ANCHOR = 0;
	public final static int POSN_LOOSE = 1;
	public final static int POSN_START = 2;
	public final static int POSN_END = 3;

// the "real data
	private final TextPosn moAnchor;
	private final TextPosn moLoose;
// filled by SortPositions()
	private TextPosn moStart;
	private TextPosn moEnd;

/**
 * Default constructor.
 * 

* The range is not initially associated with any stream. */ public TextRange () { moAnchor = new TextPosn(); moLoose = new TextPosn(); } /** * Copy constructor. *

* Copy all contents of the source range, including stream * association, and start/end indexes. * @param oSource Source position object to copy. */ public TextRange (TextRange oSource) { moAnchor = new TextPosn (oSource.moAnchor); moLoose = new TextPosn (oSource.moLoose); } /** * Constructor with stream. *

* Construct a range object associated with the given stream. The range * initially covers the entire content of the stream. * @param poStream Stream to associate with. NULL creates a range * object with no initial association. */ public TextRange (TextStream poStream) { moAnchor = new TextPosn (poStream); moLoose = new TextPosn (poStream, Integer.MAX_VALUE); reconcile(); } /** * Constructor with stream and indexes. *

* Construct a range object associated with the given stream and * covering the range of items indicated by the index values. * @param poStream Stream to associate with. NULL creates a * range object with no initial association. * @param nNewAnchor Anchor index for the range. Will be truncated if * too large. * @param nNewLoose (optional) Loose end index for the range. Default * is to include up to the end of the stream. Note that the loose index * may be less than, equal to, or greater than the anchor index. */ public TextRange (TextStream poStream, int nNewAnchor, int nNewLoose) { moAnchor = new TextPosn (poStream, nNewAnchor); moLoose = new TextPosn (poStream, nNewLoose); reconcile(); } /** * Overridden: Associate range with a new stream. *

* This method associates the range object with the specified stream, * automatically including all stream content in the range. The range * object will be tracked by the new stream (if not NULL) and will no * longer be tracked by its old stream. * @param poStream Stream to associate with. NULL leaves the range * object unassociated (and untracked). */ public void associate (TextStream poStream) { moAnchor.associate (poStream, 0); moLoose.associate (poStream, Integer.MAX_VALUE); reconcile(); } /** * Overridden: Associate range with a new stream, specifying range * indexes. *

* This method associates the range object with the specified stream, * including the portion indicated by index numbers passed as * parameters. The range object will be tracked by the new stream (if * not NULL) and will no longer be tracked by its old stream. * @param poStream Stream to associate with. NULL leaves the range * object unassociated (and untracked). * @param nNewAnchor Anchor index for the range. Will be truncated if * too large. * @param nNewLoose (optional) Loose end index for the range. Default * is to include up to the end of the stream. Note that the loose index * may be less than, equal to, or greater than the anchor index. */ public void associate (TextStream poStream, int nNewAnchor, int nNewLoose) { moAnchor.associate (poStream, nNewAnchor); moLoose.associate (poStream, nNewLoose); reconcile(); } /** * Optain a pointer to the associated stream. * @return Pointer to the associated text stream; NULL if the range * currently has no stream association. */ public TextStream stream () { return moAnchor.stream(); } /** * Count the number of items in the range. * @return Number of items included in the range. */ public int count () { sortPositions(); return moEnd.index() - moStart.index(); } /** * Count the number of characters in the range. * @return Number of characters included in the range. */ public int countText () { return countByType (TextItem.CHAR); } /** * Count the number of embedded fields in the range. * @return Number of embedded fields included in the range. */ public int countField () { return countByType (TextItem.FIELD); } /** * Count the number of embedded objects in the range. * @return Number of embedded objects included in the range. */ public int countEmbed () { return countByType (TextItem.OBJECT); } /** * Is the range empty? * @return TRUE if the range contains no items; FALSE if it contains at * least one item. */ public boolean isEmpty () { return moAnchor.index() == moLoose.index(); } /** * Obtain one of the range endpoints as a text position. * @param ePosition A member of the local PosnCode enumeration * indicating which range endpoint is desired. Value must be one of * POSN_ANCHOR, POSN_LOOSE, POSN_START or POSN_END. * @return A text position corresponding to the requested endpoint. * Will not be associated with any stream if the range has no stream * association. */ public TextPosn position (int ePosition) { switch (ePosition) { case POSN_ANCHOR: return moAnchor; case POSN_LOOSE: return moLoose; case POSN_START: sortPositions(); return moStart; case POSN_END: sortPositions(); return moEnd; default: return moAnchor; } } /** * Change a range endpoint by index number. *

* Given an endpoint position code and an index number, this method sets * that endpoint of the range to the new index. Whether setting by * anchor/loose or start/end, it is OK to set the endpoint to occur * before the start point; the range will simply reorient itself. The * call is ignored if the range currently has no stream association. * @param ePosition A member of the local PosnCode enumeration * indicating which range endpoint is desired. Value must be one of * POSN_ANCHOR, POSN_LOOSE, POSN_START or POSN_END. * @param nNewPosition Index number to move the endpoint to. Will be * truncated if too large. */ public void position (int ePosition, int nNewPosition) { switch (ePosition) { case POSN_ANCHOR: moAnchor.index (nNewPosition); break; case POSN_LOOSE: moLoose.index (nNewPosition); break; case POSN_START: sortPositions(); moStart.index (nNewPosition); break; case POSN_END: sortPositions(); moEnd.index (nNewPosition); break; } reconcile(); } /** * Change a range endpoint by text position. *

* Given an endpoint position code and text position object, this method * sets that endpoint of the range to the new new position. Whether * setting by anchor/loose or start/end, it is OK to set the endpoint to * occur before the start point; the range will simply reorient itself. * The call is ignored if the range currently has no stream association. * @param ePosition A member of the local PosnCode enumeration * indicating which range endpoint is desired. Value must be one of * POSN_ANCHOR, POSN_LOOSE, POSN_START or POSN_END. * @param oNewPosn New position to set for specified range endpoint. * If this position is associated with a different stream, only its * index number is used. */ public void position (int ePosition, TextPosn oNewPosn) { switch (ePosition) { case POSN_ANCHOR: moAnchor.copyData (oNewPosn); break; case POSN_LOOSE: moLoose.copyData (oNewPosn); break; case POSN_START: sortPositions(); moStart.copyData (oNewPosn); break; case POSN_END: sortPositions(); moEnd.copyData (oNewPosn); break; } reconcile(); } /** * Query the anchor position. * @return Anchor position. */ public TextPosn anchor () { return position (POSN_ANCHOR); } /** * Set the anchor position by index. * @param nNewIndex New index for the anchor position. Will be * truncated if too large. */ public void anchor (int nNewIndex) { position (POSN_ANCHOR, nNewIndex); } /** * Set the anchor position by text position object. * @param oNewPosn New position for the anchor. If associated with a * different stream, only its index is used. */ public void anchor (TextPosn oNewPosn) { position (POSN_ANCHOR, oNewPosn); } /** * Query the loose position. * @return Loose position. */ public TextPosn loose () { return position (POSN_LOOSE); } /** * Set the loose position by index. * @param nNewIndex New index for the loose position. Will be * truncated if too large. */ public void loose (int nNewIndex) { position (POSN_LOOSE, nNewIndex); } /** * Set the loose position by text position object. * @param oNewPosn New position for the loose. If associated with a * different stream, only its index is used. */ public void loose (TextPosn oNewPosn) { position (POSN_LOOSE, oNewPosn); } /** * Query the start position. * @return Start position. */ public TextPosn start () { return position (POSN_START); } /** * Set the start position by index. * @param nNewIndex New index for the start position. Will be * truncated if too large. */ public void start (int nNewIndex) { position (POSN_START, nNewIndex); } /** * Set the start position by text position object. * @param oNewPosn New position for the start. If associated with a * different stream, only its index is used. */ public void start (TextPosn oNewPosn) { position (POSN_START, oNewPosn); } /** * Query the end position. * @return End position. */ public TextPosn end () { return position (POSN_END); } /** * Set the end position by index. * @param nNewIndex New index for the end position. Will be * truncated if too large. */ public void end (int nNewIndex) { position (POSN_END, nNewIndex); } /** * Set the end position by text position object. * @param oNewPosn New position for the end. If associated with a * different stream, only its index is used. */ public void end (TextPosn oNewPosn) { position (POSN_END, oNewPosn); } /** * Return the union of two text ranges. *

* The union of two ranges is defined as including all items in both * ranges, as well as all items between if the ranges do not overlap. * Given a second range, this method performs the union operation and * populates a third range with the resulf. * @param oAdd Range to union with this one. * @param oResult Range resulting from the union. * @return TRUE if the two ranges overlapped; FALSE if not or the ranges * refer to different streams. Contiguous ranges are considered as * overlapping. */ public boolean union (TextRange oAdd, TextRange oResult) { if ((stream() != oAdd.stream()) || (stream() == null)) { return false; } int nStart = start().index(); int nEnd = end().index(); int nAddStart = oAdd.start().index(); int nAddEnd = oAdd.end().index(); boolean bOverlap; if (nStart < nAddStart) { bOverlap = nEnd >= nAddStart; } else { bOverlap = nAddEnd >= nStart; nStart = nAddStart; } if (nEnd < nAddEnd) { nEnd = nAddEnd; } oResult.associate (stream(), nStart, nEnd); return bOverlap; } /** * Obtain the range content as plain text. * @param bIncludeFields (optional) If TRUE, the operation recursively * descends through embedded fields within the range to include their * text as well. If FALSE (default) only text from the associated * stream is returned. */ public String text (boolean bIncludeFields) { TextStream poStream = stream(); if (poStream == null) { return ""; } sortPositions(); return poStream.rangeText (moStart, moEnd, bIncludeFields); } public String text () { return text (false); } /** * Obtain the range content as rich text. *

* Copy the content of the range to another stream, replacing its * previous content. The destination stream retains its graphic source, * which may be different from that of the associated stream. All * graphics objects copied are reconciled in the destination stream's * graphic source. Because this is a copy, the destination stream will * get clones of any embedded objects or fields. * @param oText Destination text stream. Not modified if this range * has no stream association. */ public void text (TextStream oText) { TextStream poStream = stream(); if (poStream == null) { return; } sortPositions(); // Note: no need to check for self-assignment on the stream. Text stream // object can cleanly extract a self sub-stream. poStream.rangeText (moStart, moEnd, oText); } /** * Enumerate markers contained within this range. * @param oMarkers - Array to contain pointers to the enumerated * markers. Any previous contents are removed by the call. Even though * the returned array contains non-const pointers to markers, those * markers are owned by AXTE and must not be deleted by the client, * though the client can cache pointers to these markers provide that it * participates in the marker reference counting mechanism. * @param bPositionMarkers - True if all position markers at this * position are to be included in the array. False (default) if * position markers are to be excluded. A position marker is considered * to be in the text range if it occurs at or after the start of the * range, and before or at the end of the range. * @param bRangeMarkers - True (default) if all range markers that span * this position are to be included in the array. False if range * markers are to be excluded. * @param bSubsetOnly - Applies to range markers only. True to limit * included range markers to those that span a (possibly complete) * subset of this range; false (default) if any range marker that * overlaps the this range is to be included. */ public void enumerateMarkers (List oMarkers, boolean bPositionMarkers, boolean bRangeMarkers, boolean bSubsetOnly) { TextStream poStream = stream(); if (poStream == null) { return; } sortPositions(); poStream.rangeEnumMarker (moStart, moEnd, oMarkers, bPositionMarkers, bRangeMarkers, bSubsetOnly); } public void enumerateMarkers (List oMarkers) { enumerateMarkers (oMarkers, false, true, false); } /** * Delete the contents of the range. *

* Delete all items in the associated stream that fall within this * range. Normally, there may be fix-up required after such a * deletion. If there are any attribute changes in the deleted items, * the last one must be preserved for text that follows the deletion. * Also, if the deletion spans paragraphs, the result may be a paragraph * with conflicting paragraph attributes. These are reconciled in * favour of the first paragraph (if it still has text left after the * delete). Alternatively, one can invoke a raw delete that doesn't do * the fix-ups (not recommended, except for very special cases). This * is referred to as a raw delete. * @param bRaw (optional) TRUE for raw delete (see above); FALSE * (default) for normal delete. */ public void delete (boolean bRaw) { // Watson 1325333: Don't dork with positions if empty range; could // interfere with temporary redundant attribute change. if ((stream() == null) || isEmpty()) { return; } sortPositions(); moStart.deleteAhead (moEnd.index() - moStart.index(), bRaw); } public void delete () { delete (false); } /** * Replace the range contents with a single character. *

* This method deletes the content of the range and then inserts a * single character. When it returns, the range will contain only the * inserted character. * @param cReplace Character to insert. * @param bRaw (optional) TRUE for raw delete; FALSE (default) for * normal delete. Please see the description of raw deletion with the * Delete() method. */ public void replace (char cReplace, boolean bRaw) { if (stream() == null) { return; } String sReplace = ""; sReplace += cReplace; replace (sReplace, bRaw); } public void replace (char cReplace) { replace (cReplace, false); } /** * Replace the range contents with string of text. *

* This method deletes the content of the range and then inserts a text * string When it returns, the range will contain only the inserted * text. * @param sReplace Text to insert. * @param bRaw (optional) TRUE for raw delete; FALSE (default) for * normal delete. Please see the description of raw deletion with the * Delete() method. */ public void replace (String sReplace, boolean bRaw) { if (stream() == null) { return; } sortPositions(); stream().rangeReplace (moStart, moEnd.index() - moStart.index(), sReplace, bRaw); } public final void replace (String sReplace) { replace (sReplace, false); } /** * Replace the range contents with rich text. *

* This method deletes the content of the range and then inserts rich * text. When it returns, the range will contain only the inserted * character. * @param oReplace Rich text to insert. May have a different graphic * source from the associated stream. All stream content is copied. In * other words, the associated stream gets clones of embedded objects * and fields in the source stream. * @param bRaw (optional) TRUE for raw delete; FALSE (default) for * normal delete. Please see the description of raw deletion with the * Delete() method. */ public void replace (TextStream oReplace, boolean bRaw) { if (stream() == null) { return; } sortPositions(); stream().rangeReplace (moStart, moEnd.index() - moStart.index(), oReplace, bRaw); } public final void replace (TextStream oReplace) { replace (oReplace, false); } /** * Insert a range marker at the position represented by this position * object. *

* If this range is not associated with any text stream, the call is * ignored. *

* @param poMarker - Pointer to marker to insert. Note that markers are * always cloned on insertion, so a copy actually gets inserted. The * caller continues to retain ownership of the instance referred to by * this parameter, and can delete it any time after the call. * @return Pointer to the cloned copy actually inserted in the text * stream. While this is a non-const pointer, it is owned by AXTE and * must not be deleted by the client, though the client can cache a * pointers to this marker provide that it participates in the marker * reference counting mechanism. */ public TextMarker insert (TextMarker poMarker) { if (stream() == null) { return null; } sortPositions(); return stream().rangeMarker (moStart, moEnd, poMarker); } /** * Obtain the attributes in effect over the range. *

* Returns a text attribute structure describing the attributes over the * range. Any attribute that remains constant over the range will have * an enabled value in the result. Any attribute that changes over the * range will be disabled in the result. * @return Text attribute object describing the attributes in effect * over the range. */ public TextAttr attribute () { TextStream poStream = stream(); if (poStream == null) { return TextAttr.defaultAttr (false); } sortPositions(); return poStream.rangeGetAttr (moStart, moEnd); } /** * Change text attributes over the range. *

* Given a text attribute object, this method applies enabled attributes * over the entire range. Disabled attributes in the given object are * not changed. * @param oNewAttr Attribute object with enabled attributes to apply. * @param bRaw (optional) TRUE for raw change; FALSE (default) for * normal change Please see the description of raw deletion with the * Delete() method. */ public void attribute (TextAttr oNewAttr, boolean bRaw) { TextStream poStream = stream(); if (poStream == null) { return; } sortPositions(); poStream.rangeSetAttr (moStart, moEnd, oNewAttr, bRaw); } public final void attribute (TextAttr oNewAttr) { attribute (oNewAttr, false); } /** * Convert the range contents to markup. *

* Convert the range contents to text output in a markup language. The * particular language is determined by which derived class of * TextMkOut is passed. The caller may request that fields are * flattened into stream content in the markup, or retained as * references. * @param oMarkup Output markup engine to generate the markup * language. * @param poInitAttr (optional) Ambient/initial attributes. This * parameter, if not NULL, works in concert with the bDefaultInitAttr * parameter. If that parameter indicates ambient attributes, this * represents default attributes that need not be written to the markup * if they apply to the stream. If it indicates initial attributes, all * enabled values are written to the markup. If NULL (default value) it * is ignored. * @param bDefaultInitAttr (optional) If FALSE (default), parameter * poInitAttr represents initial attributes to write. If TRUE, * poInitAttr represents ambient attributes as described above. * @param bFlattenFields Optional. If TRUE, embedded field content is * written to the markup as if it was part of the range's content. If * FALSE (default) field references are written to the markup. */ public void markup (MarkupOut oMarkup, TextAttr poInitAttr, boolean bDefaultInitAttr, boolean bFlattenFields) { TextStream poStream = stream(); if (poStream == null) { return; } sortPositions(); poStream.rangeMarkup (moStart, moEnd, oMarkup, poInitAttr, bDefaultInitAttr, bFlattenFields); } /** * Apply markup to the range. *

* Replace the range's current contents with rich text derived from a * markup language. * @param oMarkup Markup engine that processes the markup language. * This must be pre-initialized with the markup source. */ public void markup (MarkupIn oMarkup) { TextStream poStream = stream(); if (poStream == null) { return; } delete(); poStream.rangeMarkup (end(), oMarkup); } /** * Extend the range to include complete words. *

* The start of the range moves back to the start of the word containing * it. The end of the range moves forward to the end of the word that * contains it. If either position is not within a word or adjacent to * one, it does not move. * @return TRUE if the resulting range contains any items; FALSE if it * is empty (typically occurs when you call this on an empty range that * is not positioned at a word. */ public boolean grabWord (int eWordMode) { sortPositions(); moStart.wordStart (eWordMode); moEnd.nextWord (false, eWordMode); tighten(); reconcile(); return (moStart.index() != moEnd.index()); } public boolean grabWord () { return grabWord (TextPosn.WORD_MODE_LEGACY); } /** * Extend the range to include complete lines. *

* Note: the associated stream must have a text display for line * operations to succeed. The start of the range moves back to the * start of the line containing it. The end of the range moves forward * to the end of the line that contains it. * @return FALSE if no display; TRUE otherwise. */ public boolean grabLine () { sortPositions(); if (! moStart.start()) { return false; } moEnd.nextLine(); reconcile(); return true; } /** * Extend the range to include complete paragraphs. *

* Note: a paragraph starts after a paragraph mark and runs until just * after the next paragraph mark. If our end position is already just * beyond a paragraph mark, we normally won't want to move it. The * exception is when our start is also just after the same mark (empty * range once tightened). In this case, we maintain the start and move * the end after the next mark. * @return Always returns TRUE; */ public boolean grabPara () { // Note: a paragraph starts after a paragraph mark and runs until just // after the next paragraph mark. If our end position is already just // beyond a paragraph mark, we normally won't want to move it. The // exception is when our start is also just after the same mark (empty // range once tightened). In this case, we maintain the start and move // the end after the nect mark. tighten(); boolean bEmpty = isEmpty(); sortPositions(); moStart.paraStart(); boolean bSuppressEnd = false; if (!bEmpty) { TextPosnBase oTemp = new TextPosnBase (moEnd); if (oTemp.prevUserPosnType (false) == TextItem.PARA) { bSuppressEnd = true; } } if (!bSuppressEnd) { moEnd.nextPara(); } reconcile(); return true; } /** * Try to exclude spurious attr changes from range. *

*

* This method "tightens" the range around text and other objects so * that attribute changes at the extremities don't distort what gets * returned by an Attribute() call. *

*

* If the range is empty, we do the following special handling: If the * range is between attribute changes, we leave it alone (they were * probably just inserted). Otherwise, we test to see if we're at the * start of the line. If so, move both positions over any leading * attribute changes so that we show the attributes in effect at the * start of the line. Otherwise, we move both positions back over all * attribute changes, to be consistent with position user item handling. *

*/ public void tighten () { sortPositions(); if (moStart.index() == moEnd.index()) { int ePrev = moStart.prev (TextNullFrame.MODE_STOP, true); int eNext = moStart.next (TextNullFrame.MODE_STOP, true); if ((ePrev != TextItem.ATTR) || ((eNext != TextItem.ATTR) && (eNext != TextItem.UNKNOWN))) { moStart.tighten (false); if (moStart.isAtStart()) { moStart.tighten (true); moEnd.tighten (true); } else { moEnd.tighten (false); } } } else { moStart.tighten (true); if (moEnd.next (TextNullFrame.MODE_STOP, true) != TextItem.UNKNOWN) { moEnd.tighten (false); // keep trailing attr in range if at end of stream } if (moStart.index() > moEnd.index()) { if (moEnd.isAtStart()) { moEnd.tighten (true); } else { moStart.tighten (false); } } } } /** * Create a position with the associated stream, given a character * index. *

* Return text position object that is associated with the same stream * as this object, but is positioned immediately after the Nth * character, where N is passed as a parameter. * @param lIndex Character position to search for. * @return Resulting position object. */ public TextPosnBase charPosition (int lIndex) { return start().charPosition (lIndex); } /** * Create a range with the associated stream, given a character index * and length. *

* Return text range object that is associated with the same stream * as this object. The range will start after the Nth character and * include M characters, where N and M are passed as parameters. * @param lStart Character position to search for. * @param lLength Number of characters to include in the range. * @return Resulting range object. */ public TextRange charRange (int lStart, int lLength) { return start().charRange (lStart, lLength); } /** * Invalidate the area occupied by the text range in an interactive * environment. *

* In conjunction with a graphic environment, this method invalidates * the (visible) graphic area occupied by the range's underlying text. * This will lead to a future paint event through the graphic framework. * @param oGfxEnv Graphic environment to perform the invalidation in. * @param bEraseBkgnd TRUE if the background is to be erased as well; * FALSE (default) if not. */ // public void Invalidate (jfGfxEnv poGfxEnv, boolean bEraseBkgnd) { // TextStream poStream = Stream(); // if (poStream == null) { // return; // } // // TextDisplay poDisplay = poStream.Display(); // if (poDisplay == null) { // return; // } // // TextRange oDummy; // poDisplay.UpdateSelected (oGfxEnv, this, oDummy, bEraseBkgnd); // } /** * Obtain the rectangle(s) in the laid-out text corresponding to this * range. *

* A single range might yield multiple rectangles if it spans multiple * lines or there is bidirectional text. Note: This call makes sense * only for single frame displays. In a multi-frame environment it * makes more sense to call TextFrame::GetSelectionRectangles() on * each frame, in order to get rectangles that are positioned relative * to their frame. *

* @param oRectangles - Array to receive the rectangles. * @return True if any rectangles were found; false otherwise. This * method could return false if the range has no stream associated, the * stream has no display, or the range is degenerate. */ public boolean getSelectionRectangles (List oRectangles) { TextStream poStream = stream(); if (poStream == null) { return false; } TextDisplay poDisplay = poStream.display(); if (poDisplay == null) { return false; } // return poDisplay.GetSelectionRectangles (this, oRectangles); return false; // TODO: } /** * Assignment operator. *

* Copy the entire content of the source range object including stream * association and indexes. * @param oSource Source range object to copy. */ public void copyFrom (TextRange oSource) { moAnchor.copyFrom (oSource.moAnchor); moLoose.copyFrom (oSource.moLoose); } /** * Equality comparison. *

* Two text ranges are considered equal if they are associated with the * same stream and have the same pair of index numbers. Note that the * current implementation is rather crude in that it still compares * indexes even when both streams are NULL. * @param object Range to compare against. * @return TRUE if the ranges are equal; FALSE if not. */ public boolean equals (Object object) { if (this == object) return true; // This overrides Object.equals(boolean) directly, so... if (object == null) return false; if (object.getClass() != getClass()) return false; TextRange test = (TextRange) object; return moAnchor.equals (test.moAnchor) && moLoose.equals (test.moLoose); } public int hashCode() { int hash = 59; hash = (hash * 31) ^ moAnchor.hashCode(); hash = (hash * 31) ^ moLoose.hashCode(); return hash; } /** * Inequality comparison. *

* Two text ranges are considered unequal if they are associated with * different stream and have different index numbers. Note that the * current implementation is rather crude in that it still compares * indexes even when both streams are NULL. * @param oCompare Range to compare against. * @return TRUE if the ranges are not equal; FALSE if they are equal. */ public boolean notEqual (TextRange oCompare) { return ! equals (oCompare); } private int countByType (int eType) { sortPositions(); TextPosnBase oCurrent = new TextPosn (moStart); int nCount = 0; int eCurrent = oCurrent.next(); while ((oCurrent.index() <= moEnd.index()) && (eCurrent != TextItem.UNKNOWN)) { if (eCurrent == eType) { nCount++; } eCurrent = oCurrent.next(); } return nCount; } private void reconcile () { tighten(); sortPositions(); moStart.position (TextPosn.POSN_BEFORE); moEnd.position (TextPosn.POSN_AFTER); } private final void sortPositions () { if (moAnchor.index() <= moLoose.index()) { moStart = moAnchor; moEnd = moLoose; } else { moStart = moLoose; moEnd = moAnchor; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy