Пример #1
0
        private bool IsValidInsertionPoint(IHTMLElement e, MarkupPointer p)
        {
            if (InlineEditField.IsEditField(p.CurrentScope))
            {
                return(true);
            }

            IHTMLElement contentEditableParent = null;
            IHTMLElement parent = e;

            while (parent != null)
            {
                if ((parent as IHTMLElement3).isContentEditable)
                {
                    contentEditableParent = parent;
                }
                else if (contentEditableParent != null)
                {
                    break; //we hit the top-most editable parent.
                }
                parent = parent.parentElement;
            }

            if (contentEditableParent != null)
            {
                MarkupRange range = EditorContext.MarkupServices.CreateMarkupRange(contentEditableParent, false);
                return(range.InRange(p));
            }
            else
            {
                return(false);
            }
        }
Пример #2
0
        /// <summary>
        /// Wraps a MarkupRange in an element (or multiple elements if necessary to produce valid HTML).
        /// </summary>
        /// <param name="elementFactory">Creates elements to wrap the markupRange in as needed.</param>
        /// <param name="markupServices">The MarkupServices for the markupRange.</param>
        /// <param name="markupRange">The range to wrap.</param>
        protected void WrapInElement(ElementFactory elementFactory, MshtmlMarkupServices markupServices, MarkupRange markupRange)
        {
            Debug.Assert(markupRange.GetElements(ElementFilters.BLOCK_ELEMENTS, false).Length == 0,
                         "Did not expect MarkupRange to contain block elements");

            MarkupPointer startPointer = markupRange.Start.Clone();
            MarkupPointer endPointer   = markupRange.Start.Clone();
            MarkupContext context;

            while (endPointer.IsLeftOf(markupRange.End))
            {
                context = endPointer.Right(false);

                if (context.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_EnterScope ||
                    context.Context == _MARKUP_CONTEXT_TYPE.CONTEXT_TYPE_ExitScope)
                {
                    if (!markupRange.InRange(context.Element))
                    {
                        // EnterScope example: <span>[markupRange.Start]Hello [endPointer]<i>Hello[markupRange.End]</i></span>
                        // ExitScope example: <span>[markupRange.Start]Hello [endPointer]</span><span>Hello[markupRange.End]</span>
                        InsertElement(elementFactory(), markupServices, startPointer, endPointer);
                        continue;
                    }
                }

                endPointer.Right(true);
            }

            InsertElement(elementFactory(), markupServices, startPointer, endPointer);
        }
Пример #3
0
        /// <summary>
        /// Fixes up all the headers in the entire markupRange.
        /// </summary>
        /// <param name="turnBold">Whether or not the text should be turning bold.</param>
        private void FixupHeaders(bool turnBold)
        {
            IHTMLElement elementStartHeader = markupRange.Start.GetParentElement(ElementFilters.HEADER_ELEMENTS);
            IHTMLElement elementEndHeader   = markupRange.End.GetParentElement(ElementFilters.HEADER_ELEMENTS);
            MarkupRange  currentRange       = markupRange.Clone();

            if (elementStartHeader != null)
            {
                // Takes care of the following cases:
                //  <h1>...|blah|...</h1>
                //  <h1>...|blah...</h1>...|...
                MarkupRange startRange = markupServices.CreateMarkupRange(elementStartHeader, false);
                startRange.Start.MoveToPointer(markupRange.Start);

                if (startRange.End.IsRightOf(markupRange.End))
                {
                    startRange.End.MoveToPointer(markupRange.End);
                }

                FixupHeaderRange(startRange, turnBold);

                currentRange.Start.MoveAdjacentToElement(elementStartHeader, _ELEMENT_ADJACENCY.ELEM_ADJ_AfterEnd);
                if (currentRange.End.IsLeftOf(currentRange.Start))
                {
                    currentRange.End.MoveToPointer(currentRange.Start);
                }
            }

            if (elementEndHeader != null && !HTMLElementHelper.ElementsAreEqual(elementStartHeader, elementEndHeader))
            {
                // Takes care of the following case:
                //  ...|...<h1>...blah|...</h1>
                MarkupRange endRange = markupServices.CreateMarkupRange(elementEndHeader, false);
                endRange.End.MoveToPointer(markupRange.End);

                FixupHeaderRange(endRange, turnBold);

                currentRange.End.MoveAdjacentToElement(elementEndHeader, _ELEMENT_ADJACENCY.ELEM_ADJ_BeforeBegin);
                if (currentRange.Start.IsRightOf(currentRange.End))
                {
                    currentRange.Start.MoveToPointer(currentRange.End);
                }
            }

            if (!markupRange.InRange(currentRange))
            {
                return;
            }

            IHTMLElement[] headerElements = currentRange.GetElements(ElementFilters.HEADER_ELEMENTS, true);
            if (headerElements != null && headerElements.Length > 0)
            {
                foreach (IHTMLElement element in headerElements)
                {
                    MarkupRange headerRange = markupServices.CreateMarkupRange(element, false);
                    FixupHeaderRange(headerRange, turnBold);
                }
            }
        }
Пример #4
0
        private void SplitBlockForApplyingBlockStyles(MarkupPointer splitPoint, MarkupRange maximumBounds)
        {
            //find the split stop parent
            IHTMLElement splitStop = splitPoint.GetParentElement(new IHTMLElementFilter(IsSplitStopElement));

            if (splitStop != null)
            {
                MarkupPointer stopLocation = _markupServices.CreateMarkupPointer(splitStop, _ELEMENT_ADJACENCY.ELEM_ADJ_AfterBegin);
                if (maximumBounds.InRange(stopLocation))
                {
                    stopLocation.MoveAdjacentToElement(splitStop, _ELEMENT_ADJACENCY.ELEM_ADJ_BeforeEnd);
                    if (maximumBounds.InRange(stopLocation))
                    {
                        maximumBounds = maximumBounds.Clone();
                        maximumBounds.MoveToElement(splitStop, false);
                    }
                }
            }

            MarkupHelpers.SplitBlockForInsertionOrBreakout(_markupServices, maximumBounds, splitPoint);
        }
Пример #5
0
        /// <summary>
        /// Returns true if the parent element was removed and false otherwise.
        /// </summary>
        private bool RemoveEmptyParentBlock(MarkupRange range, IHTMLElement parentBlock, MarkupRange maximumBounds)
        {
            if (parentBlock != null)
            {
                range.MoveToElement(parentBlock, false);
                if (maximumBounds.InRange(range) && range.IsEmptyOfContent())
                {
                    if (!IsSplitStopElement(parentBlock))
                    {
                        //delete the parent node (only if it doesn't fall outside the maxrange (bug 465995))
                        range.MoveToElement(parentBlock, true); //expand the range around deletion area to test for maxBounds exceeded
                        if (maximumBounds.InRange(range))
                        {
                            (parentBlock as IHTMLDOMNode).removeNode(true);
                            return(true);
                        }
                    }
                }
            }

            return(false);
        }
Пример #6
0
        /// <summary>
        /// Notify the data format handler that data was dropped and should be inserted into
        /// the document at whatever insert location the handler has internally tracked.
        /// </summary>
        /// <param name="action"></param>
        public override bool DataDropped(DataAction action)
        {
            if (currentCaretLocation == null)
            {
                return(false);
            }

            // create two markup pointers that map to the location of the caret
            MarkupPointer begin = EditorContext.MarkupServices.CreateMarkupPointer();
            MarkupPointer end   = EditorContext.MarkupServices.CreateMarkupPointer();

            EditorContext.MarkupServices.MoveMarkupPointerToCaret(currentCaretLocation, begin);
            MarkupPointerMoveHelper.PerformImageBreakout(begin);

            //optimize the drop location to keep it from being in an unexpected location (fixes bug 395224)
            if (EditorContext.ShouldMoveDropLocationRight(begin))
            {
                begin.Right(true);
            }

            //synchronize the end pointer with the being pointer
            end.MoveToPointer(begin);

            MarkupRange selectedRange = EditorContext.SelectedMarkupRange;

            // WinLive 91888 Photomail image drag drop loses images
            //if (!selectedRange.IsEmpty() && selectedRange.InRange(end))
            if (!selectedRange.IsEmpty() && selectedRange.InRange(end, false))
            {
                //the drop location is over the drag source location, so don't so anything.
                return(false);
            }

            // Forces a SelectionChanged event so that the correct behaviors around the drop location are activated.
            // For example, one side effect of this call is that the OnEditableRegionFocusChanged event is fired, which
            // sets whether the current drop location in the canvas supports images, html and/or text.
            MarkupRange dropRange = EditorContext.MarkupServices.CreateMarkupRange(begin, end);

            dropRange.ToTextRange().select();

            try
            {
                // insert the data at the current insertion point
                return(InsertData(action, begin, end));
            }
            catch (Exception e)
            {
                Trace.Fail(e.Message, e.StackTrace);
                return(false);
            }
        }
Пример #7
0
        private void ApplyBlockFormatToEmptySelection(MarkupRange selection, _ELEMENT_TAG_ID styleTagId, MarkupRange maximumBounds)
        {
            bool deleteParentBlock = false;

            //expand the selection to include the parent content block.  If the expansion can cover the block element
            //without exceeding the maximum bounds, then delete the parent element and wrap the selection in the
            //new block element. If the maximum bounds are exceeded, then just wrap the selection around the bounds.
            IHTMLElementFilter stopFilter =
                ElementFilters.CreateCompoundElementFilter(ElementFilters.BLOCK_ELEMENTS,
                                                           new IHTMLElementFilter(IsSplitStopElement));

            MovePointerLeftUntilRegionBreak(selection.Start, stopFilter, maximumBounds.Start);
            MovePointerRightUntilRegionBreak(selection.End, stopFilter, maximumBounds.End);

            MarkupRange tmpRange = selection.Clone();

            tmpRange.End.MoveToPointer(selection.Start);
            IHTMLElement startStopParent = tmpRange.End.GetParentElement(stopFilter);

            if (startStopParent != null)
            {
                tmpRange.Start.MoveAdjacentToElement(startStopParent, _ELEMENT_ADJACENCY.ELEM_ADJ_BeforeBegin);
                if (tmpRange.IsEmptyOfContent()) //the range from the selection the the block start is empty
                {
                    tmpRange.Start.MoveToPointer(selection.End);
                    IHTMLElement endStopParent = tmpRange.Start.GetParentElement(stopFilter);
                    if (endStopParent != null && startStopParent.sourceIndex == endStopParent.sourceIndex)
                    {
                        tmpRange.Start.MoveAdjacentToElement(endStopParent, _ELEMENT_ADJACENCY.ELEM_ADJ_BeforeEnd);
                        if (tmpRange.IsEmptyOfContent()) //the range from the selection the the block end is empty
                        {
                            tmpRange.MoveToElement(endStopParent, true);
                            if (maximumBounds.InRange(tmpRange) && !(endStopParent is IHTMLTableCell))
                            {
                                deleteParentBlock = true; //the parent has no useful content outside the selection, so it's safe to delete
                            }
                        }
                    }
                }
            }

            //delete the block parent (if appropriate) and wrap the selection in the new block element.
            if (deleteParentBlock)
            {
                (startStopParent as IHTMLDOMNode).removeNode(false);
            }
            IHTMLElement newBlock = WrapRangeInBlockElement(selection, styleTagId);

            selection.MoveToElement(newBlock, false);
        }
Пример #8
0
        internal bool Restore(MarkupRange selection, MarkupRange bounds)
        {
            if (initialMarkup == null)
            {
                return(false);
            }

            NormalizeBounds(ref bounds);

            /*
             *          if (initialMarkup != bounds.HtmlText)
             *          {
             *              Trace.Fail("Unexpected markup");
             *              Trace.WriteLine(initialMarkup);
             *              Trace.WriteLine(bounds.HtmlText);
             *              return false;
             *          }
             */

            selection.Start.MoveToPointer(bounds.Start);

            if (movesRight == int.MaxValue)
            {
                selection.Start.MoveToPointer(bounds.End);
            }
            else
            {
                for (int i = 0; i < movesRight; i++)
                {
                    selection.Start.Right(true);
                }
            }

            for (int i = 0; i < charsLeft; i++)
            {
                selection.Start.MoveUnit(_MOVEUNIT_ACTION.MOVEUNIT_PREVCHAR);
            }

            selection.Collapse(true);
            selection.ToTextRange().select();

            Debug.Assert(bounds.InRange(selection, true), "Selection was out of bounds");

            return(true);
        }
        /// <summary>
        /// Returns true if a word range is in this list that contains this markup pointer.
        /// </summary>
        public bool Contains(MarkupPointer p)
        {
            if (words.Count == 0)
            {
                return(false);
            }

            // Just being defensive
            if (!p.Positioned)
            {
                return(false);
            }

            int idx = BinarySearch(words.Keys, p.PointerRaw, new MarkupPointerComparer());

            if (idx >= 0)
            {
                return(true);
            }

            idx = ~idx;

            // really this could be "if (idx == words.Count)"--it's to handle the case
            // where p is larger than the values in the list
            while (idx >= words.Count)
            {
                idx--;
            }

            for (; idx >= 0; idx--)
            {
                MarkupRange wordRange = words.Values[idx];
                if (wordRange.InRange(p))
                {
                    return(true);
                }
                if (wordRange.End.IsLeftOf(p))
                {
                    break;
                }
            }
            return(false);
        }
Пример #10
0
        private bool IsValidEmoticonInsertionPoint()
        {
            MarkupRange selection = _currentSelection.Clone();

            // Check to make sure the target is not in an edit field
            if (InlineEditField.IsWithinEditField(selection.ParentElement()))
            {
                return(false);
            }

            // Check to make sure the target is in the body of the post
            selection.MoveToElement(_postBodyElement, false);
            if (!selection.InRange(_currentSelection))
            {
                return(false);
            }

            return(true);
        }
        public void ClearRange(MarkupRange clear)
        {
            if (words.Count == 0)
            {
                return;
            }

            // Just being defensive here
            if (!clear.Positioned)
            {
                return;
            }

            // Debug.WriteLine(string.Format("ClearRange:\r\n{0}\r\n{1}", clear.Start.PositionTextDetail, clear.End.PositionTextDetail));

            /*
             * Start from the first range in the list where the start is left of
             * the Clear range's end. Take a look at each range until you get to
             * one where the range's end is left of the Clear range's start.
             */

            int idx = BinarySearch(words.Keys, clear.Start.PointerRaw, new MarkupPointerComparer());

            if (idx < 0)
            {
                idx = ~idx;
                idx--;
                idx = Math.Max(0, idx);
            }

            for (; idx < words.Count; idx++)
            {
                MarkupRange range = words.Values[idx];
                // Debug.WriteLine("Testing range: " + range.Text);
                if (!range.Positioned)
                {
                    // Debug.WriteLine("ClearRange: Removing unpositioned word");
                    words.RemoveAt(idx--);
                }
                else if (clear.End.IsLeftOfOrEqualTo(range.Start))
                {
                    // Debug.WriteLine("We've gone far enough--all done");
                    return;
                }
                else if (clear.InRange(range))
                {
                    // Debug.WriteLine("ClearRange: Removing contained range");
                    words.RemoveAt(idx--);
                }
                else if (range.InRange(clear))
                {
                    // Debug.WriteLine("ClearRange: Splitting range");
                    MarkupRange trailingRange = range.Clone();
                    trailingRange.Start.MoveToPointer(clear.End);
                    range.End.MoveToPointer(clear.Start);

                    if (range.IsEmpty())
                    {
                        words.RemoveAt(idx--);
                    }

                    if (!trailingRange.IsEmpty())
                    {
                        Add(trailingRange);
                    }
                }
                else if (range.InRange(clear.End, false))
                {
                    // Debug.WriteLine("ClearRange: Partial overlap, trimming from start of range");
                    words.RemoveAt(idx--);
                    range.Start.MoveToPointer(clear.End);
                    if (!range.IsEmpty())
                    {
                        Add(range);
                    }
                }
                else if (range.InRange(clear.Start, false))
                {
                    // Debug.WriteLine("ClearRange: Partial overlap, trimming from end of range");
                    range.End.MoveToPointer(clear.End);
                    if (range.IsEmpty())
                    {
                        words.RemoveAt(idx--);
                    }
                }
            }

            // Debug.WriteLine("ClearRange: Remaining words in ignore list: " + words.Count);
        }