/// <summary> /// <font><span>aaa[splitPoint]bbb</span></font> --> <font><span>aaa</span></font><font>[splitPoint]<span>bbb</span></font> /// </summary> private void SplitInlineTags(MarkupPointer splitPoint) { Debug.Assert(splitPoint.Positioned); IHTMLElement currentElement = splitPoint.GetParentElement(ElementFilters.CreateElementPassFilter()); while (currentElement != null) { if (!ElementFilters.IsInlineElement(currentElement)) { return; } IHTMLElement parentElement = currentElement.parentElement; MarkupRange currentElementRange = _markupServices.CreateMarkupRange(currentElement, false); MarkupRange leftRange = _markupServices.CreateMarkupRange(); IHTMLElement leftElement = _markupServices.CreateElement(_markupServices.GetElementTagId(currentElement), null); HTMLElementHelper.CopyAttributes(currentElement, leftElement); leftRange.MoveToPointers(currentElementRange.Start, splitPoint); _markupServices.InsertElement(leftElement, leftRange.Start, leftRange.End); splitPoint.MoveAdjacentToElement(leftElement, _ELEMENT_ADJACENCY.ELEM_ADJ_AfterEnd); MarkupRange rightRange = _markupServices.CreateMarkupRange(); IHTMLElement rightElement = _markupServices.CreateElement(_markupServices.GetElementTagId(currentElement), null); HTMLElementHelper.CopyAttributes(currentElement, rightElement); rightRange.MoveToPointers(splitPoint, currentElementRange.End); #if DEBUG // Verify that the right range does not overlap the left *element* MarkupRange leftElementRange = _markupServices.CreateMarkupRange(leftElement, true); Debug.Assert(leftElementRange.End.IsLeftOfOrEqualTo(rightRange.Start), "Your right range overlaps the left element that you just created!"); #endif _markupServices.InsertElement(rightElement, rightRange.Start, rightRange.End); splitPoint.MoveAdjacentToElement(rightElement, _ELEMENT_ADJACENCY.ELEM_ADJ_BeforeBegin); _markupServices.RemoveElement(currentElement); currentElement = parentElement; } }
/// <summary> /// Fixes up a range that is contained in a single header element. /// </summary> /// <param name="range">A range that is contained in a single header element.</param> /// <param name="turnBold">Whether or not the text should be turning bold.</param> private void FixupHeaderRange(MarkupRange range, bool turnBold) { IHTMLElement parentHeaderElement = range.ParentBlockElement(); if (parentHeaderElement == null || !ElementFilters.IsHeaderElement(parentHeaderElement)) { Debug.Fail("Expected entire range to be inside a single header element."); return; } MarkupRange expandedRange = range.Clone(); // Make sure we expand the selection to include any <font> tags that may be wrapping us. MarkupPointerMoveHelper.MoveUnitBounded(expandedRange.Start, MarkupPointerMoveHelper.MoveDirection.LEFT, MarkupPointerAdjacency.BeforeVisible, parentHeaderElement); MarkupPointerMoveHelper.MoveUnitBounded(expandedRange.End, MarkupPointerMoveHelper.MoveDirection.RIGHT, MarkupPointerAdjacency.BeforeVisible, parentHeaderElement); // Walks in-scope elements and clears out any elements or styles that might affect the bold formatting. var elementsToRemove = new List <IHTMLElement>(); expandedRange.WalkRange( delegate(MarkupRange currentexpandedRange, MarkupContext context, string text) { IHTMLElement currentElement = context.Element; if (currentElement != null && context.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_EnterScope) { if (IsStrongOrBold(currentElement)) { elementsToRemove.Add(currentElement); } else if (IsFontableElement(currentElement) && HTMLElementHelper.IsBold((IHTMLElement2)currentElement) != turnBold) { currentElement.style.fontWeight = String.Empty; } } return(true); }, true); elementsToRemove.ForEach(e => markupServices.RemoveElement(e)); // Walks the range to find any segments of text that need to be fixed up. var rangesToWrap = new List <MarkupRange>(); range.WalkRange( delegate(MarkupRange currentRange, MarkupContext context, string text) { if (context.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_Text) { TextStyles currentTextStyles = new TextStyles(currentRange.Start); if (currentTextStyles.Bold != turnBold) { rangesToWrap.Add(currentRange.Clone()); } } return(true); }, true); rangesToWrap.ForEach(r => WrapRangeInFontIfNecessary(r, turnBold)); }
public static void ChangeElementTagIds(MshtmlMarkupServices markupServices, MarkupRange selection, _ELEMENT_TAG_ID[] tagBefore, _ELEMENT_TAG_ID tagAfter) { HtmlStyleHelper htmlStyleHelper = new HtmlStyleHelper(markupServices); int parentStartDiff = 0; MarkupRange rangeToChange; bool selectionStartedEmpty = selection.IsEmpty(); if (selectionStartedEmpty) { // Operate on parent block element rangeToChange = markupServices.CreateMarkupRange(selection.ParentBlockElement()); parentStartDiff = selection.Start.MarkupPosition - rangeToChange.Start.MarkupPosition; } else { rangeToChange = selection; // If expanding the selection would not include any new text, then expand it. // <h1>|abc|</h1> --> |<h1>abc</h1>| rangeToChange.MoveOutwardIfNoText(); } IHTMLElementFilter[] filters = new IHTMLElementFilter[tagBefore.Length]; for (int i = 0; i < tagBefore.Length; i++) { filters[i] = ElementFilters.CreateTagIdFilter(markupServices.GetNameForTagId(tagBefore[i])); } IHTMLElement[] elements = rangeToChange.GetElements(ElementFilters.CreateCompoundElementFilter(filters), false); foreach (IHTMLElement element in elements) { MarkupRange elementRange = markupServices.CreateMarkupRange(element); int startPositionDiff = rangeToChange.Start.MarkupPosition - elementRange.Start.MarkupPosition; int endPositionDiff = rangeToChange.End.MarkupPosition - elementRange.End.MarkupPosition; // @RIBBON TODO: Appropriately preserve element attributes when changing tag ids? MarkupRange newElementRange = markupServices.CreateMarkupRange(htmlStyleHelper.WrapRangeInSpanElement(tagAfter, null, elementRange)); markupServices.RemoveElement(element); MarkupPointer startPointer = rangeToChange.Start.Clone(); startPointer.MoveToMarkupPosition(startPointer.Container, newElementRange.Start.MarkupPosition + startPositionDiff); if (startPointer.IsLeftOf(rangeToChange.Start)) { rangeToChange.Start.MoveToPointer(startPointer); } MarkupPointer endPointer = rangeToChange.End.Clone(); endPointer.MoveToMarkupPosition(endPointer.Container, newElementRange.End.MarkupPosition + endPositionDiff); if (endPointer.IsLeftOf(elementRange.End)) { rangeToChange.End.MoveToPointer(endPointer); } } if (selectionStartedEmpty) { selection.Start.MoveToMarkupPosition(selection.Start.Container, rangeToChange.Start.MarkupPosition + parentStartDiff); selection.Collapse(true); } }