private string GrowToAnchorParent(HTMLData htmlData) { if (htmlData.OnlyImageElement == null) { return(null); } string html; // Load up the html document from the clipboard to a document to examine the html about to be inserted MshtmlMarkupServices markupServices = new MshtmlMarkupServices(htmlData.HTMLDocument as IMarkupServicesRaw); MarkupRange range = markupServices.CreateMarkupRange(htmlData.OnlyImageElement, true); // look to see if this is a case where the inserted html is <a>|<img>|</a> MarkupContext markupContextStart = range.Start.Left(true); MarkupContext markupContextEnd = range.End.Right(true); // if that is the cause, change the html about to be inserted to |<a><img></a>| if (markupContextStart.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_ExitScope && markupContextEnd.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_ExitScope && markupContextStart.Element.tagName == "A" && markupContextEnd.Element.tagName == "A") { html = markupContextStart.Element.outerHTML; } else { html = htmlData.HTMLSelection; } return(html); }
private void ApplyBlockFormatToContentSelection(MarkupRange selection, _ELEMENT_TAG_ID styleTagId, MarkupRange maximumBounds) { MarkupRange[] stylableBlockRegions = GetSelectableBlockRegions(selection); if (stylableBlockRegions.Length > 0) { // // We want to make sure that the selection reflects only the // blocks that were changed. Unposition the start and end // pointers and then make sure they cover the stylable block // regions, no more, no less. selection.Start.Unposition(); selection.End.Unposition(); foreach (MarkupRange range in stylableBlockRegions) { ApplyBlockStyleToRange(styleTagId, range, maximumBounds); if (!selection.Start.Positioned || range.Start.IsLeftOf(selection.Start)) { selection.Start.MoveToPointer(range.Start); } if (!selection.End.Positioned || range.End.IsRightOf(selection.End)) { selection.End.MoveToPointer(range.End); } } } }
public void AddDamage(MarkupRange range, bool includeAdjacentWords) { if (DamageTrackingEnabled) { wordRangeDamager.AddDamage(range, includeAdjacentWords); } }
public static int GetParentContainerBlockWidth(MarkupRange markupRange) { IHTMLElement2 parentBlock = markupRange.Start.GetParentElement(ElementFilters.BLOCK_OR_TABLE_CELL_ELEMENTS) as IHTMLElement2; if (parentBlock != null) { // TODO: we would like to always clientWidth here however for an empty block element this will // be zero. So in this case we use scrollWidth which should be a proxy except in the case where // the parent element has a horizontal scroll bar (in which case we may insert a table which // is worst case too narrow). What we "should" do is insert and remove some bogus content // within the block element to force its clientWidth to the right value. int blockWidth = parentBlock.clientWidth; if (blockWidth == 0) { blockWidth = parentBlock.scrollWidth; } return(blockWidth); } else { return(0); } }
private bool MaybeScheduleDelayedAutoreplace(string htmlText, char key) { if (_autoreplaceManager == null) { return(false); } bool handled = false; int length; string replaceHtml = _autoreplaceManager.FindMatch(htmlText, out length); if (replaceHtml != null && length > 0 && htmlText != replaceHtml) { if (!ShouldAutoCorrect(htmlText, key, replaceHtml)) { return(false); } MarkupRange insertMarkupRange = _blogPostHtmlEditorControl.SelectedMarkupRange.Clone(); for (int i = 0; i < length; i++) { insertMarkupRange.Start.MoveUnit(_MOVEUNIT_ACTION.MOVEUNIT_PREVCHAR); } insertMarkupRange.Start.Gravity = _POINTER_GRAVITY.POINTER_GRAVITY_Right; insertMarkupRange.End.Gravity = _POINTER_GRAVITY.POINTER_GRAVITY_Left; _delayedAutoReplaceAction = new AutoReplaceAction(_blogPostHtmlEditorControl, key, replaceHtml, insertMarkupRange); //_blogPostHtmlEditorControl.InsertHtml(insertMarkupRange.Start, insertMarkupRange.End, replaceHtml); handled = true; _lastActionWasReplace++; } return(handled); }
public AutoReplaceAction(BlogPostHtmlEditorControl editor, char key, string replacement, MarkupRange range) { this.editor = editor; this.key = key; this.replacement = replacement; this.range = range; }
/// <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); } } } }
public override void Apply(MshtmlMarkupServices markupServices, MarkupRange markupRange, MshtmlCoreCommandSet commands) { // Special case because MSHTML is not able remove underlines from <a> elements. if (!Underline) { // Find the parent <a> element (if one exists). IHTMLElement currentElement = markupRange.Start.CurrentScope; while (currentElement != null && !(currentElement is IHTMLAnchorElement)) { currentElement = currentElement.parentElement; } if (currentElement != null) { // Explicitly remove the underline. const string noTextDecorationAttribute = "style=\"text-decoration: none\""; ElementFactory factory = () => markupServices.CreateElement(_ELEMENT_TAG_ID.TAGID_FONT, noTextDecorationAttribute); WrapInElement(factory, markupServices, markupRange); return; } } if (!commands[IDM.UNDERLINE].Enabled) { return; } commands[IDM.UNDERLINE].Execute(); Debug.Assert(commands[IDM.UNDERLINE].Latched == Underline, "UnderlineTextStyle did not yield the correct results."); }
/// <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> /// Inserts the extended entry break into the editor at the specified location. /// </summary> internal IHTMLElement InsertExtendedEntryBreak(MarkupPointer insertionPoint) { IHTMLElement entryBreakDiv = EditorContext.MarkupServices.CreateElement(_ELEMENT_TAG_ID.TAGID_DIV, null); IHTMLElement postBodyElement = HTMLElement; insertionPoint.PushCling(false); insertionPoint.PushGravity(_POINTER_GRAVITY.POINTER_GRAVITY_Right); try { //insert the entryBreak DIV into the beginning of the post body entryBreakDiv.id = EXTENDED_ENTRY_ID; entryBreakDiv.setAttribute("name", EXTENDED_ENTRY_ID, 0); MarkupRange markupRange = EditorContext.MarkupServices.CreateMarkupRange(); markupRange.MoveToElement(postBodyElement, false); markupRange.End.MoveToPointer(markupRange.Start); EditorContext.MarkupServices.InsertElement(entryBreakDiv, markupRange.Start, markupRange.End); //move all content that should stay above the extended entry line, above the entryBreakDiv //this effectively forces all open tags to be closed, and leaves the insertion point below //the extended entry line (with the pre-insert parent tree still intact. markupRange.Start.MoveAdjacentToElement(entryBreakDiv, _ELEMENT_ADJACENCY.ELEM_ADJ_AfterEnd); markupRange.End.MoveToPointer(insertionPoint); MarkupPointer target = EditorContext.MarkupServices.CreateMarkupPointer(entryBreakDiv, _ELEMENT_ADJACENCY.ELEM_ADJ_BeforeBegin); EditorContext.MarkupServices.Move(markupRange.Start, markupRange.End, target); } finally { insertionPoint.PopCling(); insertionPoint.PopGravity(); } return(entryBreakDiv); }
/// <summary> /// Inserts the extended entry break into the editor. /// </summary> internal void InsertExtendedEntryBreak() { IHTMLDocument3 doc3 = (IHTMLDocument3)HTMLElement.document; IHTMLElement2 entryBreak = (IHTMLElement2)doc3.getElementById(EXTENDED_ENTRY_ID); if (entryBreak == null) { using (IUndoUnit undo = EditorContext.CreateUndoUnit()) { using (EditorContext.DamageServices.CreateDamageTracker(ElementRange.Clone(), true)) { MarkupPointer insertionPoint = EditorContext.MarkupServices.CreateMarkupPointer(EditorContext.Selection.SelectedMarkupRange.Start); //delete the parent block element of the insertion point if it is empty (bug 421500) DeleteInsertionTargetBlockIfEmpty(insertionPoint); IHTMLElement extendedEntryBreak = InsertExtendedEntryBreak(insertionPoint); //reselect the insertion point MarkupRange selection = EditorContext.MarkupServices.CreateMarkupRange(); insertionPoint.MoveAdjacentToElement(extendedEntryBreak, _ELEMENT_ADJACENCY.ELEM_ADJ_AfterEnd); MarkupPointerMoveHelper.MoveUnitBounded( insertionPoint, MarkupPointerMoveHelper.MoveDirection.RIGHT, MarkupPointerAdjacency.AfterEnterBlock | MarkupPointerAdjacency.BeforeText , HTMLElement); selection.Start.MoveToPointer(insertionPoint); selection.End.MoveToPointer(insertionPoint); selection.ToTextRange().select(); } undo.Commit(); } } }
private void InsertSuggestedUrl(string matchText, GlossaryLinkItem linkItem, MarkupRange markupRange) { if (GlossarySettings.AutoLinkTermsOnlyOnce && TermAlreadyLinked(matchText, linkItem.Url)) { return; } // Make sure we're not in the title and not in a hyperlink already IHTMLElement parentElement = _blogPostHtmlEditorControl.PostTitleElement; IHTMLElement currentElement = markupRange.ParentElement(); while (currentElement != null) { if (parentElement == currentElement) { return; // in the title } if (currentElement.tagName.ToLower(CultureInfo.InvariantCulture) == "a") { return; // in an anchor } currentElement = currentElement.parentElement; } if (_linkIgnoreWord != null && matchText.ToLower(CultureInfo.CurrentCulture) == _linkIgnoreWord.ToLower(CultureInfo.CurrentCulture)) { return; } _blogPostHtmlEditorControl.InsertLink(linkItem.Url, matchText, linkItem.Title, linkItem.Rel, linkItem.OpenInNewWindow, markupRange); _blogPostHtmlEditorControl.SelectedMarkupRange.Collapse(false); }
/// <summary> /// Returns the maximum range that can be safely considered equivalent to this range (without bringing new text into the range). /// </summary> /// <param name="range"></param> /// <returns></returns> private MarkupRange CreateMaxSafeRange(MarkupRange range) { MarkupRange maxRange = range.Clone(); SelectOuter(maxRange); return(maxRange); }
/// <summary> /// Splits the specified range into block regions, and removes all block elements. /// </summary> /// <param name="range"></param> /// <returns></returns> private InnerBlockRegion[] GetNormalizedBlockContentRegions(MarkupRange range) { ArrayList regions = new ArrayList(); ElementBreakRegion[] breakRegions = SplitIntoElementRegions(range, ElementFilters.BLOCK_ELEMENTS); //DumpBreakRegions(breakRegions); foreach (ElementBreakRegion breakRegion in breakRegions) { //save the closed block range and start the next range if (!breakRegion.ContentRange.IsEmptyOfContent()) { regions.Add(new InnerBlockRegion(breakRegion.ContentRange, breakRegion.BreakStartElement ?? breakRegion.BreakEndElement)); } //remove the break elements if they should be deleted if (ShouldDeleteForBlockFormatting(breakRegion.BreakStartElement)) { _markupServices.RemoveElement(breakRegion.BreakStartElement); } if (ShouldDeleteForBlockFormatting(breakRegion.BreakEndElement)) { _markupServices.RemoveElement(breakRegion.BreakEndElement); } } return((InnerBlockRegion[])regions.ToArray(typeof(InnerBlockRegion))); }
void EditorContext_SelectionChanged(object sender, EventArgs e) { if (Attached) { MarkupRange range = EditorContext.Selection.SelectedMarkupRange; IHTMLElement element = GetSelectedChildEditField(HTMLElement, range); if (element != null) { if (_findCommandExecuting) { return; } InlineEditField field = new InlineEditField(element, SmartContent, EditorContext, HTMLElement, this); field.ClearDefaultText(); field.PersistFieldValueToContent(true); } else { if (_checkSpellingCommandExecuting) { return; } PersistAllEditFields(); } } }
/// <summary> /// Inspects the range if a new font tag need to be added to apply formatting for the range. /// Call this only for ranges that are inside a header element /// </summary> private void WrapRangeInFontIfNecessary(MarkupRange currentRange, bool turnBold) { // Check if there is an existing font/span tag that completely wraps this range, // we can just use that instead of inserting a new one MarkupContext workingContext = new MarkupContext(); bool wrapFont = true; MarkupPointer start = currentRange.Start.Clone(); start.Gravity = _POINTER_GRAVITY.POINTER_GRAVITY_Left; start.Right(false, workingContext); // Look to the right to see what we have there if (workingContext.Element != null && workingContext.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_EnterScope && IsFontableElement(workingContext.Element)) { start.MoveAdjacentToElement(workingContext.Element, _ELEMENT_ADJACENCY.ELEM_ADJ_AfterEnd); if (currentRange.End.IsEqualTo(start)) { // There is an existing <FONT>/<SPAN> enclosing the range, no need to wrap again wrapFont = false; // set its font-weight workingContext.Element.style.fontWeight = turnBold ? "bold" : "normal"; } } if (wrapFont) { string weightAttribute = String.Format(CultureInfo.InvariantCulture, "style=\"font-weight: {0}\"", turnBold ? "bold" : "normal"); HtmlStyleHelper.WrapRangeInElement(markupServices, currentRange, _ELEMENT_TAG_ID.TAGID_FONT, weightAttribute); } }
public static IHTMLElement GetSelectedChildEditField(IHTMLElement parent, MarkupRange selection) { if (selection == null || !selection.Positioned) { Trace.Fail("Selection is invalid!"); return(null); } IHTMLElement element = selection.ParentElement(); if (element == null || !HTMLElementHelper.IsChildOrSameElement(parent, element)) { return(null); } do { if (InlineEditField.IsEditField(element)) { return(element); } element = element.parentElement; } while (element != null && element.sourceIndex != parent.sourceIndex); return(null); }
private bool IsValidInsertionPoint(IHTMLElement e, MarkupPointer p) { if (InlineEditField.IsEditField(p.CurrentScope)) { return(true); } IHTMLElement contentEditableParent = null; IHTMLElement parent = e; while (parent != null) { if ((parent as IHTMLElement3).isContentEditable) { contentEditableParent = parent; } else if (contentEditableParent != null) { break; //we hit the top-most editable parent. } parent = parent.parentElement; } if (contentEditableParent != null) { MarkupRange range = EditorContext.MarkupServices.CreateMarkupRange(contentEditableParent, false); return(range.InRange(p)); } else { return(false); } }
public void ExecuteSelectionOperation(HtmlEditorSelectionOperation op) { //suspend selection change events while the real HTML selection is temporarily adjusted //to include the smart content element while the selection operation executes. _editorComponentContext.BeginSelectionChange(); try { IHTMLDocument2 document = (IHTMLDocument2)HTMLElement.document; MarkupRange elementRange = CreateElementClingMarkupRange(); MarkupRange insertionRange = CreateSelectionBoundaryMarkupRange(); elementRange.ToTextRange().select(); op(this); //reset the selection if (elementRange.Start.Positioned && elementRange.End.Positioned) { document.selection.empty(); _editorComponentContext.Selection = this; } else { insertionRange.ToTextRange().select(); } } finally { _editorComponentContext.EndSelectionChange(); } }
public override void Apply(MshtmlMarkupServices markupServices, MarkupRange markupRange, MshtmlCoreCommandSet commands) { const string smallCapsAttribute = "style=\"font-variant: small-caps\""; ElementFactory factory = () => markupServices.CreateElement(_ELEMENT_TAG_ID.TAGID_FONT, smallCapsAttribute); WrapInElement(factory, markupServices, markupRange); }
/// <summary> /// Select all of the text in the region. /// </summary> protected void SelectAll() { MarkupRange selectRange = ElementRange.Clone(); selectRange.MoveToElement(HTMLElement, false); selectRange.ToTextRange().select(); }
private void UpdateImageLink(string href, IHTMLElement ImgElement, ILinkOptions defaultOptions) { MshtmlMarkupServices markupServices = new MshtmlMarkupServices((IMarkupServicesRaw)ImgElement.document); IHTMLElement parentElement = ImgElement.parentElement; if (!(parentElement is IHTMLAnchorElement)) { parentElement = markupServices.CreateElement(_ELEMENT_TAG_ID.TAGID_A, null); MarkupRange range = markupServices.CreateMarkupRange(); range.MoveToElement(ImgElement, true); markupServices.InsertElement(parentElement, range.Start, range.End); //set the default target attribute for the new element string target = defaultOptions.ShowInNewWindow ? "_blank" : null; IHTMLAnchorElement htmlAnchorElement = (parentElement as IHTMLAnchorElement); if (htmlAnchorElement.target != target) //don't set the target to null if its already null (avoids adding empty target attr) { htmlAnchorElement.target = target; } ImageViewer viewer = DhtmlImageViewers.GetImageViewer(DhtmlImageViewer); if (viewer != null) { if (defaultOptions.UseImageViewer) { viewer.Apply(htmlAnchorElement, defaultOptions.ImageViewerGroupName); } } } parentElement.setAttribute("href", href, 0); }
public bool FilterAppliesRanged(int offset, int length) { MarkupRange adjustedRange = currentWordRange.Clone(); MarkupHelpers.AdjustMarkupRange(ref stagingTextRange, adjustedRange, offset, length); return(filter != null && filter(adjustedRange)); }
private static bool TableElementIsContainedInSmartContent(MarkupRange elementRange) { // table elements inside smart content regions are not editable IHTMLElement parentSmartContent = elementRange.Start.GetParentElement(ContentSourceManager.CreateSmartContentElementFilter()); return(parentSmartContent != null); }
private void HighlightWordRange(MarkupRange word) { try { IHighlightSegmentRaw segment; IDisplayPointerRaw start; IDisplayPointerRaw end; _displayServices.CreateDisplayPointer(out start); _displayServices.CreateDisplayPointer(out end); DisplayServices.TraceMoveToMarkupPointer(start, word.Start); DisplayServices.TraceMoveToMarkupPointer(end, word.End); _highlightRenderingServices.AddSegment(start, end, HighlightWordStyle, out segment); _tracker.AddSegment(segment, MarkupHelpers.UseStagingTextRange(ref stagingTextRange, word, rng => rng.text), _markupServicesRaw); } catch (COMException ce) { if (ce.ErrorCode == unchecked ((int)0x800A025E)) { return; } throw; } }
public bool Contains(MarkupRange testRange) { // Select just the inner-most text to normalize the MarkupRange before comparing it. testRange.SelectInner(); int pos = BinarySearch(words.Keys, testRange.Start.PointerRaw, new MarkupPointerComparer()); if (pos >= 0) { if (words.Values[pos].End.IsLeftOf(testRange.End)) { Debug.Fail("testRange partially overlaps with range"); try { Debug.WriteLine("testRange: [" + testRange.Text + "]"); Debug.WriteLine("thisRange: [" + words.Values[pos].Text + "]"); } catch (Exception e) { Debug.WriteLine(e.ToString()); } } return(true); } pos = (~pos) - 1; if (pos < 0) { return(false); } if (words.Values[pos].End.IsRightOf(testRange.Start)) { if (words.Values[pos].End.IsLeftOf(testRange.End)) { #if DEBUG MarkupRange temp = testRange.Clone(); temp.Start.MoveToPointer(words.Values[pos].End); if ((temp.Text ?? "").Trim().Length > 0) { Debug.Fail("testRange partially overlaps with range"); try { Debug.WriteLine("testRange: [" + testRange.Text + "]"); Debug.WriteLine("thisRange: [" + words.Values[pos].Text + "]"); Debug.WriteLine("overlap: [" + temp.Text + "]"); } catch (Exception e) { Debug.WriteLine(e.ToString()); } } #endif } return(true); } return(false); }
/// <summary> /// Expands a range to the safest outter tags that can be contained without encompassing /// text that is not currently in this range. /// </summary> /// <param name="range"></param> private void SelectOuter(MarkupRange range) { IHTMLElement parent = range.ParentElement(); MarkupRange editableRange = MarkupHelpers.GetEditableRange(parent, MarkupServices); if (editableRange == null) { return; } while (parent != null && range.MoveOutwardIfNoContent()) { parent = range.Start.CurrentScope; } if (range.Start.IsLeftOf(editableRange.Start)) { range.Start.MoveToPointer(editableRange.Start); } if (range.End.IsRightOf(editableRange.End)) { range.End.MoveToPointer(editableRange.End); } return; }
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); }
public void EnqueueDamage(MarkupRange range) { lock (damagedRanges) { damagedRanges.Add(range); } }
private static void NormalizeBounds(ref MarkupRange bounds) { bool cloned = false; if (bounds.Start.IsRightOf(bounds.End)) { if (!cloned) { cloned = true; bounds = bounds.Clone(); } bounds.Normalize(); } MarkupContext ctx = bounds.Start.Right(false); while (ctx.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_EnterScope && ElementFilters.IsBlockElement(ctx.Element)) { if (!cloned) { cloned = true; bounds = bounds.Clone(); } bounds.Start.Right(true); bounds.Start.Right(false, ctx); } }
/// <summary> /// Create a MarkupRange from a TextRange. /// </summary> /// <param name="textRange"></param> /// <returns></returns> public MarkupRange CreateMarkupRange(IHTMLTxtRange textRange) { MarkupPointer Begin = CreateMarkupPointer(); MarkupPointer End = CreateMarkupPointer(); End.Gravity = _POINTER_GRAVITY.POINTER_GRAVITY_Right; MovePointersToRange(textRange, Begin, End); MarkupRange markupRange = new MarkupRange(Begin, End, this); return markupRange; }
/// <summary> /// Create a MarkupRange from a set of MarkupPointers. /// </summary> /// <param name="start"></param> /// <param name="end"></param> /// <returns></returns> public MarkupRange CreateMarkupRange(MarkupPointer start, MarkupPointer end) { MarkupRange markupRange = new MarkupRange(start, end, this); return markupRange; }
public SelectionPreserver(MarkupRange selectedMarkupRange) { _preservedMarkupRange = selectedMarkupRange.Clone(); _preservedMarkupRange.Start.Cling = true; _preservedMarkupRange.End.Cling = true; }
/// <summary> /// Create a MarkupRange from that surrounds an Element. /// </summary> /// <returns></returns> public MarkupRange CreateMarkupRange(IHTMLElement element, bool outside) { _ELEMENT_ADJACENCY beginAdj = outside ? _ELEMENT_ADJACENCY.ELEM_ADJ_BeforeBegin : _ELEMENT_ADJACENCY.ELEM_ADJ_AfterBegin; _ELEMENT_ADJACENCY endAdj = outside ? _ELEMENT_ADJACENCY.ELEM_ADJ_AfterEnd : _ELEMENT_ADJACENCY.ELEM_ADJ_BeforeEnd; MarkupPointer Begin = CreateMarkupPointer(element, beginAdj); MarkupPointer End = CreateMarkupPointer(element, endAdj); End.Gravity = _POINTER_GRAVITY.POINTER_GRAVITY_Right; MarkupRange markupRange = new MarkupRange(Begin, End, this); return markupRange; }