/// <summary> /// Grabs HTML copied in the clipboard and pastes it into the document (pulls in a copy of embedded content too) /// </summary> protected override bool DoInsertData(DataAction action, MarkupPointer begin, MarkupPointer end) { using (new WaitCursor()) { try { // get the list of files from the data meister FileItem[] files = DataMeister.FileData.Files; string[] filePaths = new string[files.Length]; // create an array of file entities to insert for (int i = 0; i < files.Length; i++) { filePaths[i] = files[i].ContentsPath; } string html = EditorContext.HtmlGenerationService.GenerateHtmlFromFiles(filePaths); EditorContext.InsertHtml(begin, end, html, null); //place the caret at the end of the inserted content //EditorContext.MoveCaretToMarkupPointer(end, true); return true; } catch (Exception e) { //bugfix 1696, put exceptions into the trace log. Trace.Fail("Exception while inserting HTML: " + e.Message, e.StackTrace); return false; } } }
protected override bool DoInsertData(DataAction action, MarkupPointer begin, MarkupPointer end) { // get the table and its cells IHTMLTable sourceTable = GetSourceTable(DataMeister); IHTMLElementCollection cells = (sourceTable as IHTMLElement2).getElementsByTagName("td"); // single-cell tables just get the innerHTML of the cell pasted at the selection if (cells.length == 1) { IHTMLElement cell = cells.item(0, 0) as IHTMLElement; EditorContext.InsertHtml(begin, end, cell.innerHTML, UrlHelper.GetBaseUrl(DataMeister.HTMLData.SourceURL)); } else { // if we are inside a table TableSelection tableSelection = new TableSelection(EditorContext.MarkupServices.CreateMarkupRange(begin, end)); if (tableSelection.Table != null) { // paste the source cells into the table PasteCellsIntoTable(sourceTable, tableSelection); } else { // get table html (make sure width matches # of rows selected) TableHelper.SynchronizeTableWidthForEditing(sourceTable); string html = (sourceTable as IHTMLElement).outerHTML; // insert the html (nests within an undo unit) EditorContext.InsertHtml(begin, end, html, UrlHelper.GetBaseUrl(DataMeister.HTMLData.SourceURL)); } } return true; }
/// <summary> /// Insert html at the given pointer. /// </summary> /// <param name="html"></param> /// <param name="insertionPoint"></param> public void InsertHtml(string html, MarkupPointer insertionPoint) { MarkupRange content = CreateMarkupRange(); ParseString(html, content.Start, content.End); Move(content.Start, content.End, insertionPoint); }
/// <summary> /// Create an unpositioned MarkupRange. /// </summary> /// <returns></returns> public MarkupRange CreateMarkupRange() { MarkupPointer start = CreateMarkupPointer(); MarkupPointer end = CreateMarkupPointer(); end.Gravity = _POINTER_GRAVITY.POINTER_GRAVITY_Right; return(CreateMarkupRange(start, end)); }
public void EnsureStartIsBeforeEnd() { if (Start.IsRightOf(End)) { MarkupPointer temp = End.Clone(); End = Start.Clone(); Start = temp; } }
public void Normalize() { if (Start.IsRightOf(End)) { MarkupPointer tmp = Start; Start = End; End = tmp; } }
/// <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); } }
/// <summary> /// Create a text range spanning the specified markup positions. /// </summary> /// <param name="start">the start point of the text range</param> /// <param name="end">the end point of the text range</param> /// <returns></returns> public IHTMLTxtRange CreateTextRange(MarkupPointer start, MarkupPointer end) { // when switching between wywiwyg and source view sometimes .body is null // and this throws a null ref exception that we catch (can be detected by enabling // exception breaking in the debugger) IHTMLTxtRange range = (Document.body as IHTMLBodyElement).createTextRange(); MarkupServices.MoveRangeToPointers(start, end, range); return range; }
/// <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> /// Returns a copy of this markup pointer that is positioned at the same location. /// </summary> /// <returns></returns> public MarkupPointer Clone() { MarkupPointer p = MarkupServices.CreateMarkupPointer(this); p.Cling = Cling; p.Gravity = Gravity; p.clingStack = (Stack)clingStack.Clone(); p.gravityStack = (Stack)gravityStack.Clone(); return(p); }
/// <summary> /// Create a text range spanning the specified markup positions. /// </summary> /// <param name="start">the start point of the text range</param> /// <param name="end">the end point of the text range</param> /// <returns></returns> public IHTMLTxtRange CreateTextRange(MarkupPointer start, MarkupPointer end) { // when switching between wywiwyg and source view sometimes .body is null // and this throws a null ref exception that we catch (can be detected by enabling // exception breaking in the debugger) IHTMLTxtRange range = (Document.body as IHTMLBodyElement).createTextRange(); MarkupServices.MoveRangeToPointers(start, end, range); return(range); }
/// <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); }
private static void MovePointer(MarkupPointer p, MoveDirection d, MarkupContext context) { if (d == MoveDirection.LEFT) { p.Left(true, context); } else { p.Right(true, context); } }
/// <summary> /// Returns true if the specified pointer is in a position between, or equal to this range's Start/End points. /// </summary> /// <param name="p"></param> /// <returns></returns> public bool InRange(MarkupPointer p, bool allowEquals) { if (allowEquals) { return(Start.IsLeftOfOrEqualTo(p) && End.IsRightOfOrEqualTo(p)); } else { return(Start.IsLeftOf(p) && End.IsRightOf(p)); } }
private static bool CheckMoveBoundary(MarkupPointer p, MarkupPointer boundary, MoveDirection d) { if (d == MoveDirection.LEFT) { return(p.IsRightOf(boundary)); } else { return(p.IsLeftOf(boundary)); } }
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; }
/// <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); }
public TypographicCharacterHandler(MarkupRange currentSelection, InsertHtml insertHtml, IBlogPostImageEditingContext imageEditingContext, IHTMLElement postBodyElement, char c, string htmlText, MarkupPointer blockBoundary) { _currentSelection = currentSelection.Clone(); _currentSelection.Start.Gravity = _POINTER_GRAVITY.POINTER_GRAVITY_Right; _currentSelection.End.Gravity = _POINTER_GRAVITY.POINTER_GRAVITY_Left; _insertHtml = insertHtml; _imageEditingContext = imageEditingContext; _postBodyElement = postBodyElement; this.c = c; this.htmlText = htmlText; this.blockBoundary = blockBoundary; }
private static void AdjustMarkupRangeCore(MarkupRange range, int offset, int length, string currentText) { MarkupPointer start = range.Start; MarkupPointer end = range.End; if (offset > 0) { start.MoveToMarkupPosition(start.Container, start.MarkupPosition + offset); } if (length < (offset + currentText.Length)) { end.MoveToMarkupPosition(start.Container, start.MarkupPosition + length); } }
public static void PerformImageBreakout(MarkupPointer p) { Direction dir = ImageBreakout(p); if (dir == Direction.Right) { p.MoveAdjacentToElement(p.CurrentScope, _ELEMENT_ADJACENCY.ELEM_ADJ_AfterEnd); } if (dir == Direction.Left) { p.MoveAdjacentToElement(p.CurrentScope, _ELEMENT_ADJACENCY.ELEM_ADJ_BeforeBegin); } }
/// <summary> /// Returns true if the specified element begins and ends within the range. /// </summary> /// <param name="e"></param> /// <returns></returns> private bool isInScope(IHTMLElement e) { MarkupPointer p = MarkupServices.CreateMarkupPointer(e, _ELEMENT_ADJACENCY.ELEM_ADJ_BeforeBegin); if (p.IsRightOfOrEqualTo(Start)) { p = MarkupServices.CreateMarkupPointer(e, _ELEMENT_ADJACENCY.ELEM_ADJ_AfterEnd); if (p.IsLeftOfOrEqualTo(End)) { return(true); } } return(false); }
/// <summary> /// Creates a MarkupContainer that contains the results of parsing the contents of a string. /// </summary> /// <param name="html">html content to parse</param> /// <param name="start">pointer to position at the beginning of the parsed content (null is allowed)</param> /// <param name="end">pointer to position at the end of the parsed content (null is allowed)</param> /// <returns></returns> public MarkupContainer ParseString(string html, MarkupPointer start, MarkupPointer end) { if (start == null) { start = CreateMarkupPointer(); } if (end == null) { end = CreateMarkupPointer(); } IMarkupContainerRaw container; MarkupServices.ParseString(html, 0, out container, start.PointerRaw, end.PointerRaw); return(new MarkupContainer(this, container)); }
public static void SplitBlockForInsertionOrBreakout(MshtmlMarkupServices markupServices, MarkupRange bounds, MarkupPointer insertAt) { IHTMLElement currentBlock = insertAt.GetParentElement(ElementFilters.BLOCK_OR_TABLE_CELL_ELEMENTS); if (currentBlock == null) { return; } if (ElementFilters.IsBlockQuoteElement(currentBlock) || ElementFilters.IsTableCellElement(currentBlock)) { return; } MarkupPointer blockStart = markupServices.CreateMarkupPointer(currentBlock, _ELEMENT_ADJACENCY.ELEM_ADJ_BeforeBegin); MarkupPointer blockEnd = markupServices.CreateMarkupPointer(currentBlock, _ELEMENT_ADJACENCY.ELEM_ADJ_AfterEnd); if (bounds != null && (blockStart.IsLeftOf(bounds.Start) || blockEnd.IsRightOf(bounds.End))) { return; } // Don't split if at the beginning or end of the visible content in the block. // Instead just move the insertion point outside the block. MarkupRange testRange = markupServices.CreateMarkupRange(); testRange.Start.MoveToPointer(insertAt); testRange.End.MoveAdjacentToElement(currentBlock, _ELEMENT_ADJACENCY.ELEM_ADJ_BeforeEnd); if (testRange.IsEmptyOfContent()) { insertAt.MoveAdjacentToElement(currentBlock, _ELEMENT_ADJACENCY.ELEM_ADJ_AfterEnd); return; } testRange.Start.MoveAdjacentToElement(currentBlock, _ELEMENT_ADJACENCY.ELEM_ADJ_AfterBegin); testRange.End.MoveToPointer(insertAt); if (testRange.IsEmptyOfContent()) { insertAt.MoveAdjacentToElement(currentBlock, _ELEMENT_ADJACENCY.ELEM_ADJ_BeforeBegin); return; } MarkupPointer moveTarget = markupServices.CreateMarkupPointer(blockEnd); markupServices.Move(insertAt, blockEnd, moveTarget); insertAt.MoveAdjacentToElement(currentBlock, _ELEMENT_ADJACENCY.ELEM_ADJ_AfterEnd); }
/// <summary> /// Returns null if ranges do not intersect /// </summary> /// <param name="range"></param> /// <returns></returns> public MarkupRange Intersect(MarkupRange range) { MarkupPointer maxStart = Start.IsRightOf(range.Start) ? Start : range.Start; MarkupPointer minEnd = End.IsLeftOf(range.End) ? End : range.End; if (minEnd.IsLeftOf(maxStart)) { return(null); } MarkupRange intersection = MarkupServices.CreateMarkupRange(); intersection.Start.MoveToPointer(maxStart); intersection.End.MoveToPointer(minEnd); return(intersection); }
/// <summary> /// Shrinks the range until further shrinking would exclude text that is currently in the range. /// </summary> public void SelectInner() { // Without this check, the start pointer can move outside // of the current container tag (e.g. ...text...|</p> => </p>|) if (IsEmpty()) { return; } EnsureStartIsBeforeEnd(); // Move the start until you hit text MarkupPointer innerStart = GetFirstTextPoint(Start, true); MarkupPointer innerEnd = GetFirstTextPoint(End, false); Start = innerStart; End = innerEnd; }
//this is similar to the GetTopLevelElements except will also return table cells if correct filter // is set and recurse is equal to true public IHTMLElement[] GetTopLevelBlocksAndCells(IHTMLElementFilter filter, bool recurse) { ArrayList list = new ArrayList(); Hashtable usedElements = new Hashtable(); MarkupPointer p = MarkupServices.CreateMarkupPointer(Start); MarkupContext context = p.Right(false); //move p through the range to locate each of the top level elements while (p.IsLeftOf(End)) { if (context.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_EnterScope || context.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_NoScope) { p.MoveAdjacentToElement(context.Element, _ELEMENT_ADJACENCY.ELEM_ADJ_AfterEnd); if (usedElements[context.Element] == null) { if (p.IsLeftOfOrEqualTo(End) && (filter == null || filter(context.Element))) { list.Add(context.Element); } //special case--inside of a table element, want to get out the cells inside else if (recurse && ElementFilters.TABLE_ELEMENTS(context.Element)) { MarkupRange newRange = MarkupServices.CreateMarkupRange(context.Element); newRange.Start.MoveAdjacentToElement(context.Element, _ELEMENT_ADJACENCY.ELEM_ADJ_AfterBegin); if (newRange.Start.IsLeftOf(Start)) { newRange.Start.MoveToPointer(Start); } if (newRange.End.IsRightOf(End)) { newRange.End.MoveToPointer(End); } //recursively check inside table element for table cells list.AddRange(newRange.GetTopLevelBlocksAndCells(filter, true)); } //cache the fact that we've already tested this element. usedElements[context.Element] = context.Element; } } p.Right(true, context); } return(HTMLElementHelper.ToElementArray(list)); }
/// <summary> /// Checks if the MarkupPointer is inside of an anchor that only contains /// an image, and if so, moves the pointer to be outside the anchor. /// This prevents cases where hyperlinked images were getting nested inside /// of each other as a result of drag and drop. /// </summary> public static Direction ImageBreakout(MarkupPointer p) { // If inside <a><img></a>, then move to outside IHTMLElement currentScope = p.CurrentScope; if (currentScope is IHTMLAnchorElement) { IHTMLDOMNode anchor = (IHTMLDOMNode)currentScope; if (anchor.hasChildNodes() && anchor.firstChild is IHTMLImgElement && anchor.firstChild.nextSibling == null) { // Figure out if we are positioned before or after the image; this will determine // whether we want to move before or after the anchor return((p.Right(false).Element is IHTMLImgElement) ? Direction.Left : Direction.Right); } } return(Direction.None); }
/// <summary> /// Grabs text copied in the clipboard and pastes it into the document /// </summary> protected override bool DoInsertData(DataAction action, MarkupPointer begin, MarkupPointer end) { try { // get the text data as a string string textData = DataMeister.TextData.Text; string html = EditorContext.HtmlGenerationService.GenerateHtmlFromPlainText(textData); //insert captured content into the document EditorContext.InsertHtml(begin, end, html, null); return true; } catch (Exception e) { //bugfix 1696, put exceptions into the trace log. Trace.Fail("Exception while inserting URL: " + e.Message, e.StackTrace); return false; } }
public static void TraceMoveToMarkupPointer(IDisplayPointerRaw displayPointer, MarkupPointer markupPointer) { try { if (displayPointer == null) throw new ArgumentException("Unexpected null display pointer."); if (markupPointer == null) throw new ArgumentException("Unexpected null markup pointer."); //position a display pointer on the same line as the markup pointer displayPointer.MoveToMarkupPointer(markupPointer.PointerRaw, null); } catch (Exception e) { Trace.Fail("Unexpected exception in TraceMoveToMarkupPointer: " + e.ToString()); throw; } }
/// <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); }
public IHTMLElement SeekElementRight(IHTMLElementFilter filter, MarkupPointer boundaryPointer) { // initialize markup context used to track seeking MarkupContext markupContext = new MarkupContext(); markupContext.Context = _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_NoScope; while ((boundaryPointer == null || IsLeftOf(boundaryPointer)) && // apply boundary if one exists (markupContext.Context != _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_None)) // otherwise use end of document { Right(true, markupContext); IHTMLElement element = markupContext.Element; if (element != null && filter(element)) { return(element); } } // none found return(null); }
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> /// Gets the elements in the range that match the filter. /// </summary> /// <param name="filter">the delegate testing each element to determine if it should be added to the list of elements to return</param> /// <param name="inScopeElementsOnly">if true, the only</param> /// <returns></returns> public IHTMLElement[] GetElements(IHTMLElementFilter filter, bool inScopeElementsOnly) { ArrayList list = new ArrayList(); if (!IsEmpty()) { Hashtable usedElements = new Hashtable(); MarkupPointer p = MarkupServices.CreateMarkupPointer(Start); MarkupPointer end = MarkupServices.CreateMarkupPointer(End); MarkupContext context = p.Right(false); //move p through the range to locate each the elements adding elements that pass the filter while (p.IsLeftOfOrEqualTo(end)) { if (context.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_EnterScope || context.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_ExitScope || context.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_NoScope) { if (usedElements[context.Element] == null) { if ((inScopeElementsOnly && isInScope(context.Element)) || !inScopeElementsOnly) { if (filter(context.Element)) { list.Add(context.Element); } } //cache the fact that we've already tested this element. usedElements[context.Element] = context.Element; } } p.Right(true, context); } } return(HTMLElementHelper.ToElementArray(list)); }
private static void MoveUnitBounded(MarkupPointer p, MoveDirection direction, MoveContextFilter continueFilter, MarkupPointer boundary) { MarkupPointer p1 = p.Clone(); MarkupPointer lastGoodPosition = p.Clone(); MarkupContext context = new MarkupContext(); MoveFilterResult result = MoveFilterResult.CONTINUE; while (CheckMoveBoundary(p1, boundary, direction) && result == MoveFilterResult.CONTINUE) { lastGoodPosition.MoveToPointer(p1); MovePointer(p1, direction, context); result = continueFilter(context); } if (result == MoveFilterResult.CONTINUE) { //we hit the boundary, so position pointer at the boundary p1.MoveToPointer(boundary); } else if (result == MoveFilterResult.STOP_BACK) { p1.MoveToPointer(lastGoodPosition); } p.MoveToPointer(p1); }
public bool IsAdjacentToWordEnd(MarkupPointer p) { lock (_p) { _p.MoveToPointer(p); _p.MoveUnit(_MOVEUNIT_ACTION.MOVEUNIT_NEXTCHAR); _p.MoveUnit(_MOVEUNIT_ACTION.MOVEUNIT_PREVWORDEND); return _p.IsEqualTo(p); } }
private float GetFontSizeAt(MarkupPointer location) { IDisplayServicesRaw displayServices = (IDisplayServicesRaw)HTMLDocument; IHTMLComputedStyle computedStyle; displayServices.GetComputedStyle(location.PointerRaw, out computedStyle); float pixels = DisplayHelper.TwipsToPixelsY(computedStyle.fontSize); float points = HTMLElementHelper.PixelsToPointSize(pixels, true); return points; }
public void MoveToWordEnd(MarkupPointer p) { lock (_p) { _p.MoveToPointer(p); _p2.MoveToPointer(p); _p.MoveUnit(_MOVEUNIT_ACTION.MOVEUNIT_NEXTWORDBEGIN); _p2.MoveUnit(_MOVEUNIT_ACTION.MOVEUNIT_NEXTWORDEND); // If CurrentScope is null, this means we have walked off the end of the // document, in that case we don't want to move the pointer, at is already // at the end of word. if (_p2.IsLeftOfOrEqualTo(_p) && _p.CurrentScope != null) p.MoveToPointer(_p2); //else, the pointer is already at the end of the current word } }
private IDisposable CreateDamageTracking(MarkupPointer end, bool p) { return _damageServices.CreateDamageTracker(end, end, true); }
/// <summary> /// Moves the pointer one unit, but not past a given markup pointer's position. /// </summary> /// <param name="muAction"></param> public void MoveUnitBounded(_MOVEUNIT_ACTION muAction, MarkupPointer boundary) { (PointerRaw as IMarkupPointer2Raw).MoveUnitBounded(muAction, boundary.PointerRaw); }
/// <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; }
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; }
private bool OverwriteDestinationBlockIfEmpty(MarkupPointer destinationStart, MarkupRange bounds) { bool blockOverwritten = false; IHTMLElement parentBlockElement = destinationStart.GetParentElement(ElementFilters.BLOCK_ELEMENTS); if (parentBlockElement != null) { MarkupRange parentBlockRange = MarkupServices.CreateMarkupRange(parentBlockElement, false); if (bounds.InRange(parentBlockRange, false)) { if (PrimaryEditableBounds == null || PrimaryEditableBounds.InRange(parentBlockRange)) { if (parentBlockRange.IsEmptyOfContent()) { parentBlockRange.MoveToElement(parentBlockElement, true); DeleteContentNoCling(parentBlockRange.Start, parentBlockRange.End); // Check to see if the delete we just did caused the insertion point to be // to become a no longer positioned, and if it did we move it to the start // of what we deleted if (!destinationStart.Positioned) { //Debug.WriteLine("Invalid pointer after delete, moving the target pointer to the start of the deleted markup."); destinationStart.MoveToPointer(parentBlockRange.Start); } blockOverwritten = true; } } } } return blockOverwritten; }
public IDisposable CreateDamageTracker(MarkupPointer start, MarkupPointer end, bool includeAdjacentWords) { if (DamageTrackingEnabled) return new DamageTracker(this, start, end, includeAdjacentWords); else return null; }
public static void MoveUnitBounded(MarkupPointer p, MoveDirection direction, MarkupPointerAdjacency stopRule, MarkupPointer boundary) { MoveContextFilter filter = CreateMoveContextFilter(stopRule); MoveUnitBounded(p, direction, filter, boundary); }
void IHtmlMarshallingTarget.InsertHtml(MarkupPointer start, MarkupPointer end, string html, string sourceUrl) { InsertHtml(start, end, html, sourceUrl, true); }
/// <summary> /// Utility for deleting a range of content while suppressing pointer cling. /// </summary> /// <param name="start"></param> /// <param name="end"></param> private void DeleteContentNoCling(MarkupPointer start, MarkupPointer end) { start.PushCling(false); end.PushCling(false); try { DeleteContent(start, end); } finally { start.PopCling(); end.PopCling(); } }
/// <summary> /// Delete the content between 2 pointers from the document. /// </summary> /// <param name="start"></param> /// <param name="end"></param> private void DeleteContent(MarkupPointer start, MarkupPointer end) { MarkupRange range = MarkupServices.CreateMarkupRange(start, end); DeleteContent(range); }
/// <summary> /// Grabs HTML copied in the clipboard and pastes it into the document (pulls in a copy of embedded content too) /// </summary> protected override bool DoInsertData(DataAction action, MarkupPointer begin, MarkupPointer end) { using (new WaitCursor()) { try { //StringBuilder html = new StringBuilder(); //html.AppendFormat("<a href=\"{0}\">{1}</a>", DataMeister.URLData.URL, DataMeister.URLData.Title); string html = EditorContext.HtmlGenerationService.GenerateHtmlFromLink(Url, Title, Title, String.Empty, false); EditorContext.InsertHtml(begin, end, html, null); //place the caret at the end of the inserted content //EditorContext.MoveCaretToMarkupPointer(end, true); return true; } catch (Exception e) { //bugfix 1696, put exceptions into the trace log. Trace.Fail("Exception while inserting URL: " + e.Message, e.StackTrace); return false; } } }
public DamageTracker(HtmlEditorControlDamageServices damageServices, MarkupPointer start, MarkupPointer end, bool includeAdjacentWords) { _damageServices = damageServices; _damageRange = damageServices.wordRangeDamager.CreateDamageTrackingRange(start, end, includeAdjacentWords); }
protected virtual bool ContentIsDeletableForInsert(MarkupPointer start, MarkupPointer end) { return true; }
internal MarkupRange CreateDamageTrackingRange(MarkupPointer start, MarkupPointer end, bool includeAdjecentWords) { MarkupRange range = _mshtmlEditor.MshtmlControl.MarkupServices.CreateMarkupRange(); range.Start.MoveToPointer(start); range.Start.Gravity = _POINTER_GRAVITY.POINTER_GRAVITY_Left; range.End.MoveToPointer(end); range.End.Gravity = _POINTER_GRAVITY.POINTER_GRAVITY_Right; _wordHelper.MoveToWordStart(range.Start); _wordHelper.MoveToWordEnd(range.End); if (includeAdjecentWords) { ExpandDamageToAdjacentWords(range); } return range; }
private void DeleteInsertionTargetBlockIfEmpty(MarkupPointer insertionPoint) { //locate the parent block element (stop at post body element) IHTMLElement parent = insertionPoint.GetParentElement( ElementFilters.CreateCompoundElementFilter(ElementFilters.CreateElementEqualsFilter(HTMLElement), ElementFilters.BLOCK_ELEMENTS)); if (parent != null && parent.sourceIndex != HTMLElement.sourceIndex && //never remove the post body block EditorContext.MarkupServices.CreateMarkupRange(parent, false).IsEmptyOfContent()) { //delete the empty parent block element (parent as IHTMLDOMNode).removeNode(true); } }
public MarkupServicesWordHelper(MshtmlMarkupServices markupServices) { MarkupServices = markupServices; _p = MarkupServices.CreateMarkupPointer(); _p2 = MarkupServices.CreateMarkupPointer(); }
private void EnsureNewLineAtDocEnd(MarkupPointer mpStart, MarkupPointer mpEnd) { // Add a <p></p> at the end of the document if there isn't one. MarkupPointer endBody = MarkupServices.CreateMarkupPointer(); endBody.MoveAdjacentToElement(PostBodyElement, _ELEMENT_ADJACENCY.ELEM_ADJ_BeforeEnd); // If we have to insert the <p> this is where we will do it, so save it for later MarkupPointer insertLocation = endBody.Clone(); // Move left one more time to find out if it is p with a space in it. endBody.Left(true); // Check to see if it a p with a space. We use innerHtml because if the html looked like // <p><img ...> </p> innerText only reports " " though this isnt really just a blank line. // We dont use HtmlUtils.HtmlToText because it will replace img tags as a space. if (endBody.CurrentScope.tagName != "P" || endBody.CurrentScope.innerHTML != " ") { // Move it into the real document IHTMLDocument2 docInsert = mpStart.GetDocument(); MarkupRange stagingRangeInsert = MarkupServices.CreateMarkupRange(mpStart, mpEnd); stagingRangeInsert.MoveToElement(docInsert.body, false); MarkupServices.Move(stagingRangeInsert.Start, stagingRangeInsert.End, insertLocation); } }
public void MoveToWordStart(MarkupPointer p) { lock (_p) { _p.MoveToPointer(p); _p2.MoveToPointer(p); _p.MoveUnit(_MOVEUNIT_ACTION.MOVEUNIT_PREVWORDEND); _p2.MoveUnit(_MOVEUNIT_ACTION.MOVEUNIT_PREVWORDBEGIN); if (_p2.IsRightOfOrEqualTo(_p)) p.MoveToPointer(_p2); //else, the pointer is already at the start of the current word } }
/// <summary> /// Moves this pointer to another pointer's location. /// </summary> /// <param name="p"></param> public void MoveToPointer(MarkupPointer p) { PointerRaw.MoveToPointer(p.PointerRaw); }
public bool IsAdjacentToWordStart(MarkupPointer p) { lock (_p) { _p.MoveToPointer(p); _p.MoveUnit(_MOVEUNIT_ACTION.MOVEUNIT_PREVCHAR); _p.MoveUnit(_MOVEUNIT_ACTION.MOVEUNIT_NEXTWORDBEGIN); return _p.IsEqualTo(p); } }
public void InsertPlainText(MarkupPointer start, MarkupPointer end, string text) { IUndoUnit undo = CreateUndoUnit(); using (undo) { if (!start.IsEqualTo(end)) { DeleteContentNoCling(start, end); } if (start.CurrentScope.tagName == "PRE") { //if pasting into a preblock, then we want to preserve the whitespace in //the text, and we don't want to convert line breaks into <BR>. MSHTML //is really nasty about tossing out whitespace, but will keep its hands //off the text as long as it has <pre> tags around it //hack MSHTML's whitespace mangling by the text wrapping in a <pre> tag //for insertion, and then yank it. text = "<pre>" + HttpUtility.HtmlEncode(text) + "</pre>"; MarkupRange range = MarkupServices.CreateMarkupRange(); MarkupContainer c = MarkupServices.ParseString(text, range.Start, range.End); range.MoveToElement((IHTMLElement)(c.Document.body as IHTMLDOMNode).firstChild, false); MarkupServices.Move(range.Start, range.End, start); } else { //if this insn't wrapped in a <pre> tag, then use a textRange to insert the //text so that it will be padded with <BR> and  . MarkupRange range = MarkupServices.CreateMarkupRange(start, end); IHTMLTxtRange txtRange = range.ToTextRange(); txtRange.text = text; } undo.Commit(); } }
public virtual bool ShouldMoveDropLocationRight(MarkupPointer dropLocation) { return false; }