Пример #1
0
        /// <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>
        /// 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;
        }
Пример #3
0
        protected virtual void InsertHtml(MarkupPointer start, MarkupPointer end, string html, string sourceUrl, bool allowBlockBreakout)
        {
            MarkupRange range = MarkupServices.CreateMarkupRange(start, end);
            if (!IsValidContentInsertionPoint(range))
            {
                DisplayMessage.Show(MessageId.InvalidInsertionPoint);
                return;
            }

            Trace.Assert(start.Positioned && end.Positioned, string.Format(CultureInfo.InvariantCulture, "Invalid pointer being used for insert. start:({0}),end:({1})", start.Positioned, end.Positioned));

            // begin undo unit
            IUndoUnit undoUnit = CreateUndoUnit();

            start.PushCling(true);
            end.PushCling(true);

            using (undoUnit)
            {
                // Any changes to the way we remove the content in the destination may need to be changed in
                // KeepSourceFormatting.PasteSourceOverDestination as well!
                MarkupPointerMoveHelper.PerformImageBreakout(start);
                MarkupPointerMoveHelper.PerformImageBreakout(end);

                //if the start and endpoints are not equal, then we need to paste over the selection
                //so delete the selected region (which will collapse the pointers to now be equal.
                if (!start.IsEqualTo(end))
                {
                    //delete the selected content
                    if (ContentIsDeletableForInsert(start, end))
                    {
                        // CT: There is currently a case where we leave empty blocks behind
                        // see bug 628054. This happens when the start and end markup pointers don't completely
                        // contain the selected blocks, like: <p>|line1</p><p>line2|</p>. In this case, calling
                        // deleteNoContentNoClient will leave you with <p>|</p><p>|</p>. The next line collapses
                        // the end pointer back to the start point since that is where selection started.
                        DeleteContentNoCling(start, end);
                        end.MoveToPointer(start);
                    }
                }

                if (!string.IsNullOrEmpty(html))
                {
                    //Note: we use MarkupServices to insert the content so that IE doesn't try to fix up URLs.
                    //Element.insertAdjacentHTML() is a no-no because it rewrites relaive URLs to include
                    //the fullpath from the local filesytem.

                    //MarkupServices.ParseString() doesn't attempt to fix up URLs, so its safe to use.
                    //We will now stage the new content into a MarkupContainer, and then move it into
                    //the working document.
                    MarkupPointer sc1 = MarkupServices.CreateMarkupPointer();
                    MarkupPointer sc2 = MarkupServices.CreateMarkupPointer();

                    // Do the work ahead of time to get an <p></P> ready to be inserted
                    // doing this work after the insert this html was called with sometimes
                    // causes mshtml to not paint things until they are moused over(embeds)
                    // BUG: 624122, 622715
                    MarkupPointer mpStart = MarkupServices.CreateMarkupPointer();
                    MarkupPointer mpEnd = MarkupServices.CreateMarkupPointer();
                    // Make a temp document and load our ending html into it.
                    MarkupServices.ParseString(CONTENT_BODY_PADDING, mpStart, mpEnd);

                    //Create a temporary document from the html and set the start/end pointers to the
                    //start and end of the document.

                    MarkupServices.ParseString(html, sc1, sc2);

                    IHTMLDocument2 doc = sc1.GetDocument();
                    MarkupRange stagingRange = MarkupServices.CreateMarkupRange(sc1, sc2);
                    stagingRange.MoveToElement(doc.body, false);

                    // We only need to insert the ending new line if there was a div or image added
                    bool allowNewLineInsert = ShouldAllowNewLineInsert(html);

                    Trace.Assert(stagingRange.Positioned && stagingRange.Start.Positioned && stagingRange.End.Positioned && sc1.Positioned && sc2.Positioned, String.Format(CultureInfo.InvariantCulture, "Staging document is not ready. stagingRange:({0}),stagingRange.Start:({1}),stagingRange.End:({2}),sc1:({3}),sc2:({4})", stagingRange.Positioned, stagingRange.Start.Positioned, stagingRange.End.Positioned, sc1.Positioned, sc2.Positioned));

                    try
                    {
                        // Any changes to the way we remove the content in the destination may need to be changed in
                        // KeepSourceFormatting.PasteSourceOverDestination as well!
                        bool emptyBlockRemoved;
                        if (stagingRange.ContainsElements(ElementFilters.IsBlockOrTableElement))
                        {
                            // if the destination is an empty block element then just overwrite it
                            emptyBlockRemoved = OverwriteDestinationBlockIfEmpty(start, PrimaryEditableBounds);
                            if (!emptyBlockRemoved && allowBlockBreakout)
                            {
                                // otherwise split the destination block or move outside of the block
                                MarkupHelpers.SplitBlockForInsertionOrBreakout(MarkupServices, PrimaryEditableBounds, start);
                            }
                            end.MoveToPointer(start);
                        }
                    }
                    catch (COMException ex)
                    {
                        Trace.WriteLine(String.Format(CultureInfo.InvariantCulture, "RemoveBlockOrTableElement Failed ({0},{1},{2},{4}): {3}", stagingRange.Start.Positioned, stagingRange.End.Positioned, end.Positioned, ex, start.Positioned));
                        throw;
                    }

                    InflateEmptyParagraphs(stagingRange);
                    FixUpStickyBrs(stagingRange);

                    if (HTMLDocumentHelper.IsQuirksMode(HTMLDocument))
                    {
                        ForceTablesToInheritFontColor(stagingRange);
                    }

                    Trace.Assert(stagingRange.Positioned && stagingRange.Start.Positioned && stagingRange.End.Positioned && sc1.Positioned && sc2.Positioned, String.Format(CultureInfo.InvariantCulture, "Staging document corrupt after RemoveBlockOrTableElement. stagingRange:({0}),stagingRange.Start:({1}),stagingRange.End:({2}),sc1:({3}),sc2:({4})", stagingRange.Positioned, stagingRange.Start.Positioned, stagingRange.End.Positioned, sc1.Positioned, sc2.Positioned));

                    IDisposable damageTracker = null;
                    try
                    {
                        damageTracker = CreateDamageTracking(end, true);
                    }
                    catch (COMException ex)
                    {
                        Trace.WriteLine(String.Format(CultureInfo.InvariantCulture, "CreateDamageTracking Failed ({0}): {1}", end.Positioned, ex));
                        throw;
                    }

                    Trace.Assert(stagingRange.Positioned && stagingRange.Start.Positioned && stagingRange.End.Positioned && sc1.Positioned && sc2.Positioned, String.Format(CultureInfo.InvariantCulture, "Staging document corrupt after CreateDamageTracking. stagingRange:({0}),stagingRange.Start:({1}),stagingRange.End:({2}),sc1:({3}),sc2:({4})", stagingRange.Positioned, stagingRange.Start.Positioned, stagingRange.End.Positioned, sc1.Positioned, sc2.Positioned));

                    using (damageTracker)
                    {

                        // CT: Because we don't set gravity, these pointers can end up in indeterminant positions.
                        // For example, when inserting HTML over a selection inside of a block, the start
                        // pointer can end up on the right side of the end pointer. Pushing gravity onto
                        // the pointers before we call this should provide consistent markup pointer behavior.
                        try
                        {
                            start.PushGravity(_POINTER_GRAVITY.POINTER_GRAVITY_Left);
                            end.PushGravity(_POINTER_GRAVITY.POINTER_GRAVITY_Right);

                            Trace.Assert(stagingRange.Positioned && stagingRange.Start.Positioned && stagingRange.End.Positioned && sc1.Positioned && sc2.Positioned, String.Format(CultureInfo.InvariantCulture, "Staging document corrupt after applying gravity. stagingRange:({0}),stagingRange.Start:({1}),stagingRange.End:({2}),sc1:({3}),sc2:({4})", stagingRange.Positioned, stagingRange.Start.Positioned, stagingRange.End.Positioned, sc1.Positioned, sc2.Positioned));

                            try
                            {
                                MarkupServices.Move(stagingRange.Start, stagingRange.End, end);
                            }
                            catch (COMException ex)
                            {
                                Trace.WriteLine(
                                    String.Format(CultureInfo.InvariantCulture, "MarkupServices.Move Failed ({0},{1},{2}): {3}",
                                                  stagingRange.Start.Positioned, stagingRange.End.Positioned,
                                                  end.Positioned, ex));
                                throw;
                            }
                        }
                        finally
                        {
                            end.PopGravity();
                            start.PopGravity();
                        }

                        if (allowNewLineInsert && TidyWhitespace)
                        {
                            try
                            {
                                EnsureNewLineAtDocEnd(mpStart, mpEnd);
                            }
                            catch (Exception ex)
                            {
                                Trace.WriteLine("Failed to insert new line at end of document: " + ex);
                            }

                        }

                    }
                }
                // note that we have completed our edit
                undoUnit.Commit();

                start.PopCling();
                end.PopCling();

            }

        }