public static String ToFormattedHtml(MshtmlMarkupServices markupServices, MarkupRange bounds) { StringBuilder sb = new StringBuilder(); HtmlWriter xmlWriter = new HtmlWriter(sb); PrintHtml(xmlWriter, markupServices, bounds); return sb.ToString(); }
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; }
public virtual string GetEditedHtml(bool useXhtml, bool doCleanup) { try { if (doCleanup || useXhtml) { MshtmlMarkupServices markupServices = new MshtmlMarkupServices(HTMLElement.document as IMarkupServicesRaw); if (doCleanup) { MarkupRange bodyRange = markupServices.CreateMarkupRange(((IHTMLDocument2)HTMLElement.document).body, false); bodyRange.RemoveElementsByTagId(_ELEMENT_TAG_ID.TAGID_FONT, true); } if (useXhtml) { MarkupRange bounds = markupServices.CreateMarkupRange(HTMLElement, false); string xhtml = FormattedHtmlPrinter.ToFormattedHtml(markupServices, bounds); return doCleanup ? CleanupHtml(xhtml, true) : xhtml; } } } catch (Exception e) { // E.g. this failure case: <pre><b></pre></b> Trace.Fail("Exception generating XHTML: " + e.ToString()); } string html = HTMLElement.innerHTML ?? String.Empty; if (doCleanup) return CleanupHtml(html, false); else return html; }
private void Init(IHTMLDocument document, MshtmlMarkupServices markupServices, MarkupRange selectionRange, MarkupRangeFilter filter, DamageFunction damageFunction, bool expandRange) { // save references this.htmlDocument = document; this.markupServices = markupServices; this.selectionRange = selectionRange; this.filter = filter; this.damageFunction = damageFunction; // If the range is already the body, don't expand it or else it will be the whole document if (expandRange) ExpandRangeToWordBoundaries(selectionRange); // initialize pointer to beginning of selection range MarkupPointer wordStart = MarkupServices.CreateMarkupPointer(selectionRange.Start); MarkupPointer wordEnd = MarkupServices.CreateMarkupPointer(selectionRange.Start); //create the range for holding the current word. //Be sure to set its gravity so that it stays around text that get replaced. currentWordRange = MarkupServices.CreateMarkupRange(wordStart, wordEnd); currentWordRange.Start.Gravity = _POINTER_GRAVITY.POINTER_GRAVITY_Left; currentWordRange.End.Gravity = _POINTER_GRAVITY.POINTER_GRAVITY_Right; currentVirtualPosition = currentWordRange.End.Clone(); }
public static MarkupRange GetEditableRange(IHTMLElement e, MshtmlMarkupServices markupServices) { IHTMLElement3 editableElement = null; while (e != null) { if (((IHTMLElement3)e).isContentEditable) { editableElement = (IHTMLElement3)e; if (ElementFilters.IsBlockElement(e)) { break; } } else { break; } e = e.parentElement; } if (editableElement != null) { return(markupServices.CreateMarkupRange((IHTMLElement)editableElement, false)); } else { return(null); } }
private static void PrintHtml(HtmlWriter writer, MshtmlMarkupServices MarkupServices, MarkupRange bounds) { //create a range to span a single position while walking the doc MarkupRange range = MarkupServices.CreateMarkupRange(); range.Start.MoveToPointer(bounds.Start); range.End.MoveToPointer(bounds.Start); //create a context that can be reused while walking the document. MarkupContext context = new MarkupContext(); //move the range.End to the right and print out each element along the way range.End.Right(true, context); while (context.Context != _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_None && range.Start.IsLeftOf(bounds.End)) { string text = null; if (context.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_Text) { //if this is a text context, then get the text that is between the start and end points. text = range.HtmlText; //the range.HtmlText operation sometimes returns the outer tags for a text node, //so we need to strip the tags. //FIXME: if the Right/Left operations returned the available text value, this wouldn't be necessary. if (text != null) text = StripSurroundingTags(text); } else if (context.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_ExitScope) { string htmlText = range.HtmlText; if (context.Element.innerHTML == null && htmlText != null && htmlText.IndexOf(" ") != -1) { //HACK: Under these conditions, there was a was an invisible NBSP char in the //document that is not detectable by walking through the document with MarkupServices. //So, we force the text of the element to be the char to ensure that the //whitespace that was visible in the editor is visible in the final document. text = " "; } } //print the context. printContext(writer, context, text, range); //move the start element to the spot where the end currently is so tht there is //only ever a single difference in position range.Start.MoveToPointer(range.End); //move the end to the next position range.End.Right(true, context); } }
public SpellingHighlighter(ISpellingChecker spellingChecker, IHighlightRenderingServicesRaw highlightRenderingServices, IDisplayServicesRaw displayServices, IMarkupServicesRaw markupServices, IHTMLDocument4 htmlDocument) { _spellingChecker = spellingChecker; _highlightRenderingServices = highlightRenderingServices; _displayServices = displayServices; _markupServicesRaw = markupServices; _markupServices = new MshtmlMarkupServices(_markupServicesRaw); _htmlDocument = htmlDocument; _tracker = new HighlightSegmentTracker(); //the timer to handle interleaving of spell ghecking _timer = new SpellingTimer(TIMER_INTERVAL); _timer.Start(); _timer.Tick += new EventHandler(_timer_Tick); _workerQueue = new Queue(); }
public KeepSourceFormatting(MarkupRange sourceRange, MarkupRange destinationRange) { Debug.Assert(sourceRange.Start.Container.GetOwningDoc() == destinationRange.Start.Container.GetOwningDoc(), "Ranges must share an owning document!"); if (sourceRange == null) { throw new ArgumentNullException("sourceRange"); } if (!sourceRange.Positioned) { throw new ArgumentException("sourceRange must be positioned."); } if (sourceRange.Start.IsRightOf(sourceRange.End)) { throw new ArgumentException("sourceRange start must be before range end."); } if (destinationRange == null) { throw new ArgumentNullException("destinationRange"); } if (!destinationRange.Positioned) { throw new ArgumentException("destinationRange must be positioned."); } if (destinationRange.Start.IsRightOf(destinationRange.End)) { throw new ArgumentException("destinationRange start must be before range end."); } this.sourceDocument = sourceRange.Start.Container.Document; this.sourceMarkupServices = new MshtmlMarkupServices((IMarkupServicesRaw)this.sourceDocument); this.sourceRange = sourceRange.Clone(); this.sourceRange.Start.Gravity = _POINTER_GRAVITY.POINTER_GRAVITY_Left; this.sourceRange.End.Gravity = _POINTER_GRAVITY.POINTER_GRAVITY_Right; this.destinationDocument = destinationRange.Start.Container.Document; this.destinationMarkupServices = new MshtmlMarkupServices((IMarkupServicesRaw)this.destinationDocument); this.destinationRange = destinationRange.Clone(); this.destinationRange.Start.Gravity = _POINTER_GRAVITY.POINTER_GRAVITY_Left; this.destinationRange.End.Gravity = _POINTER_GRAVITY.POINTER_GRAVITY_Right; }
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> /// Initialize word range for the specified markup-range within the document /// </summary> public MshtmlWordRange(IHTMLDocument document, bool useDocumentSelectionRange, MarkupRangeFilter filter, DamageFunction damageFunction) { MshtmlMarkupServices markupServices = new MshtmlMarkupServices((IMarkupServicesRaw)document); IHTMLDocument2 document2 = (IHTMLDocument2)document; MarkupRange markupRange; if (useDocumentSelectionRange) { markupRange = markupServices.CreateMarkupRange(document2.selection); } else { // TODO: Although this works fine, it would be better to only spellcheck inside editable regions. markupRange = markupServices.CreateMarkupRange(document2.body, false); } Init(document, markupServices, markupRange, filter, damageFunction, useDocumentSelectionRange); }
public OleUndoUnit(MshtmlMarkupServices markupServices, MarkupRange selection) { _markupServices = markupServices; //serialize the current position of the markup pointers so that they can be restored if //the DOM gets rolled back into the same state via an undo/redo operation. if (selection != null && selection.Positioned) { IMarkupPointer2Raw pointer2StartRaw = selection.Start.PointerRaw as IMarkupPointer2Raw; IMarkupPointer2Raw pointer2EndRaw = selection.End.PointerRaw as IMarkupPointer2Raw; pointer2StartRaw.GetMarkupPosition(out _startPosition); pointer2EndRaw.GetMarkupPosition(out _endPosition); pointer2StartRaw.GetContainer(out _markupContainer); } _description = "OleUndoUnit" + Guid.NewGuid().ToString(); Undo = true; }
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 IHTMLElement WrapRangeInElement(MshtmlMarkupServices services, MarkupRange range, _ELEMENT_TAG_ID tagId) { return WrapRangeInElement(services, range, tagId, string.Empty); }
/// <summary> /// Initialize word range for the specified markup-range within the document /// </summary> public MshtmlWordRange(IHTMLDocument document, MarkupRange markupRange, MarkupRangeFilter filter, DamageFunction damageFunction) { MshtmlMarkupServices markupServices = new MshtmlMarkupServices((IMarkupServicesRaw)document); Init(document, markupServices, markupRange, filter, damageFunction, true); }
public static IHTMLElement WrapRangeInElement(MshtmlMarkupServices services, MarkupRange range, _ELEMENT_TAG_ID tagId, string attributes) { IHTMLElement newElement = services.CreateElement(tagId, attributes); services.InsertElement(newElement, range.Start, range.End); return newElement; }
internal MarkupPointer(MshtmlMarkupServices markupServices, IMarkupPointerRaw pointer) { MarkupServices = markupServices; _pointerRaw = pointer; }
protected ContentSelection(IHtmlEditorComponentContext editorComponentContext, IHTMLElement element, SmartContentState contentState) { _editorComponentContext = editorComponentContext; _markupServices = editorComponentContext.MarkupServices; _element = element; _contentState = contentState; _markupRange = _markupServices.CreateMarkupRange(_element, true); _markupRange.Start.Gravity = _POINTER_GRAVITY.POINTER_GRAVITY_Right; _markupRange.End.Gravity = _POINTER_GRAVITY.POINTER_GRAVITY_Left; _markupRange.Start.Cling = false; _markupRange.End.Cling = false; }
public HtmlEditorSelection(MshtmlEditor editor, IHTMLDocument2 document) { _document = document; _editor = editor; MarkupServices = _editor.MshtmlControl.MarkupServices; }
/// <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> /// 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); } } } }
internal MarkupContainer(MshtmlMarkupServices markupServices, IMarkupContainerRaw container) { MarkupServices = markupServices; Container = container; }
/// <summary> /// Initialize with begin and end pointers /// </summary> /// <param name="start">start</param> /// <param name="end">end</param> /// <param name="markupServices"></param> internal MarkupRange(MarkupPointer start, MarkupPointer end, MshtmlMarkupServices markupServices) { Start = start; End = end; MarkupServices = markupServices; }
public SelectionUndoUnit(HtmlEditorControl editor, MarkupRange selection) { _editor = editor; _selection = selection; _markupServices = _editor.MshtmlEditor.MshtmlControl.MarkupServices; undoUnit = new SelectionOleUndoUnit(_markupServices, _selection); _editor.UndoManager.Add(undoUnit); }
private void RemoveParentAnchorFromTitle(IHTMLElement titleElement, MshtmlMarkupServices markupServices) { try { // Look for a parent <A> anchor tag MarkupPointer startPointer = markupServices.CreateMarkupPointer(titleElement, _ELEMENT_ADJACENCY.ELEM_ADJ_AfterBegin); IHTMLElement parentAnchor = startPointer.GetParentElement(ElementFilters.ANCHOR_ELEMENTS); if (parentAnchor != null) { // To make sure the title is readable, we will replace the anchor tag with a new span tag // that has all of the anchor tag properties we believe need to be propogated. This will // keep the final render as close to the original as possible. // Get the next parent block element to compare against the anchor tag IHTMLElement parentBlock = startPointer.GetParentElement(ElementFilters.BLOCK_OR_TABLE_CELL_ELEMENTS); // If no block element was found we will compare against the body if (parentBlock == null) parentBlock = startPointer.GetParentElement(ElementFilters.BODY_ELEMENT); Debug.Assert(parentBlock != null, "parentBlock was unexpectedly null!"); IHTMLElement newAnchor = markupServices.CreateElement(_ELEMENT_TAG_ID.TAGID_SPAN, string.Empty); IHTMLElement2 newAnchor2 = (IHTMLElement2)newAnchor; IHTMLElement2 parentAnchor2 = (IHTMLElement2)parentAnchor; IHTMLElement2 parentBlock2 = (IHTMLElement2)parentBlock; // Only insert the size if it was redefined from the anchor's parent. That way // relative sizes don't layer on each other. if (!(parentAnchor2.currentStyle.fontSize.Equals(parentBlock2.currentStyle.fontSize))) newAnchor2.runtimeStyle.fontSize = parentAnchor2.currentStyle.fontSize; // Copy all other attributes CopyAnchorAttributes(parentAnchor2, newAnchor2); markupServices.ReplaceElement(parentAnchor, newAnchor); } } catch (Exception ex) { // Any failure is ignorable, we will just continue with the parent anchor tag Debug.WriteLine("Failed to remove parent anchor tag from title, " + ex); } }
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 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); }
/// <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 { string baseUrl = UrlHelper.GetBasePathUrl(DataMeister.HTMLData.SourceURL); string html = DataMeister.HTMLData.HTMLSelection; //Check to see if the selection has an incomplete unordered list var finder = new IncompleteListFinder(html); finder.Parse(); if ((!EditorContext.CleanHtmlOnPaste) || finder.HasIncompleteList) { using (IUndoUnit undoUnit = EditorContext.CreateInvisibleUndoUnit()) { // Create a new MarkupContainer off of EditorContext's document that contains the source HTML // with comments marking the start and end selection. MarkupContainer sourceContainer = EditorContext.MarkupServices.ParseString(DataMeister.HTMLData.HTMLWithMarkers); // MSHTML's ParseString implementation clears all the attributes on the <body> element, so we // have to manually add them back in. CopyBodyAttributes(DataMeister.HTMLData.HTMLWithMarkers, sourceContainer.Document.body); MarkupRange sourceRange = FindMarkedFragment(sourceContainer.Document, HTMLDataObject.START_FRAGMENT_MARKER, HTMLDataObject.END_FRAGMENT_MARKER); MshtmlMarkupServices sourceContainerMarkupServices = new MshtmlMarkupServices((IMarkupServicesRaw)sourceContainer.Document); // Some applications may not add the correct fragment markers (e.g. copying from Fiddler from // the Web Sessions view). We'll just select the entire <body> of the clipboard in this case. if (sourceRange == null) { sourceRange = sourceContainerMarkupServices.CreateMarkupRange(sourceContainer.Document.body, false); } else { // Make sure that we don't try to copy just parts of a table/list. We need to include the // parent table/list. if (!EditorContext.CleanHtmlOnPaste) { ExpandToIncludeTables(sourceRange, sourceContainerMarkupServices); } ExpandToIncludeLists(sourceRange, sourceContainerMarkupServices); } if (sourceRange != null) { if (!EditorContext.CleanHtmlOnPaste) { // WinLive 273280: Alignment on a table acts like a float, which can throw off the layout of the rest of // the document. If there is nothing before or after the table, then we can safely remove the alignment. RemoveAlignmentIfSingleTable(sourceRange); // Serialize the source HTML to a string while keeping the source formatting. MarkupRange destinationRange = EditorContext.MarkupServices.CreateMarkupRange(begin.Clone(), end.Clone()); html = KeepSourceFormatting(sourceRange, destinationRange); } else { html = sourceRange.HtmlText; } } undoUnit.Commit(); } Trace.Assert(html != null, "Inline source CSS failed!"); } if (html == null) { html = DataMeister.HTMLData.HTMLSelection; } if (IsPasteFromSharedCanvas(DataMeister)) { if (action == DataAction.Copy) { // WinLive 96840 - Copying and pasting images within shared canvas should persist source // decorator settings. "wlCopySrcUrl" is inserted while copy/pasting within canvas. html = EditorContext.FixImageReferences(ImageCopyFixupHelper.FixupSourceUrlForCopy(html), DataMeister.HTMLData.SourceURL); } } else { html = EditorContext.FixImageReferences(html, DataMeister.HTMLData.SourceURL); HtmlCleanupRule cleanupRule = HtmlCleanupRule.Normal; if (IsOfficeHtml(DataMeister.HTMLData)) cleanupRule = HtmlCleanupRule.PreserveTables; // In Mail, we want to preserve the style of the html that is on the clipboard // Whereas in Writer we by default want to remove formatting so it looks like your blog theme if (EditorContext.CleanHtmlOnPaste) { // optionally cleanup the html html = EditorContext.HtmlGenerationService.CleanupHtml(html, baseUrl, cleanupRule); } else { html = HtmlCleaner.StripNamespacedTagsAndCommentsAndMarkupDirectives(html); } // standard fixups html = EditorContext.HtmlGenerationService.GenerateHtmlFromHtmlFragment(html, baseUrl); } // insert the content if (EditorContext.MarshalHtmlSupported) EditorContext.InsertHtml(begin, end, html, DataMeister.HTMLData.SourceURL); else if (EditorContext.MarshalTextSupported) { // This is called only in the case that we're attempting to marshal HTML, but only // text is supported. In this case, we should down convert to text and provide that. html = HTMLDocumentHelper.HTMLToPlainText(html); EditorContext.InsertHtml(begin, end, html, DataMeister.HTMLData.SourceURL); } else Debug.Assert(false, "Html being inserted when text or html isn't supported."); // Now select what was just inserted EditorContext.MarkupServices.CreateMarkupRange(begin, end).ToTextRange().select(); //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; } } }
public BoldApplier(MshtmlMarkupServices markupServices, MarkupRange markupRange, IMshtmlCommand boldCommand) { this.markupServices = markupServices; this.markupRange = markupRange.Clone(); this.boldCommand = boldCommand; }
/// <summary> /// Searches through the provided document for a start and end comment marker and then returns the fragment as /// a MarkupRange. /// </summary> /// <param name="document">The document to search.</param> /// <param name="startMarker">The comment text that marks the start of the fragment /// (e.g. <!--StartFragment--> ).</param> /// <param name="endMarker">The comment text that marks the end of the fragment /// (e.g. <!--EndFragment--> ).</param> /// <returns>The fragment as a MarkupRange or null if no valid fragment was found.</returns> private MarkupRange FindMarkedFragment(IHTMLDocument2 document, string startMarker, string endMarker) { MarkupPointer startFragment = null; MarkupPointer endFragment = null; MshtmlMarkupServices markupServices = new MshtmlMarkupServices((IMarkupServicesRaw)document); // Look for the markers in the document. foreach (IHTMLElement element in document.all) { if (element is IHTMLCommentElement && ((IHTMLCommentElement)element).text == startMarker) { startFragment = markupServices.CreateMarkupPointer(element, _ELEMENT_ADJACENCY.ELEM_ADJ_AfterEnd); } else if (element is IHTMLCommentElement && ((IHTMLCommentElement)element).text == endMarker) { endFragment = markupServices.CreateMarkupPointer(element, _ELEMENT_ADJACENCY.ELEM_ADJ_BeforeBegin); } } if (startFragment == null || endFragment == null || !startFragment.Positioned || !endFragment.Positioned || startFragment.IsRightOf(endFragment)) { Trace.WriteLine("Unable to find fragment or invalid fragment!"); return null; } // WinLive 251786: IE (and most other browsers) allow HTML like the following: // <p>This is a paragraph[cursor] // <p>This is a paragraph // However, when we use MarkupPointers to walk through this HTML, IE pretends there is a </p> at the end // of each of the above lines. This can cause issues when we copy part of this HTML somewhere else (e.g // everything after the [cursor]) and attempt to walk through both copies (e.g. during paste with keep // source formatting) at the same time. This holds true for some other elements, such as <li>s and <td>s. MarkupContext startContext = startFragment.Right(false); if (startFragment.IsLeftOf(endFragment) && startContext.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_ExitScope && startContext.Element != null && ElementFilters.IsEndTagOptional(startContext.Element) && !Regex.IsMatch(startContext.Element.outerHTML, String.Format(CultureInfo.InvariantCulture, @"</{0}(\s[^>]*)?>\s*$", startContext.Element.tagName), RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)) { startFragment.Right(true); } return markupServices.CreateMarkupRange(startFragment, endFragment); }
public SelectionOleUndoUnit(MshtmlMarkupServices markupServices, MarkupRange selection) : base(markupServices, selection) { }
public MarkupServicesWordHelper(MshtmlMarkupServices markupServices) { MarkupServices = markupServices; _p = MarkupServices.CreateMarkupPointer(); _p2 = MarkupServices.CreateMarkupPointer(); }
/// <summary> /// Takes the source HTML and makes necessary modifications to keep the source formatting as if it were to be /// pasted into the destination range. /// </summary> /// <param name="sourceRange">The range containing the HTML that is being copied.</param> /// <param name="destinationRange">The range that the source HTML will be copied to.</param> /// <returns>A serialized string of the source HTML with necessary modifications to keep the source formatting /// or null if unsuccessful.</returns> private string KeepSourceFormatting(MarkupRange sourceRange, MarkupRange destinationRange) { Debug.Assert(sourceRange.Start.Container.GetOwningDoc() == destinationRange.Start.Container.GetOwningDoc(), "Ranges must share an owning document!"); // We will temporarily add comments to the destination document to mark the destinationRange. IHTMLElement startComment = null; IHTMLElement endComment = null; try { // This is our true destination document. IHTMLDocument2 destinationDocument = destinationRange.Start.Container.Document; MshtmlMarkupServices destinationMarkupServices = new MshtmlMarkupServices((IMarkupServicesRaw)destinationDocument); // However, we'll use a temp destination because we don't want to paste anything into the real // document yet as it could fail, it would fire events, images would start loading, etc. MarkupContainer temporaryDestinationContainer = destinationMarkupServices.CreateMarkupContainer(); MarkupPointer temporaryDestinationPointer = destinationMarkupServices.CreateMarkupPointer(); temporaryDestinationPointer.MoveToContainer(temporaryDestinationContainer, true); // We add in comments to the destination document so that when we copy this range over to the fake // destination we'll be able to find the range again. destinationRange.Start.Gravity = _POINTER_GRAVITY.POINTER_GRAVITY_Left; destinationRange.End.Gravity = _POINTER_GRAVITY.POINTER_GRAVITY_Right; string startMarker = string.Format(CultureInfo.InvariantCulture, "<!--{0}-->", Guid.NewGuid()); destinationMarkupServices.InsertHtml(startMarker, destinationRange.Start); startComment = destinationRange.Start.Right(false).Element; string endMarker = string.Format(CultureInfo.InvariantCulture, "<!--{0}-->", Guid.NewGuid()); destinationMarkupServices.InsertHtml(endMarker, destinationRange.End); endComment = destinationRange.End.Left(false).Element; try { // Copy over the entire destination document into the fake destination document. MarkupRange destinationAll = SelectAll(destinationDocument); destinationMarkupServices.Copy(destinationAll.Start, destinationAll.End, temporaryDestinationPointer); // Find the original destination range in this copy. MarkupRange temporaryDestinationRange = FindMarkedFragment(temporaryDestinationContainer.Document, startMarker, endMarker); if (temporaryDestinationRange != null) { // Do the work to keep the source formatting. MarkupRange inlinedRange = new KeepSourceFormatting(sourceRange, temporaryDestinationRange).Execute(); if (inlinedRange != null) { return inlinedRange.HtmlText; } } } finally { // WinLive 249077: Clear the temporary destination container, otherwise behaviors may // inadvertently attach to elements in the MarkupContainer. temporaryDestinationContainer.Document.body.innerHTML = String.Empty; } } catch (Exception e) { // I really dont want some funky html on the clipboard that causes a problem with this code // to prevent a paste from going through. Trace.Fail("Failed to get inline css for selection: " + e); } finally { Debug.Assert(startComment is IHTMLCommentElement, "Didn't find start comment or it wasn't created."); if (startComment is IHTMLCommentElement) { HTMLElementHelper.RemoveElement(startComment); } Debug.Assert(endComment is IHTMLCommentElement, "Didn't find end comment or it wasn't created."); if (endComment is IHTMLCommentElement) { HTMLElementHelper.RemoveElement(endComment); } } return null; }
/// <summary> /// Creates a MarkupRange that contains the entire provided document. /// </summary> /// <param name="document">The document to select.</param> /// <returns>A MarkupRange that contains the entire document.</returns> private MarkupRange SelectAll(IHTMLDocument2 document) { MshtmlMarkupServices markupServices = new MshtmlMarkupServices((IMarkupServicesRaw)document); MarkupRange entireDocument = markupServices.CreateMarkupRange(((IHTMLDocument3)document).documentElement, true); // Make sure the doctype and anything else outside the root element is selected too. MarkupContext context = entireDocument.Start.Left(true); while (context.Context != _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_None) { context = entireDocument.Start.Left(true); } context = entireDocument.End.Right(true); while (context.Context != _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_None) { context = entireDocument.End.Right(true); } return entireDocument; }