Пример #1
0
        public void InsertPlainText(MarkupPointer start, MarkupPointer end, string text)
        {
            IUndoUnit undo = CreateUndoUnit();
            using (undo)
            {
                if (!start.IsEqualTo(end))
                {
                    DeleteContentNoCling(start, end);
                }

                if (start.CurrentScope.tagName == "PRE")
                {
                    //if pasting into a preblock, then we want to preserve the whitespace in
                    //the text, and we don't want to convert line breaks into <BR>.  MSHTML
                    //is really nasty about tossing out whitespace, but will keep its hands
                    //off the text as long as it has <pre> tags around it

                    //hack MSHTML's whitespace mangling by the text wrapping in a <pre> tag
                    //for insertion, and then yank it.
                    text = "<pre>" + HttpUtility.HtmlEncode(text) + "</pre>";
                    MarkupRange range = MarkupServices.CreateMarkupRange();
                    MarkupContainer c = MarkupServices.ParseString(text, range.Start, range.End);
                    range.MoveToElement((IHTMLElement)(c.Document.body as IHTMLDOMNode).firstChild, false);
                    MarkupServices.Move(range.Start, range.End, start);
                }
                else
                {
                    //if this insn't wrapped in a <pre> tag, then use a textRange to insert the
                    //text so that it will be padded with <BR> and &nbsp.
                    MarkupRange range = MarkupServices.CreateMarkupRange(start, end);
                    IHTMLTxtRange txtRange = range.ToTextRange();
                    txtRange.text = text;
                }

                undo.Commit();
            }
        }
Пример #2
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();

            }

        }