/// <summary> /// Wraps a MarkupRange in an element (or multiple elements if necessary to produce valid HTML). /// </summary> /// <param name="elementFactory">Creates elements to wrap the markupRange in as needed.</param> /// <param name="markupServices">The MarkupServices for the markupRange.</param> /// <param name="markupRange">The range to wrap.</param> protected void WrapInElement(ElementFactory elementFactory, MshtmlMarkupServices markupServices, MarkupRange markupRange) { Debug.Assert(markupRange.GetElements(ElementFilters.BLOCK_ELEMENTS, false).Length == 0, "Did not expect MarkupRange to contain block elements"); MarkupPointer startPointer = markupRange.Start.Clone(); MarkupPointer endPointer = markupRange.Start.Clone(); MarkupContext context; while (endPointer.IsLeftOf(markupRange.End)) { context = endPointer.Right(false); if (context.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_EnterScope || context.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_ExitScope) { if (!markupRange.InRange(context.Element)) { // EnterScope example: <span>[markupRange.Start]Hello [endPointer]<i>Hello[markupRange.End]</i></span> // ExitScope example: <span>[markupRange.Start]Hello [endPointer]</span><span>Hello[markupRange.End]</span> InsertElement(elementFactory(), markupServices, startPointer, endPointer); continue; } } endPointer.Right(true); } InsertElement(elementFactory(), markupServices, startPointer, endPointer); }
/// <summary> /// Makes sure that whole (not parts of) lists are included in the source of a paste. /// </summary> /// <param name="range">The original source range. The range may be modified.</param> /// <param name="markupServices">MarkupServices for the range.</param> private void ExpandToIncludeLists(MarkupRange range, MshtmlMarkupServices markupServices) { MarkupPointer pointer = markupServices.CreateMarkupPointer(); IHTMLElementFilter listFilter = ElementFilters.CreateCompoundElementFilter(ElementFilters.LIST_ELEMENTS, ElementFilters.LIST_ITEM_ELEMENTS); IHTMLElement[] listElements = range.GetElements(listFilter, false); foreach (IHTMLElement element in listElements) { IHTMLElement parentList = element; while (parentList != null && !ElementFilters.IsListElement(parentList)) { parentList = parentList.parentElement; } if (parentList != null) { pointer.MoveAdjacentToElement(parentList, _ELEMENT_ADJACENCY.ELEM_ADJ_BeforeBegin); if (range.Start.IsRightOf(pointer)) { range.Start.MoveToPointer(pointer); } pointer.MoveAdjacentToElement(parentList, _ELEMENT_ADJACENCY.ELEM_ADJ_AfterEnd); if (range.End.IsLeftOf(pointer)) { range.End.MoveToPointer(pointer); } } } }
/// <summary> /// Makes sure that whole (not parts of) tables are included in the source of a paste. /// </summary> /// <param name="range">The original source range. The range may be modified.</param> /// <param name="markupServices">MarkupServices for the range.</param> private void ExpandToIncludeTables(MarkupRange range, MshtmlMarkupServices markupServices) { MarkupPointer pointer = markupServices.CreateMarkupPointer(); IHTMLElement[] tableElements = range.GetElements(ElementFilters.TABLE_ELEMENTS, false); foreach (IHTMLElement element in tableElements) { IHTMLElement parentTable = element; while (parentTable != null && markupServices.GetElementTagId(parentTable) != _ELEMENT_TAG_ID.TAGID_TABLE) { parentTable = parentTable.parentElement; } if (parentTable != null) { pointer.MoveAdjacentToElement(parentTable, _ELEMENT_ADJACENCY.ELEM_ADJ_BeforeBegin); if (range.Start.IsRightOf(pointer)) { range.Start.MoveToPointer(pointer); } pointer.MoveAdjacentToElement(parentTable, _ELEMENT_ADJACENCY.ELEM_ADJ_AfterEnd); if (range.End.IsLeftOf(pointer)) { range.End.MoveToPointer(pointer); } } } }
/// <summary> /// Fixes up all the headers in the entire markupRange. /// </summary> /// <param name="turnBold">Whether or not the text should be turning bold.</param> private void FixupHeaders(bool turnBold) { IHTMLElement elementStartHeader = markupRange.Start.GetParentElement(ElementFilters.HEADER_ELEMENTS); IHTMLElement elementEndHeader = markupRange.End.GetParentElement(ElementFilters.HEADER_ELEMENTS); MarkupRange currentRange = markupRange.Clone(); if (elementStartHeader != null) { // Takes care of the following cases: // <h1>...|blah|...</h1> // <h1>...|blah...</h1>...|... MarkupRange startRange = markupServices.CreateMarkupRange(elementStartHeader, false); startRange.Start.MoveToPointer(markupRange.Start); if (startRange.End.IsRightOf(markupRange.End)) { startRange.End.MoveToPointer(markupRange.End); } FixupHeaderRange(startRange, turnBold); currentRange.Start.MoveAdjacentToElement(elementStartHeader, _ELEMENT_ADJACENCY.ELEM_ADJ_AfterEnd); if (currentRange.End.IsLeftOf(currentRange.Start)) { currentRange.End.MoveToPointer(currentRange.Start); } } if (elementEndHeader != null && !HTMLElementHelper.ElementsAreEqual(elementStartHeader, elementEndHeader)) { // Takes care of the following case: // ...|...<h1>...blah|...</h1> MarkupRange endRange = markupServices.CreateMarkupRange(elementEndHeader, false); endRange.End.MoveToPointer(markupRange.End); FixupHeaderRange(endRange, turnBold); currentRange.End.MoveAdjacentToElement(elementEndHeader, _ELEMENT_ADJACENCY.ELEM_ADJ_BeforeBegin); if (currentRange.Start.IsRightOf(currentRange.End)) { currentRange.Start.MoveToPointer(currentRange.End); } } if (!markupRange.InRange(currentRange)) { return; } IHTMLElement[] headerElements = currentRange.GetElements(ElementFilters.HEADER_ELEMENTS, true); if (headerElements != null && headerElements.Length > 0) { foreach (IHTMLElement element in headerElements) { MarkupRange headerRange = markupServices.CreateMarkupRange(element, false); FixupHeaderRange(headerRange, turnBold); } } }
private void FindCellRange(MarkupRange selectedRange, out ArrayList selectedCells, out IHTMLTableCell beginCell, out IHTMLTableCell endCell) { // default to null beginCell = null; endCell = null; selectedCells = new ArrayList(); // JJA: fix bug #476623 -- at document initialization the selected markup range // may not yet be positioned so protect ourselves in this case if (!selectedRange.Positioned) { return; } // query for all of the table cells within the range selectedCells.AddRange(selectedRange.GetElements(ElementFilters.TABLE_CELL_ELEMENT, false)); // extract the begin and end cells if (selectedCells.Count == 0) { // see if the selection is contained within a single cell beginCell = selectedRange.Start.GetParentElement(ElementFilters.TABLE_CELL_ELEMENT) as IHTMLTableCell; if (beginCell != null) { // make sure the cell is content editable (it would not be in the case // where the call to GetParentElement went all the way out of the body // and found a cell that was part of the containing template) if (!(beginCell as IHTMLElement3).isContentEditable) { beginCell = null; } } endCell = beginCell; selectedCells.Add(beginCell); } else if (selectedCells.Count == 1) { beginCell = selectedCells[0] as IHTMLTableCell; endCell = selectedCells[0] as IHTMLTableCell; } else { beginCell = selectedCells[0] as IHTMLTableCell; endCell = selectedCells[selectedCells.Count - 1] as IHTMLTableCell; } }
private void SelectNextRegion(bool backward) { MarkupRange smartContentRange = EditorContext.MarkupServices.CreateMarkupRange(HTMLElement, false); IHTMLElement[] editFields = smartContentRange.GetElements(ElementFilters.CreateClassFilter(InlineEditField.EDIT_FIELD), true); IHTMLElement element = GetSelectedChildEditField(HTMLElement, EditorContext.Selection.SelectedMarkupRange); if (element == null) { if (editFields.Length > 0) { SelectElement(backward ? editFields[editFields.Length - 1] : editFields[0]); } else { Select(); } return; } // One of the edit fields was selected for (int i = 0; i < editFields.Length; i++) { IHTMLElement editField = editFields[i]; if (element.sourceIndex == editField.sourceIndex) { if (i == 0 && backward || i == editFields.Length - 1 && !backward) { Select(); } else { SelectElement(backward ? editFields[i - 1] : editFields[i + 1]); } return; } } Debug.Fail("How did we get here?"); }
public static void RemoveAttributes(MshtmlMarkupServices markupServices, MarkupRange selection, string[] attributesToRemove) { IHTMLElementFilter[] filters = new IHTMLElementFilter[attributesToRemove.Length]; for (int i = 0; i < attributesToRemove.Length; i++) { filters[i] = ElementFilters.CreateElementAttributeFilter(attributesToRemove[i]); } IHTMLElement[] elements = selection.GetElements(ElementFilters.CreateCompoundElementFilter(filters), false); foreach (IHTMLElement element in elements) { foreach (string attribute in attributesToRemove) { element.removeAttribute(attribute, 0); } } }
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); }