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("&nbsp;") != -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 &nbsp; char to ensure that the
                        //whitespace that was visible in the editor is visible in the final document.
                        text = "&nbsp;";
                    }
                }

                //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;
        }
示例#9
0
        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);
        }
示例#11
0
        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;
 }
示例#19
0
        /// <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);
                    }
                }
            }
        }
示例#20
0
        /// <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);
                    }
                }
            }
        }
示例#21
0
 internal MarkupContainer(MshtmlMarkupServices markupServices, IMarkupContainerRaw container)
 {
     MarkupServices = markupServices;
     Container      = container;
 }
示例#22
0
 /// <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);
        }
示例#27
0
        /// <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;
                }
            }
        }
 /// <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;
 }
示例#29
0
 public BoldApplier(MshtmlMarkupServices markupServices, MarkupRange markupRange, IMshtmlCommand boldCommand)
 {
     this.markupServices = markupServices;
     this.markupRange = markupRange.Clone();
     this.boldCommand = boldCommand;
 }
示例#30
0
        /// <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. &lt;!--StartFragment--&gt; ).</param>
        /// <param name="endMarker">The comment text that marks the end of the fragment
        /// (e.g. &lt;!--EndFragment--&gt; ).</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();
 }
示例#33
0
        /// <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;
        }
示例#34
0
 internal MarkupPointer(MshtmlMarkupServices markupServices, IMarkupPointerRaw pointer)
 {
     MarkupServices = markupServices;
     _pointerRaw    = pointer;
 }
示例#35
0
        /// <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;
        }