コード例 #1
0
        private static void MoveUnitBounded(MarkupPointer p, MoveDirection direction, MoveContextFilter continueFilter, MarkupPointer boundary)
        {
            MarkupPointer    p1 = p.Clone();
            MarkupPointer    lastGoodPosition = p.Clone();
            MarkupContext    context          = new MarkupContext();
            MoveFilterResult result           = MoveFilterResult.CONTINUE;

            while (CheckMoveBoundary(p1, boundary, direction) && result == MoveFilterResult.CONTINUE)
            {
                lastGoodPosition.MoveToPointer(p1);
                MovePointer(p1, direction, context);
                result = continueFilter(context);
            }
            if (result == MoveFilterResult.CONTINUE)
            {
                //we hit the boundary, so position pointer at the boundary
                p1.MoveToPointer(boundary);
            }
            else if (result == MoveFilterResult.STOP_BACK)
            {
                p1.MoveToPointer(lastGoodPosition);
            }

            p.MoveToPointer(p1);
        }
コード例 #2
0
        /// <summary>
        /// Creates an instance of the IMarkupPointer object with an initial position
        /// at the same location as another pointer.
        /// </summary>
        /// <param name="initialPosition"></param>
        /// <returns></returns>
        public MarkupPointer CreateMarkupPointer(MarkupPointer initialPosition)
        {
            MarkupPointer pointer = CreateMarkupPointer();

            pointer.MoveToPointer(initialPosition);
            return(pointer);
        }
コード例 #3
0
        /// <summary>
        /// Walk through the markup range in reverse, letting the walker visit each position.
        /// </summary>
        /// <param name="walker">the delegate walking navigating the the markup range</param>
        /// <param name="inScopeElementsOnly">if true, enter/exit notifications about out-of-scope elements will be suppressed.</param>
        /// <returns></returns>
        public void WalkRangeReverse(MarkupRangeWalker walker, bool inScopeContextsOnly)
        {
            MarkupPointer p1 = MarkupServices.CreateMarkupPointer(End);
            MarkupPointer p2 = MarkupServices.CreateMarkupPointer(End);

            p1.Cling = false;
            p2.Cling = false;
            MarkupContext context         = new MarkupContext();
            bool          continueWalking = true;
            MarkupRange   currentRange    = null;

            while (continueWalking && p2.IsRightOf(Start))
            {
                string text      = null;
                bool   isInScope = true;

                p2.Left(true, context);
                currentRange = new MarkupRange(p2.Clone(), p1.Clone(), MarkupServices);

                if (inScopeContextsOnly)
                {
                    if (context.Element != null)
                    {
                        if (context.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_EnterScope)
                        {
                            p1.MoveAdjacentToElement(context.Element, _ELEMENT_ADJACENCY.ELEM_ADJ_AfterEnd);
                            isInScope = InRange(p1);
                        }
                        else if (context.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_ExitScope)
                        {
                            p1.MoveAdjacentToElement(context.Element, _ELEMENT_ADJACENCY.ELEM_ADJ_BeforeBegin);
                            isInScope = InRange(p1);
                        }
                    }
                    else if (context.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_Text)
                    {
                        // It's possible part of the text is out of scope, so only return the in-scope text.
                        if (currentRange.Start.IsLeftOf(Start))
                        {
                            currentRange.Start.MoveToPointer(Start);
                        }
                    }
                }

                if (context.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_Text)
                {
                    text = currentRange.Text;
                }

                if (!inScopeContextsOnly || isInScope)
                {
                    continueWalking = walker(currentRange, context, text);
                }

                p1.MoveToPointer(p2);
            }
        }
コード例 #4
0
        public void ExpandToInclude(MarkupRange range)
        {
            if (range == null)
            {
                return;
            }

            if (Positioned)
            {
                if (range.Start.IsLeftOf(Start))
                {
                    Start.MoveToPointer(range.Start);
                }

                if (range.End.IsRightOf(End))
                {
                    End.MoveToPointer(range.End);
                }
            }
            else
            {
                MoveToRange(range);
            }
        }
コード例 #5
0
 public void MoveToWordEnd(MarkupPointer p)
 {
     lock (_p)
     {
         _p.MoveToPointer(p);
         _p2.MoveToPointer(p);
         _p.MoveUnit(_MOVEUNIT_ACTION.MOVEUNIT_NEXTWORDBEGIN);
         _p2.MoveUnit(_MOVEUNIT_ACTION.MOVEUNIT_NEXTWORDEND);
         // If CurrentScope is null, this means we have walked off the end of the
         // document, in that case we don't want to move the pointer, at is already
         // at the end of word.
         if (_p2.IsLeftOfOrEqualTo(_p) && _p.CurrentScope != null)
             p.MoveToPointer(_p2);
         //else, the pointer is already at the end of the current word
     }
 }
コード例 #6
0
 public void MoveToWordStart(MarkupPointer p)
 {
     lock (_p)
     {
         _p.MoveToPointer(p);
         _p2.MoveToPointer(p);
         _p.MoveUnit(_MOVEUNIT_ACTION.MOVEUNIT_PREVWORDEND);
         _p2.MoveUnit(_MOVEUNIT_ACTION.MOVEUNIT_PREVWORDBEGIN);
         if (_p2.IsRightOfOrEqualTo(_p))
             p.MoveToPointer(_p2);
         //else, the pointer is already at the start of the current word
     }
 }
コード例 #7
0
        private bool OverwriteDestinationBlockIfEmpty(MarkupPointer destinationStart, MarkupRange bounds)
        {
            bool blockOverwritten = false;
            IHTMLElement parentBlockElement = destinationStart.GetParentElement(ElementFilters.BLOCK_ELEMENTS);
            if (parentBlockElement != null)
            {
                MarkupRange parentBlockRange = MarkupServices.CreateMarkupRange(parentBlockElement, false);
                if (bounds.InRange(parentBlockRange, false))
                {
                    if (PrimaryEditableBounds == null || PrimaryEditableBounds.InRange(parentBlockRange))
                    {
                        if (parentBlockRange.IsEmptyOfContent())
                        {
                            parentBlockRange.MoveToElement(parentBlockElement, true);
                            DeleteContentNoCling(parentBlockRange.Start, parentBlockRange.End);
                            // Check to see if the delete we just did caused the insertion point to be
                            // to become a no longer positioned, and if it did we move it to the start
                            // of what we deleted
                            if (!destinationStart.Positioned)
                            {
                                //Debug.WriteLine("Invalid pointer after delete, moving the target pointer to the start of the deleted markup.");
                                destinationStart.MoveToPointer(parentBlockRange.Start);
                            }

                            blockOverwritten = true;
                        }
                    }
                }
            }
            return blockOverwritten;
        }
コード例 #8
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();

            }

        }
コード例 #9
0
        /// <summary>
        /// Safely removes the content within this range without leaving the document badly formed.
        /// </summary>
        public void RemoveContent()
        {
            //delete the selection by moving a delete range right (from the start).
            //Each time that a tag that does not entirely exist within this selection
            //is encountered, the range content will be deleted, the deleteRange will
            //skip over the element.
            MarkupRange deleteRange = this.Clone();

            Trace.Assert(deleteRange.Start.Positioned, "Trying to remove content from selection that contains pointers that are not positioned.");

            deleteRange.End.MoveToPointer(deleteRange.Start);
            MarkupPointer p = MarkupServices.CreateMarkupPointer();
            MarkupPointer previousPosition = MarkupServices.CreateMarkupPointer(deleteRange.End);
            MarkupContext context          = new MarkupContext();

            deleteRange.End.Right(true, context);
            while (deleteRange.End.IsLeftOf(End))
            {
                if (context.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_EnterScope)
                {
                    p.MoveAdjacentToElement(context.Element, _ELEMENT_ADJACENCY.ELEM_ADJ_AfterEnd);
                    if (p.IsRightOf(End))
                    {
                        //this element does not exist entirely in this selection, so we need to
                        //ignore it in the delete.

                        //save this position so that the delete range can be repositioned here
                        p.MoveToPointer(deleteRange.End);

                        //move the end left since we overstepped the valid delete range
                        deleteRange.End.MoveToPointer(previousPosition);

                        //delete the content in the deleteRange, and move it back to this position
                        deleteRangeContentAndMoveToPosition(deleteRange, p);
                    }
                    else
                    {
                        //this element exists entirely in this selection, so skip to its end (since
                        //we know it can be deleted)
                        deleteRange.End.MoveToPointer(p);
                    }
                }
                else if (context.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_ExitScope)
                {
                    p.MoveAdjacentToElement(context.Element, _ELEMENT_ADJACENCY.ELEM_ADJ_BeforeBegin);
                    if (p.IsLeftOf(Start))
                    {
                        //this element does not exist entirely in this selection, so we need to
                        //ignore it in the delete.

                        //save this position so that the delete range can be repositioned here
                        p.MoveToPointer(deleteRange.End);

                        //move the end left since we overstepped the valid delete range
                        deleteRange.End.MoveToPointer(previousPosition);

                        //delete the content in the deleteRange, and move it back to this position
                        deleteRangeContentAndMoveToPosition(deleteRange, p);
                    }
                    else
                    {
                        //this element exists entirely in this selection, so skip to its end (since
                        //we know it can be deleted)
                        deleteRange.End.MoveToPointer(p);
                    }
                }

                previousPosition.MoveToPointer(deleteRange.End);
                deleteRange.End.Right(true, context);
            }

            //delete the last part of the range
            deleteRange.End.MoveToPointer(End);
            if (!deleteRange.Start.Equals(deleteRange.End))
            {
                MarkupServices.Remove(deleteRange.Start, deleteRange.End);
            }
        }
コード例 #10
0
        private static void MoveUnitBounded(MarkupPointer p, MoveDirection direction, MoveContextFilter continueFilter, MarkupPointer boundary)
        {
            MarkupPointer p1 = p.Clone();
            MarkupPointer lastGoodPosition = p.Clone();
            MarkupContext context = new MarkupContext();
            MoveFilterResult result = MoveFilterResult.CONTINUE;
            while (CheckMoveBoundary(p1, boundary, direction) && result == MoveFilterResult.CONTINUE)
            {
                lastGoodPosition.MoveToPointer(p1);
                MovePointer(p1, direction, context);
                result = continueFilter(context);
            }
            if (result == MoveFilterResult.CONTINUE)
            {
                //we hit the boundary, so position pointer at the boundary
                p1.MoveToPointer(boundary);
            }
            else if (result == MoveFilterResult.STOP_BACK)
            {
                p1.MoveToPointer(lastGoodPosition);
            }

            p.MoveToPointer(p1);
        }