/// <summary> /// Condenses this range into the smallest well-formed state that still contains the same /// text markup. /// </summary> /// <returns></returns> public bool Trim() { MarkupPointer newStart = MarkupServices.CreateMarkupPointer(Start); MarkupPointer newEnd = MarkupServices.CreateMarkupPointer(End); MarkupContext context = new MarkupContext(); //set newStart adjacent to the first text element to its right newStart.Right(true, context); while (!HasContentBetween(Start, newStart) && newStart.IsLeftOf(End)) { newStart.Right(true, context); } if (HasContentBetween(Start, newStart)) { newStart.Left(true); //we overstepped the text, so back up one step } //set newEnd adjacent to the first text element to its left newEnd.Left(true, context); while (!HasContentBetween(newEnd, End) && newEnd.IsRightOf(Start)) { newEnd.Left(true, context); } if (HasContentBetween(newEnd, End)) { newEnd.Right(true); //we overstepped the text, so back up one step } IHTMLElement sharedParent = GetSharedParent(newStart, newEnd); //span the start and end pointers as siblings by finding the parents of start and end //pointers that are direct children of the sharedParent IHTMLElement child = GetOuterMostChildOfParent(newStart, true, sharedParent); if (child != null) { newStart.MoveAdjacentToElement(child, _ELEMENT_ADJACENCY.ELEM_ADJ_BeforeBegin); } child = GetOuterMostChildOfParent(newEnd, false, sharedParent); if (child != null) { newEnd.MoveAdjacentToElement(child, _ELEMENT_ADJACENCY.ELEM_ADJ_AfterEnd); } if (!HasContentBetween(newStart, Start) && !HasContentBetween(End, newEnd) && !(Start.IsEqualTo(newStart) && End.IsEqualTo(newEnd))) { Start.MoveToPointer(newStart); End.MoveToPointer(newEnd); return(true); } else { //the range didn't change, so return false. return(false); } }
/// <summary> /// Walk through the markup range in reverse, letting the walker visit each position. /// </summary> /// <param name="walker">the delegate walking navigating the the markup range</param> /// <param name="inScopeElementsOnly">if true, enter/exit notifications about out-of-scope elements will be suppressed.</param> /// <returns></returns> public void WalkRangeReverse(MarkupRangeWalker walker, bool inScopeContextsOnly) { MarkupPointer p1 = MarkupServices.CreateMarkupPointer(End); MarkupPointer p2 = MarkupServices.CreateMarkupPointer(End); p1.Cling = false; p2.Cling = false; MarkupContext context = new MarkupContext(); bool continueWalking = true; MarkupRange currentRange = null; while (continueWalking && p2.IsRightOf(Start)) { string text = null; bool isInScope = true; p2.Left(true, context); currentRange = new MarkupRange(p2.Clone(), p1.Clone(), MarkupServices); if (inScopeContextsOnly) { if (context.Element != null) { if (context.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_EnterScope) { p1.MoveAdjacentToElement(context.Element, _ELEMENT_ADJACENCY.ELEM_ADJ_AfterEnd); isInScope = InRange(p1); } else if (context.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_ExitScope) { p1.MoveAdjacentToElement(context.Element, _ELEMENT_ADJACENCY.ELEM_ADJ_BeforeBegin); isInScope = InRange(p1); } } else if (context.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_Text) { // It's possible part of the text is out of scope, so only return the in-scope text. if (currentRange.Start.IsLeftOf(Start)) { currentRange.Start.MoveToPointer(Start); } } } if (context.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_Text) { text = currentRange.Text; } if (!inScopeContextsOnly || isInScope) { continueWalking = walker(currentRange, context, text); } p1.MoveToPointer(p2); } }
private static void MovePointer(MarkupPointer p, MoveDirection d, MarkupContext context) { if (d == MoveDirection.LEFT) { p.Left(true, context); } else { p.Right(true, context); } }
public override bool ShouldMoveDropLocationRight(MarkupPointer dropLocation) { MarkupContext mc = new MarkupContext(); dropLocation.Right(false, mc); if (mc.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_EnterScope && ElementFilters.IsBlockElement(mc.Element) && !ContentSourceManager.IsSmartContent(mc.Element)) { dropLocation.Left(false, mc); if (mc.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_EnterScope && ElementFilters.IsBlockElement(mc.Element)) return true; } return false; }
private MarkupPointer GetFirstTextPoint(MarkupPointer from, bool forward) { MarkupPointer firstTextPoint = from.Clone(); MarkupContext context = new MarkupContext(); bool keepLooking = true; do { if (forward) { firstTextPoint.Right(false, context); } else { firstTextPoint.Left(false, context); } if (context.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_Text) { break; } if (forward) { firstTextPoint.Right(true, context); keepLooking = context.Element != null && firstTextPoint.IsLeftOf(End); } else { firstTextPoint.Left(true, context); keepLooking = context.Element != null && firstTextPoint.IsRightOf(Start); } } while (keepLooking); return(firstTextPoint); }
/// <summary> /// Retrieve the parent of a child element that is closest to an outer parent element. /// </summary> /// <param name="from">the position to move move out from</param> /// <param name="lookRight">if true, look right for the inner child to start from, otherwise look left</param> /// <param name="outerParent">parent element to move out to</param> /// <returns>the direct child of the outerparent that contains the innerChild</returns> IHTMLElement GetOuterMostChildOfParent(MarkupPointer from, bool lookRight, IHTMLElement outerParent) { MarkupContext lookContext = new MarkupContext(); if (lookRight) { from.Right(false, lookContext); } else { from.Left(false, lookContext); } //if there is a new element coming into scope, start the search from there, //otherwise, start from the currentScope. IHTMLElement innerChild; if (lookContext.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_EnterScope) { innerChild = lookContext.Element; } else { innerChild = from.CurrentScope; } IHTMLElement parent = innerChild; IHTMLElement innerParent = innerChild; while (parent != outerParent && parent != null) { innerParent = parent; parent = parent.parentElement; } Debug.Assert(innerParent != null, "Parent not found"); if (innerParent == outerParent) //occurs when the from pointer is position directly in the parent. { return(null); } return(innerParent); }
private IHTMLElement GetNextElement(MarkupPointer start, MarkupRange boundaries, IHTMLElementFilter filter, bool forward) { start = start.Clone(); MarkupPointer boundary = forward ? boundaries.End : boundaries.Start; MarkupContext moveResult = new MarkupContext(); _MARKUP_CONTEXT_TYPE skipContext = _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_ExitScope; //advance the pointer if (forward) start.Right(true, moveResult); else start.Left(true, moveResult); while (forward ? start.IsLeftOf(boundary) : start.IsRightOf(boundary)) { if (moveResult.Element != null && moveResult.Context != skipContext && filter(moveResult.Element)) { return moveResult.Element; } //advance the pointer if (forward) start.Right(true, moveResult); else start.Left(true, moveResult); } return null; }
/// <summary> /// Retrieve the parent of a child element that is closest to an outer parent element. /// </summary> /// <param name="from">the position to move move out from</param> /// <param name="lookRight">if true, look right for the inner child to start from, otherwise look left</param> /// <param name="outerParent">parent element to move out to</param> /// <returns>the direct child of the outerparent that contains the innerChild</returns> IHTMLElement GetOuterMostChildOfParent(MarkupPointer from, bool lookRight, IHTMLElement outerParent) { MarkupContext lookContext = new MarkupContext(); if (lookRight) from.Right(false, lookContext); else from.Left(false, lookContext); //if there is a new element coming into scope, start the search from there, //otherwise, start from the currentScope. IHTMLElement innerChild; if (lookContext.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_EnterScope) innerChild = lookContext.Element; else innerChild = from.CurrentScope; IHTMLElement parent = innerChild; IHTMLElement innerParent = innerChild; while (parent != outerParent && parent != null) { innerParent = parent; parent = parent.parentElement; } Debug.Assert(innerParent != null, "Parent not found"); if (innerParent == outerParent) //occurs when the from pointer is position directly in the parent. { return null; } return innerParent; }
private static void MovePointer(MarkupPointer p, MoveDirection d, MarkupContext context) { if (d == MoveDirection.LEFT) p.Left(true, context); else p.Right(true, context); }
private void MovePointerRightUntilRegionBreak(MarkupPointer p, IHTMLElementFilter regionBreakFilter, MarkupPointer rightBoundary) { MarkupContext moveContext = new MarkupContext(); while (p.IsLeftOf(rightBoundary)) { p.Right(true, moveContext); if (moveContext.Element != null && regionBreakFilter(moveContext.Element)) { p.Left(true); return; } } }