예제 #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
        public static void MoveUnitBounded(MarkupPointer p, MoveDirection direction, MarkupPointerAdjacency stopRule, IHTMLElement boundary)
        {
            MarkupPointer pBoundary = p.Clone();

            pBoundary.MoveAdjacentToElement(boundary, direction == MoveDirection.LEFT ? _ELEMENT_ADJACENCY.ELEM_ADJ_AfterBegin : _ELEMENT_ADJACENCY.ELEM_ADJ_BeforeEnd);
            MoveUnitBounded(p, direction, stopRule, pBoundary);
        }
예제 #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 EnsureStartIsBeforeEnd()
 {
     if (Start.IsRightOf(End))
     {
         MarkupPointer temp = End.Clone();
         End   = Start.Clone();
         Start = temp;
     }
 }
        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);
        }
예제 #6
0
        private MarkupPointer GetFirstTextPoint(MarkupPointer from, bool forward)
        {
            MarkupPointer firstTextPoint = from.Clone();

            MarkupContext context     = new MarkupContext();
            bool          keepLooking = true;

            do
            {
                if (forward)
                {
                    firstTextPoint.Right(false, context);
                }
                else
                {
                    firstTextPoint.Left(false, context);
                }

                if (context.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_Text)
                {
                    break;
                }

                if (forward)
                {
                    firstTextPoint.Right(true, context);
                    keepLooking = context.Element != null && firstTextPoint.IsLeftOf(End);
                }
                else
                {
                    firstTextPoint.Left(true, context);
                    keepLooking = context.Element != null && firstTextPoint.IsRightOf(Start);
                }
            } while (keepLooking);

            return(firstTextPoint);
        }
        private IHTMLElement GetNextElement(MarkupPointer start, MarkupRange boundaries, IHTMLElementFilter filter, bool forward)
        {
            start = start.Clone();
            MarkupPointer boundary = forward ? boundaries.End : boundaries.Start;
            MarkupContext moveResult = new MarkupContext();
            _MARKUP_CONTEXT_TYPE skipContext = _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_ExitScope;

            //advance the pointer
            if (forward)
                start.Right(true, moveResult);
            else
                start.Left(true, moveResult);

            while (forward ? start.IsLeftOf(boundary) : start.IsRightOf(boundary))
            {
                if (moveResult.Element != null && moveResult.Context != skipContext && filter(moveResult.Element))
                {
                    return moveResult.Element;
                }
                //advance the pointer
                if (forward)
                    start.Right(true, moveResult);
                else
                    start.Left(true, moveResult);
            }
            return null;
        }
        /// <summary>
        /// Returns the bounds of line that the pointer is positioned within in client-based coordinates.
        /// </summary>
        /// <param name="pointer"></param>
        /// <returns></returns>
        protected Rectangle GetLineClientRectangle(MarkupPointer pointer)
        {
            //getting the line associated with a pointer is a little complicated because the
            //ILineInfo for the pointer position only returns information based on the font
            //exactly at that position.  It does not take the max font height of the line into
            //account, so we need to that manually.  To do this, we get the LineInfo at each
            //point in the line where the line height may change by moving a markup pointer
            //in to each element declared on the line.

            IDisplayServicesRaw displayServices = (IDisplayServicesRaw)HTMLElement.document;

            //position a display pointer on the same line as the markup pointer
            IDisplayPointerRaw displayPointer;
            displayServices.CreateDisplayPointer(out displayPointer);
            DisplayServices.TraceMoveToMarkupPointer(displayPointer, pointer);

            //position a markup pointer at the end of the line
            MarkupPointer pLineEnd = pointer.Clone();
            displayPointer.MoveUnit(_DISPLAY_MOVEUNIT.DISPLAY_MOVEUNIT_CurrentLineEnd, 0);
            displayPointer.PositionMarkupPointer(pLineEnd.PointerRaw);

            //position a markup pointer at the start of the line
            MarkupPointer pLineStart = pointer.Clone();
            displayPointer.MoveUnit(_DISPLAY_MOVEUNIT.DISPLAY_MOVEUNIT_CurrentLineStart, 0);
            displayPointer.PositionMarkupPointer(pLineStart.PointerRaw);

            //calculate the maximum rectangle taken up by any text on this line by walking
            //the lineStart pointer to the lineEnd pointer and calculating a max rectangle
            //at each step.
            Rectangle lineRect = GetLineRect(HTMLElement, displayPointer);
            pLineStart.Right(true);
            while (pLineStart.IsLeftOfOrEqualTo(pLineEnd))
            {
                Rectangle dpLineRect;
                try
                {
                    displayPointer.MoveToMarkupPointer(pLineStart.PointerRaw, null);
                    dpLineRect = GetLineRect(HTMLElement, displayPointer);
                }
                catch (COMException e)
                {
                    if (e.ErrorCode == IE_CTL_E.INVALIDLINE)
                    {
                        // http://msdn.microsoft.com/en-us/library/aa752674(VS.85).aspx
                        // IDisplayPointer::MoveToMarkupPointer will return an error (CTL_E_INVALIDLINE),
                        // if the markup pointer is in a line whose nearest layout element *is not a flow layout element*.
                        dpLineRect = GetLineRect(pLineStart.CurrentScope);

                        // We also want to skip past the entire current scope...
                        pLineStart.MoveAdjacentToElement(pLineStart.CurrentScope, _ELEMENT_ADJACENCY.ELEM_ADJ_BeforeEnd);
                    }
                    else
                    {
                        Trace.Fail("Exception thrown in GetLineClientRectangle: " + e.ToString());
                        throw;
                    }
                }

                lineRect.Y = Math.Min(dpLineRect.Y, lineRect.Y);
                if (lineRect.Bottom < dpLineRect.Bottom)
                {
                    lineRect.Height += dpLineRect.Bottom - lineRect.Bottom;
                }

                pLineStart.Right(true);
            }

            //return the line rectangle
            return lineRect;
        }
예제 #9
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;
                }
            }
        }
예제 #10
0
        private MarkupPointer GetFirstTextPoint(MarkupPointer from, bool forward)
        {
            MarkupPointer firstTextPoint = from.Clone();

            MarkupContext context = new MarkupContext();
            bool keepLooking = true;
            do
            {
                if (forward)
                    firstTextPoint.Right(false, context);
                else
                    firstTextPoint.Left(false, context);

                if (context.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_Text)
                    break;

                if (forward)
                {
                    firstTextPoint.Right(true, context);
                    keepLooking = context.Element != null && firstTextPoint.IsLeftOf(End);
                }
                else
                {
                    firstTextPoint.Left(true, context);
                    keepLooking = context.Element != null && firstTextPoint.IsRightOf(Start);
                }
            } while (keepLooking);

            return firstTextPoint;
        }
 public static void MoveUnitBounded(MarkupPointer p, MoveDirection direction, MarkupPointerAdjacency stopRule, IHTMLElement boundary)
 {
     MarkupPointer pBoundary = p.Clone();
     pBoundary.MoveAdjacentToElement(boundary, direction == MoveDirection.LEFT ? _ELEMENT_ADJACENCY.ELEM_ADJ_AfterBegin : _ELEMENT_ADJACENCY.ELEM_ADJ_BeforeEnd);
     MoveUnitBounded(p, direction, stopRule, pBoundary);
 }