public static void ClearBackgroundColor(MshtmlMarkupServices markupServices, MarkupRange selection)
        {
            HtmlStyleHelper htmlStyleHelper = new HtmlStyleHelper(markupServices);

            htmlStyleHelper.SplitInlineTags(selection.Start);
            htmlStyleHelper.SplitInlineTags(selection.End);

            IHTMLElement[] elements = selection.GetElements(ElementFilters.CreateTagIdFilter("font"), false);
            foreach (IHTMLElement element in elements)
            {
                element.style.backgroundColor = "";
            }

            // We may now be left with empty font tags, e.g. <font>blah</font>.
            // After switching between editors this becomes <font size="+0">blah</font>, which
            // causes blah to be rendered differently.
            // To avoid that we need to remove any empty-attribute font tags.
            selection.RemoveElementsByTagId(_ELEMENT_TAG_ID.TAGID_FONT, true);
        }
        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);
            }
        }