// Token: 0x060039C1 RID: 14785 RVA: 0x001064C0 File Offset: 0x001046C0
        private static bool IsAdjacentToFormatElement(ITextPointer pointer, LogicalDirection direction)
        {
            bool result = false;

            if (direction == LogicalDirection.Forward)
            {
                TextPointerContext pointerContext = pointer.GetPointerContext(LogicalDirection.Forward);
                if (pointerContext == TextPointerContext.ElementStart && TextSchema.IsFormattingType(pointer.GetElementType(LogicalDirection.Forward)))
                {
                    result = true;
                }
                else if (pointerContext == TextPointerContext.ElementEnd && TextSchema.IsFormattingType(pointer.ParentType))
                {
                    result = true;
                }
            }
            else
            {
                TextPointerContext pointerContext = pointer.GetPointerContext(LogicalDirection.Backward);
                if (pointerContext == TextPointerContext.ElementEnd && TextSchema.IsFormattingType(pointer.GetElementType(LogicalDirection.Backward)))
                {
                    result = true;
                }
                else if (pointerContext == TextPointerContext.ElementStart && TextSchema.IsFormattingType(pointer.ParentType))
                {
                    result = true;
                }
            }
            return(result);
        }
Пример #2
0
        // Token: 0x06007245 RID: 29253 RVA: 0x0020AA54 File Offset: 0x00208C54
        internal static List <AutomationPeer> GetAutomationPeersFromRange(ITextPointer start, ITextPointer end, ITextPointer ownerContentStart)
        {
            List <AutomationPeer> list = new List <AutomationPeer>();

            start = start.CreatePointer();
            while (start.CompareTo(end) < 0)
            {
                bool flag = false;
                if (start.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementStart)
                {
                    object adjacentElement = start.GetAdjacentElement(LogicalDirection.Forward);
                    if (adjacentElement is ContentElement)
                    {
                        AutomationPeer automationPeer = ContentElementAutomationPeer.CreatePeerForElement((ContentElement)adjacentElement);
                        if (automationPeer != null)
                        {
                            if (ownerContentStart == null || TextContainerHelper.IsImmediateAutomationChild(start, ownerContentStart))
                            {
                                list.Add(automationPeer);
                            }
                            start.MoveToNextContextPosition(LogicalDirection.Forward);
                            start.MoveToElementEdge(ElementEdge.AfterEnd);
                            flag = true;
                        }
                    }
                }
                else if (start.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.EmbeddedElement)
                {
                    object adjacentElement = start.GetAdjacentElement(LogicalDirection.Forward);
                    if (adjacentElement is UIElement)
                    {
                        if (ownerContentStart == null || TextContainerHelper.IsImmediateAutomationChild(start, ownerContentStart))
                        {
                            AutomationPeer automationPeer = UIElementAutomationPeer.CreatePeerForElement((UIElement)adjacentElement);
                            if (automationPeer != null)
                            {
                                list.Add(automationPeer);
                            }
                            else
                            {
                                TextContainerHelper.iterate((Visual)adjacentElement, list);
                            }
                        }
                    }
                    else if (adjacentElement is ContentElement)
                    {
                        AutomationPeer automationPeer = ContentElementAutomationPeer.CreatePeerForElement((ContentElement)adjacentElement);
                        if (automationPeer != null && (ownerContentStart == null || TextContainerHelper.IsImmediateAutomationChild(start, ownerContentStart)))
                        {
                            list.Add(automationPeer);
                        }
                    }
                }
                if (!flag && !start.MoveToNextContextPosition(LogicalDirection.Forward))
                {
                    break;
                }
            }
            return(list);
        }
Пример #3
0
        // Token: 0x060038D8 RID: 14552 RVA: 0x00100E4C File Offset: 0x000FF04C
        private static bool IsErrorAtNonMergeableInlineEdge(SpellingError spellingError, out ITextPointer textStart, out ITextPointer textEnd)
        {
            bool result = false;

            textStart = spellingError.Start.CreatePointer(LogicalDirection.Backward);
            while (textStart.CompareTo(spellingError.End) < 0 && textStart.GetPointerContext(LogicalDirection.Forward) != TextPointerContext.Text)
            {
                textStart.MoveToNextContextPosition(LogicalDirection.Forward);
            }
            textEnd = spellingError.End.CreatePointer();
            while (textEnd.CompareTo(spellingError.Start) > 0 && textEnd.GetPointerContext(LogicalDirection.Backward) != TextPointerContext.Text)
            {
                textEnd.MoveToNextContextPosition(LogicalDirection.Backward);
            }
            if (textStart.GetPointerContext(LogicalDirection.Forward) != TextPointerContext.Text || textStart.CompareTo(spellingError.End) == 0)
            {
                return(false);
            }
            Invariant.Assert(textEnd.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.Text && textEnd.CompareTo(spellingError.Start) != 0);
            if ((TextPointerBase.IsAtNonMergeableInlineStart(textStart) || TextPointerBase.IsAtNonMergeableInlineEnd(textEnd)) && typeof(Run).IsAssignableFrom(textStart.ParentType) && textStart.HasEqualScope(textEnd))
            {
                result = true;
            }
            return(result);
        }
Пример #4
0
        // Token: 0x06002C19 RID: 11289 RVA: 0x000C8360 File Offset: 0x000C6560
        private static DocumentSequenceTextPointer xGetClingDSTP(DocumentSequenceTextPointer thisTp, LogicalDirection direction)
        {
            TextPointerContext pointerContext = thisTp.ChildPointer.GetPointerContext(direction);

            if (pointerContext != TextPointerContext.None)
            {
                return(thisTp);
            }
            ChildDocumentBlock childDocumentBlock = thisTp.ChildBlock;
            ITextPointer       textPointer        = thisTp.ChildPointer;

            if (direction == LogicalDirection.Forward)
            {
                while (pointerContext == TextPointerContext.None)
                {
                    if (childDocumentBlock.IsTail)
                    {
                        break;
                    }
                    childDocumentBlock = childDocumentBlock.NextBlock;
                    textPointer        = childDocumentBlock.ChildContainer.Start;
                    pointerContext     = textPointer.GetPointerContext(direction);
                }
            }
            else
            {
                while (pointerContext == TextPointerContext.None && !childDocumentBlock.IsHead)
                {
                    childDocumentBlock = childDocumentBlock.PreviousBlock;
                    textPointer        = childDocumentBlock.ChildContainer.End;
                    pointerContext     = textPointer.GetPointerContext(direction);
                }
            }
            return(new DocumentSequenceTextPointer(childDocumentBlock, textPointer));
        }
Пример #5
0
        // Token: 0x06007CED RID: 31981 RVA: 0x0023255C File Offset: 0x0023075C
        private static FlowDirection GetTextFlowDirection(ITextPointer pointer)
        {
            Invariant.Assert(pointer != null, "Null pointer passed.");
            Invariant.Assert(pointer.IsAtInsertionPosition, "Pointer is not an insertion position");
            int num = 0;
            LogicalDirection   logicalDirection = pointer.LogicalDirection;
            TextPointerContext pointerContext   = pointer.GetPointerContext(logicalDirection);
            FlowDirection      result;

            if ((pointerContext == TextPointerContext.ElementEnd || pointerContext == TextPointerContext.ElementStart) && !TextSchema.IsFormattingType(pointer.ParentType))
            {
                result = (FlowDirection)pointer.GetValue(FrameworkElement.FlowDirectionProperty);
            }
            else
            {
                Rect         anchorRectangle = TextSelectionHelper.GetAnchorRectangle(pointer);
                ITextPointer textPointer     = pointer.GetNextInsertionPosition(logicalDirection);
                if (textPointer != null)
                {
                    textPointer = textPointer.CreatePointer((logicalDirection == LogicalDirection.Backward) ? LogicalDirection.Forward : LogicalDirection.Backward);
                    if (logicalDirection == LogicalDirection.Forward)
                    {
                        if (pointerContext == TextPointerContext.ElementEnd && textPointer.GetPointerContext(textPointer.LogicalDirection) == TextPointerContext.ElementStart)
                        {
                            return((FlowDirection)pointer.GetValue(FrameworkElement.FlowDirectionProperty));
                        }
                    }
                    else if (pointerContext == TextPointerContext.ElementStart && textPointer.GetPointerContext(textPointer.LogicalDirection) == TextPointerContext.ElementEnd)
                    {
                        return((FlowDirection)pointer.GetValue(FrameworkElement.FlowDirectionProperty));
                    }
                    Rect anchorRectangle2 = TextSelectionHelper.GetAnchorRectangle(textPointer);
                    if (anchorRectangle2 != Rect.Empty && anchorRectangle != Rect.Empty)
                    {
                        num = Math.Sign(anchorRectangle2.Left - anchorRectangle.Left);
                        if (logicalDirection == LogicalDirection.Backward)
                        {
                            num = -num;
                        }
                    }
                }
                if (num == 0)
                {
                    result = (FlowDirection)pointer.GetValue(FrameworkElement.FlowDirectionProperty);
                }
                else
                {
                    result = ((num > 0) ? FlowDirection.LeftToRight : FlowDirection.RightToLeft);
                }
            }
            return(result);
        }
Пример #6
0
        // Token: 0x06006B2D RID: 27437 RVA: 0x001EF394 File Offset: 0x001ED594
        private List <TextElement> GetAttachedObjectElements(int dcpFirst, int dcpLast)
        {
            List <TextElement> list              = new List <TextElement>();
            ITextPointer       contentStart      = TextContainerHelper.GetContentStart(base.StructuralCache.TextContainer, base.Element);
            ITextPointer       textPointerFromCP = TextContainerHelper.GetTextPointerFromCP(base.StructuralCache.TextContainer, base.ParagraphStartCharacterPosition + dcpFirst, LogicalDirection.Forward);

            if (dcpLast > base.Cch)
            {
                dcpLast = base.Cch;
            }
            while (contentStart.GetOffsetToPosition(textPointerFromCP) < dcpLast)
            {
                if (textPointerFromCP.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementStart)
                {
                    TextElement adjacentElementFromOuterPosition = ((TextPointer)textPointerFromCP).GetAdjacentElementFromOuterPosition(LogicalDirection.Forward);
                    if (adjacentElementFromOuterPosition is Figure || adjacentElementFromOuterPosition is Floater)
                    {
                        list.Add(adjacentElementFromOuterPosition);
                        textPointerFromCP.MoveByOffset(adjacentElementFromOuterPosition.SymbolCount);
                    }
                    else
                    {
                        textPointerFromCP.MoveToNextContextPosition(LogicalDirection.Forward);
                    }
                }
                else
                {
                    textPointerFromCP.MoveToNextContextPosition(LogicalDirection.Forward);
                }
            }
            return(list);
        }
        // Token: 0x06003889 RID: 14473 RVA: 0x000FDB54 File Offset: 0x000FBD54
        private static UIElement GetUIElementWhenMouseOver(TextEditor This, Point mouseMovePoint)
        {
            ITextPointer textPositionFromPoint = This.TextView.GetTextPositionFromPoint(mouseMovePoint, false);

            if (textPositionFromPoint == null)
            {
                return(null);
            }
            if (textPositionFromPoint.GetPointerContext(textPositionFromPoint.LogicalDirection) != TextPointerContext.EmbeddedElement)
            {
                return(null);
            }
            ITextPointer     textPointer = textPositionFromPoint.GetNextContextPosition(textPositionFromPoint.LogicalDirection);
            LogicalDirection gravity     = (textPositionFromPoint.LogicalDirection == LogicalDirection.Forward) ? LogicalDirection.Backward : LogicalDirection.Forward;

            textPointer = textPointer.CreatePointer(0, gravity);
            Rect rectangleFromTextPosition  = This.TextView.GetRectangleFromTextPosition(textPositionFromPoint);
            Rect rectangleFromTextPosition2 = This.TextView.GetRectangleFromTextPosition(textPointer);
            Rect rect = rectangleFromTextPosition;

            rect.Union(rectangleFromTextPosition2);
            if (!rect.Contains(mouseMovePoint))
            {
                return(null);
            }
            return(textPositionFromPoint.GetAdjacentElement(textPositionFromPoint.LogicalDirection) as UIElement);
        }
Пример #8
0
        // Token: 0x060038DB RID: 14555 RVA: 0x00100F94 File Offset: 0x000FF194
        private static ITextPointer GetNextTextPosition(ITextPointer position, ITextPointer limit, LogicalDirection direction, out char character)
        {
            bool flag = false;

            character = '\0';
            while (position != null && !flag && (limit == null || position.CompareTo(limit) < 0))
            {
                switch (position.GetPointerContext(direction))
                {
                case TextPointerContext.Text:
                {
                    char[] array = new char[1];
                    position.GetTextInRun(direction, array, 0, 1);
                    character = array[0];
                    flag      = true;
                    continue;
                }

                case TextPointerContext.ElementStart:
                case TextPointerContext.ElementEnd:
                    if (TextSchema.IsFormattingType(position.GetElementType(direction)))
                    {
                        position = position.CreatePointer(1);
                        continue;
                    }
                    position = null;
                    continue;
                }
                position = null;
            }
            return(position);
        }
Пример #9
0
        // Token: 0x060068B0 RID: 26800 RVA: 0x001D8BE4 File Offset: 0x001D6DE4
        protected override BaseParagraph GetParagraph(ITextPointer textPointer, bool fEmptyOk)
        {
            Invariant.Assert(textPointer is TextPointer);
            BaseParagraph baseParagraph = null;

            while (baseParagraph == null)
            {
                TextPointerContext pointerContext = textPointer.GetPointerContext(LogicalDirection.Forward);
                if (pointerContext == TextPointerContext.ElementStart)
                {
                    TextElement adjacentElementFromOuterPosition = ((TextPointer)textPointer).GetAdjacentElementFromOuterPosition(LogicalDirection.Forward);
                    if (adjacentElementFromOuterPosition is ListItem)
                    {
                        baseParagraph = new ListItemParagraph(adjacentElementFromOuterPosition, base.StructuralCache);
                        break;
                    }
                    if (adjacentElementFromOuterPosition is List)
                    {
                        baseParagraph = new ListParagraph(adjacentElementFromOuterPosition, base.StructuralCache);
                        break;
                    }
                    if (((TextPointer)textPointer).IsFrozen)
                    {
                        textPointer = textPointer.CreatePointer();
                    }
                    textPointer.MoveToPosition(adjacentElementFromOuterPosition.ElementEnd);
                }
                else if (pointerContext == TextPointerContext.ElementEnd)
                {
                    if (base.Element == ((TextPointer)textPointer).Parent)
                    {
                        break;
                    }
                    if (((TextPointer)textPointer).IsFrozen)
                    {
                        textPointer = textPointer.CreatePointer();
                    }
                    textPointer.MoveToNextContextPosition(LogicalDirection.Forward);
                }
                else
                {
                    if (((TextPointer)textPointer).IsFrozen)
                    {
                        textPointer = textPointer.CreatePointer();
                    }
                    textPointer.MoveToNextContextPosition(LogicalDirection.Forward);
                }
            }
            if (baseParagraph != null)
            {
                base.StructuralCache.CurrentFormatContext.DependentMax = (TextPointer)textPointer;
            }
            return(baseParagraph);
        }
Пример #10
0
        //------------------------------------------------------
        //
        //  Internal Property
        //
        //------------------------------------------------------

        //------------------------------------------------------
        //
        //  Private Methods
        //
        //------------------------------------------------------

        #region Private Methods
        private static DocumentSequenceTextPointer xGetClingDSTP(DocumentSequenceTextPointer thisTp, LogicalDirection direction)
        {
            TextPointerContext context = thisTp.ChildPointer.GetPointerContext(direction);

            if (context != TextPointerContext.None)
            {
                return(thisTp);
            }

            ChildDocumentBlock block   = thisTp.ChildBlock;
            ITextPointer       pointer = thisTp.ChildPointer;

            if (direction == LogicalDirection.Forward)
            {
                while (context == TextPointerContext.None && !block.IsTail)
                {
                    // get next block
                    block = block.NextBlock;
                    // get start
                    pointer = block.ChildContainer.Start;
                    context = pointer.GetPointerContext(direction);
                }
            }
            else
            {
                Debug.Assert(direction == LogicalDirection.Backward);
                while (context == TextPointerContext.None && !block.IsHead)
                {
                    // get next block
                    block = block.PreviousBlock;
                    // get start
                    pointer = block.ChildContainer.End;
                    context = pointer.GetPointerContext(direction);
                }
            }

            return(new DocumentSequenceTextPointer(block, pointer));
        }
Пример #11
0
            // Token: 0x06008461 RID: 33889 RVA: 0x00247F80 File Offset: 0x00246180
            internal void AddCompositionLines()
            {
                this._compositionLines.Clear();
                ITextPointer textPointer  = this._textView.TextContainer.Start.CreatePointer(this._startOffset, LogicalDirection.Forward);
                ITextPointer textPointer2 = this._textView.TextContainer.Start.CreatePointer(this._endOffset, LogicalDirection.Backward);

                while (textPointer.CompareTo(textPointer2) < 0 && textPointer.GetPointerContext(LogicalDirection.Forward) != TextPointerContext.Text)
                {
                    textPointer.MoveToNextContextPosition(LogicalDirection.Forward);
                }
                Invariant.Assert(textPointer.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text);
                if (textPointer2.HasValidLayout)
                {
                    this._startRect = this._textView.GetRectangleFromTextPosition(textPointer);
                    this._endRect   = this._textView.GetRectangleFromTextPosition(textPointer2);
                    if (this._startRect.Top != this._endRect.Top)
                    {
                        this.AddMultipleCompositionLines(textPointer, textPointer2);
                        return;
                    }
                    Color lineColor = this._textServicesDisplayAttribute.GetLineColor(textPointer);
                    this._compositionLines.Add(new CompositionAdorner.CompositionLine(this._startRect, this._endRect, lineColor));
                }
            }
Пример #12
0
            //------------------------------------------------------
            //
            //  Internal Methods
            //
            //------------------------------------------------------

            #region Internal Methods

            // Add the composition lines for rendering the composition lines.
            internal void AddCompositionLines()
            {
                // Erase any current lines.
                _compositionLines.Clear();

                ITextPointer start = _textView.TextContainer.Start.CreatePointer(_startOffset, LogicalDirection.Forward);
                ITextPointer end   = _textView.TextContainer.Start.CreatePointer(_endOffset, LogicalDirection.Backward);

                while (start.CompareTo(end) < 0 && start.GetPointerContext(LogicalDirection.Forward) != TextPointerContext.Text)
                {
                    start.MoveToNextContextPosition(LogicalDirection.Forward);
                }

                Invariant.Assert(start.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text);

                if (end.HasValidLayout)
                {
                    // Get the rectangle for start/end position
                    _startRect = _textView.GetRectangleFromTextPosition(start);
                    _endRect   = _textView.GetRectangleFromTextPosition(end);

                    // Check whether the composition line is single or multiple lines
                    if (_startRect.Top != _endRect.Top)
                    {
                        // Add the composition lines to be rendered for the composition string
                        AddMultipleCompositionLines(start, end);
                    }
                    else
                    {
                        // Set the start/end pointer to draw the line
                        Color lineColor = _textServicesDisplayAttribute.GetLineColor(start);
                        // Add the composition line to be rendered
                        _compositionLines.Add(new CompositionLine(_startRect, _endRect, lineColor));
                    }
                }
            }
Пример #13
0
        // Token: 0x06003282 RID: 12930 RVA: 0x000DD010 File Offset: 0x000DB210
        internal static bool HasNoTextContent(Paragraph paragraph)
        {
            ITextPointer textPointer = paragraph.ContentStart.CreatePointer();
            ITextPointer contentEnd  = paragraph.ContentEnd;

            while (textPointer.CompareTo(contentEnd) < 0)
            {
                TextPointerContext pointerContext = textPointer.GetPointerContext(LogicalDirection.Forward);
                if (pointerContext == TextPointerContext.Text || pointerContext == TextPointerContext.EmbeddedElement || typeof(LineBreak).IsAssignableFrom(textPointer.ParentType) || typeof(AnchoredBlock).IsAssignableFrom(textPointer.ParentType))
                {
                    return(false);
                }
                textPointer.MoveToNextContextPosition(LogicalDirection.Forward);
            }
            return(true);
        }
Пример #14
0
        // Token: 0x06006B2C RID: 27436 RVA: 0x001EF318 File Offset: 0x001ED518
        internal int GetLastDcpAttachedObjectBeforeLine(int dcpFirst)
        {
            ITextPointer textPointerFromCP = TextContainerHelper.GetTextPointerFromCP(base.StructuralCache.TextContainer, base.ParagraphStartCharacterPosition + dcpFirst, LogicalDirection.Forward);
            ITextPointer contentStart      = TextContainerHelper.GetContentStart(base.StructuralCache.TextContainer, base.Element);

            while (textPointerFromCP.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementStart)
            {
                TextElement adjacentElementFromOuterPosition = ((TextPointer)textPointerFromCP).GetAdjacentElementFromOuterPosition(LogicalDirection.Forward);
                if (!(adjacentElementFromOuterPosition is Figure) && !(adjacentElementFromOuterPosition is Floater))
                {
                    break;
                }
                textPointerFromCP.MoveByOffset(adjacentElementFromOuterPosition.SymbolCount);
            }
            return(contentStart.GetOffsetToPosition(textPointerFromCP));
        }
            // Token: 0x06008E5B RID: 36443 RVA: 0x0025BE9C File Offset: 0x0025A09C
            private void GetContent()
            {
                this._contentSegments.Clear();
                ITextPointer textPointer  = this._segment.Start.CreatePointer();
                ITextPointer textPointer2 = null;

                while (textPointer.CompareTo(this._segment.End) < 0)
                {
                    TextPointerContext pointerContext = textPointer.GetPointerContext(LogicalDirection.Forward);
                    if (pointerContext == TextPointerContext.ElementStart)
                    {
                        Type elementType = textPointer.GetElementType(LogicalDirection.Forward);
                        if (typeof(Run).IsAssignableFrom(elementType) || typeof(BlockUIContainer).IsAssignableFrom(elementType))
                        {
                            this.OpenSegment(ref textPointer2, textPointer);
                        }
                        else if (typeof(Table).IsAssignableFrom(elementType) || typeof(Floater).IsAssignableFrom(elementType) || typeof(Figure).IsAssignableFrom(elementType))
                        {
                            this.CloseSegment(ref textPointer2, textPointer, this._segment.End);
                        }
                        textPointer.MoveToNextContextPosition(LogicalDirection.Forward);
                        if (typeof(Run).IsAssignableFrom(elementType) || typeof(BlockUIContainer).IsAssignableFrom(elementType))
                        {
                            textPointer.MoveToElementEdge(ElementEdge.AfterEnd);
                        }
                    }
                    else if (pointerContext == TextPointerContext.ElementEnd)
                    {
                        Type parentType = textPointer.ParentType;
                        if (typeof(TableCell).IsAssignableFrom(parentType) || typeof(Floater).IsAssignableFrom(parentType) || typeof(Figure).IsAssignableFrom(parentType))
                        {
                            this.CloseSegment(ref textPointer2, textPointer, this._segment.End);
                        }
                        textPointer.MoveToNextContextPosition(LogicalDirection.Forward);
                    }
                    else if (pointerContext == TextPointerContext.Text || pointerContext == TextPointerContext.EmbeddedElement)
                    {
                        this.OpenSegment(ref textPointer2, textPointer);
                        textPointer.MoveToNextContextPosition(LogicalDirection.Forward);
                    }
                    else
                    {
                        Invariant.Assert(false, "unexpected TextPointerContext");
                    }
                }
                this.CloseSegment(ref textPointer2, textPointer, this._segment.End);
            }
        // Returns the position preceeding the next text character in a specified
        // direction, or null if no such position exists.
        // The scan will halt if limit is encounted; limit may be null.
        private static ITextPointer GetNextTextPosition(ITextPointer position, ITextPointer limit, LogicalDirection direction, out char character)
        {
            bool foundText = false;

            character = (char)0;

            while (position != null &&
                   !foundText &&
                   (limit == null || position.CompareTo(limit) < 0))
            {
                switch (position.GetPointerContext(direction))
                {
                case TextPointerContext.Text:
                    char[] buffer = new char[1];
                    position.GetTextInRun(direction, buffer, 0, 1);
                    character = buffer[0];
                    foundText = true;
                    break;

                case TextPointerContext.ElementStart:
                case TextPointerContext.ElementEnd:
                    if (TextSchema.IsFormattingType(position.GetElementType(direction)))
                    {
                        position = position.CreatePointer(+1);
                    }
                    else
                    {
                        position = null;
                    }
                    break;

                case TextPointerContext.EmbeddedElement:
                case TextPointerContext.None:
                default:
                    position = null;
                    break;
                }
            }

            return(position);
        }
Пример #17
0
        // Return a UIElement when mouseMovePoint is within the ui element's bounding Rect. Null otherwise.
        private static UIElement GetUIElementWhenMouseOver(TextEditor This, Point mouseMovePoint)
        {
            ITextPointer mouseMovePosition = This.TextView.GetTextPositionFromPoint(mouseMovePoint, /*snapToText:*/ false);

            if (mouseMovePosition == null)
            {
                return(null);
            }

            if (!(mouseMovePosition.GetPointerContext(mouseMovePosition.LogicalDirection) == TextPointerContext.EmbeddedElement))
            {
                return(null);
            }

            // Find out if mouseMovePoint is within the bounding Rect of UIElement, we need to do this check explicitly
            // because even when snapToText is false, textview returns a first/last position on a line when point is in
            // an area before/after line start/end. This is by-design behavior for textview.

            // Need to get Rect from TextView, since Rect returned by TextPointer.GetCharacterRect()
            // is transformed to UiScope coordinates and we want RenderScope coordinates here.

            ITextPointer     otherEdgePosition  = mouseMovePosition.GetNextContextPosition(mouseMovePosition.LogicalDirection);
            LogicalDirection otherEdgeDirection = (mouseMovePosition.LogicalDirection == LogicalDirection.Forward) ?
                                                  LogicalDirection.Backward : LogicalDirection.Forward;

            // Normalize with correct gravity
            otherEdgePosition = otherEdgePosition.CreatePointer(0, otherEdgeDirection);

            Rect uiElementFirstEdgeRect  = This.TextView.GetRectangleFromTextPosition(mouseMovePosition);
            Rect uiElementSecondEdgeRect = This.TextView.GetRectangleFromTextPosition(otherEdgePosition);

            Rect boundingRect = uiElementFirstEdgeRect;

            boundingRect.Union(uiElementSecondEdgeRect);
            if (!boundingRect.Contains(mouseMovePoint))
            {
                return(null);
            }

            return(mouseMovePosition.GetAdjacentElement(mouseMovePosition.LogicalDirection) as UIElement);
        }
Пример #18
0
            // Token: 0x06008465 RID: 33893 RVA: 0x002480A0 File Offset: 0x002462A0
            private void AddMultipleCompositionLines(ITextPointer start, ITextPointer end)
            {
                ITextPointer textPointer  = start;
                ITextPointer textPointer2 = textPointer;

                while (textPointer2.CompareTo(end) < 0)
                {
                    TextSegment lineRange = this._textView.GetLineRange(textPointer2);
                    if (lineRange.IsNull)
                    {
                        textPointer = textPointer2;
                    }
                    else
                    {
                        if (textPointer.CompareTo(lineRange.Start) < 0)
                        {
                            textPointer = lineRange.Start;
                        }
                        if (textPointer2.CompareTo(lineRange.End) < 0)
                        {
                            if (end.CompareTo(lineRange.End) < 0)
                            {
                                textPointer2 = end.CreatePointer();
                            }
                            else
                            {
                                textPointer2 = lineRange.End.CreatePointer(LogicalDirection.Backward);
                            }
                        }
                        Rect rectangleFromTextPosition  = this._textView.GetRectangleFromTextPosition(textPointer);
                        Rect rectangleFromTextPosition2 = this._textView.GetRectangleFromTextPosition(textPointer2);
                        this._compositionLines.Add(new CompositionAdorner.CompositionLine(rectangleFromTextPosition, rectangleFromTextPosition2, this._textServicesDisplayAttribute.GetLineColor(textPointer)));
                        textPointer = lineRange.End.CreatePointer(LogicalDirection.Forward);
                    }
                    while (textPointer.GetPointerContext(LogicalDirection.Forward) != TextPointerContext.None && textPointer.GetPointerContext(LogicalDirection.Forward) != TextPointerContext.Text)
                    {
                        textPointer.MoveToNextContextPosition(LogicalDirection.Forward);
                    }
                    textPointer2 = textPointer;
                }
            }
        // Token: 0x06006600 RID: 26112 RVA: 0x001CAB08 File Offset: 0x001C8D08
        public override TextSpan <CultureSpecificCharacterBufferRange> GetPrecedingText(int dcp)
        {
            int num = 0;
            CharacterBufferRange empty   = CharacterBufferRange.Empty;
            CultureInfo          culture = null;

            if (dcp > 0)
            {
                ITextPointer textPointer = this._owner.TextContainer.CreatePointerAtOffset(dcp, LogicalDirection.Backward);
                while (textPointer.GetPointerContext(LogicalDirection.Backward) != TextPointerContext.Text && textPointer.CompareTo(this._owner.TextContainer.Start) != 0)
                {
                    textPointer.MoveByOffset(-1);
                    num++;
                }
                string textInRun = textPointer.GetTextInRun(LogicalDirection.Backward);
                empty = new CharacterBufferRange(textInRun, 0, textInRun.Length);
                StaticTextPointer staticTextPointer = textPointer.CreateStaticPointer();
                DependencyObject  element           = (staticTextPointer.Parent != null) ? staticTextPointer.Parent : this._owner;
                culture = DynamicPropertyReader.GetCultureInfo(element);
            }
            return(new TextSpan <CultureSpecificCharacterBufferRange>(num + empty.Length, new CultureSpecificCharacterBufferRange(culture, empty)));
        }
Пример #20
0
        /// <summary>
        /// Get text immediately before specified text source position. Return CharacterBufferRange
        /// containing this text.
        /// </summary>
        /// <param name="dcp">
        /// dcp of position relative to start of line
        /// </param>
        internal override TextSpan <CultureSpecificCharacterBufferRange> GetPrecedingText(int dcp)
        {
            // Parameter validation
            Invariant.Assert(dcp >= 0);

            int nonTextLength = 0;
            CharacterBufferRange precedingText = CharacterBufferRange.Empty;
            CultureInfo          culture       = null;

            if (dcp > 0)
            {
                // Create TextPointer at dcp, and pointer at paragraph start to compare
                ITextPointer startPosition = TextContainerHelper.GetTextPointerFromCP(_paraClient.Paragraph.StructuralCache.TextContainer, _cpPara, LogicalDirection.Forward);
                ITextPointer position      = TextContainerHelper.GetTextPointerFromCP(_paraClient.Paragraph.StructuralCache.TextContainer, _cpPara + dcp, LogicalDirection.Forward);

                // Move backward until we find a position at the end of a text run, or reach start of TextContainer
                while (position.GetPointerContext(LogicalDirection.Backward) != TextPointerContext.Text &&
                       position.CompareTo(startPosition) != 0)
                {
                    position.MoveByOffset(-1);
                    nonTextLength++;
                }


                // Return text in run. If it is at start of TextContainer this will return an empty string
                string precedingTextString = position.GetTextInRun(LogicalDirection.Backward);
                precedingText = new CharacterBufferRange(precedingTextString, 0, precedingTextString.Length);


                StaticTextPointer pointer = position.CreateStaticPointer();
                DependencyObject  element = (pointer.Parent != null) ? pointer.Parent : _paraClient.Paragraph.Element;
                culture = DynamicPropertyReader.GetCultureInfo(element);
            }

            return(new TextSpan <CultureSpecificCharacterBufferRange>(
                       nonTextLength + precedingText.Length,
                       new CultureSpecificCharacterBufferRange(culture, precedingText)
                       ));
        }
Пример #21
0
        // Token: 0x06006864 RID: 26724 RVA: 0x001D6C0C File Offset: 0x001D4E0C
        internal override TextSpan <CultureSpecificCharacterBufferRange> GetPrecedingText(int dcp)
        {
            Invariant.Assert(dcp >= 0);
            int num = 0;
            CharacterBufferRange empty   = CharacterBufferRange.Empty;
            CultureInfo          culture = null;

            if (dcp > 0)
            {
                ITextPointer textPointerFromCP  = TextContainerHelper.GetTextPointerFromCP(this._paraClient.Paragraph.StructuralCache.TextContainer, this._cpPara, LogicalDirection.Forward);
                ITextPointer textPointerFromCP2 = TextContainerHelper.GetTextPointerFromCP(this._paraClient.Paragraph.StructuralCache.TextContainer, this._cpPara + dcp, LogicalDirection.Forward);
                while (textPointerFromCP2.GetPointerContext(LogicalDirection.Backward) != TextPointerContext.Text && textPointerFromCP2.CompareTo(textPointerFromCP) != 0)
                {
                    textPointerFromCP2.MoveByOffset(-1);
                    num++;
                }
                string textInRun = textPointerFromCP2.GetTextInRun(LogicalDirection.Backward);
                empty = new CharacterBufferRange(textInRun, 0, textInRun.Length);
                StaticTextPointer staticTextPointer = textPointerFromCP2.CreateStaticPointer();
                DependencyObject  element           = (staticTextPointer.Parent != null) ? staticTextPointer.Parent : this._paraClient.Paragraph.Element;
                culture = DynamicPropertyReader.GetCultureInfo(element);
            }
            return(new TextSpan <CultureSpecificCharacterBufferRange>(num + empty.Length, new CultureSpecificCharacterBufferRange(culture, empty)));
        }
Пример #22
0
        // ------------------------------------------------------------------
        // Get text immediately before specified text source position.
        // ------------------------------------------------------------------
        public override TextSpan <CultureSpecificCharacterBufferRange> GetPrecedingText(int dcp)
        {
            // Parameter validation
            Debug.Assert(dcp >= 0);

            int nonTextLength = 0;
            CharacterBufferRange precedingText = CharacterBufferRange.Empty;
            CultureInfo          culture       = null;

            if (dcp > 0)
            {
                // Create TextPointer at dcp
                ITextPointer position = _owner.TextContainer.CreatePointerAtOffset(dcp, LogicalDirection.Backward);

                // Move backward until we find a position at the end of a text run, or reach start of TextContainer
                while (position.GetPointerContext(LogicalDirection.Backward) != TextPointerContext.Text &&
                       position.CompareTo(_owner.TextContainer.Start) != 0)
                {
                    position.MoveByOffset(-1);
                    nonTextLength++;
                }

                // Return text in run. If it is at start of TextContainer this will return an empty string
                string precedingTextString = position.GetTextInRun(LogicalDirection.Backward);
                precedingText = new CharacterBufferRange(precedingTextString, 0, precedingTextString.Length);

                StaticTextPointer pointer = position.CreateStaticPointer();
                DependencyObject  element = (pointer.Parent != null) ? pointer.Parent : _owner;
                culture = DynamicPropertyReader.GetCultureInfo(element);
            }

            return(new TextSpan <CultureSpecificCharacterBufferRange>(
                       nonTextLength + precedingText.Length,
                       new CultureSpecificCharacterBufferRange(culture, precedingText)
                       ));
        }
        internal static bool IsAtNormalizedPosition(ITextPointer position, LogicalDirection direction, bool respectCaretUnitBoundaries)
        {
            if (!IsAtNormalizedPosition(position, respectCaretUnitBoundaries))
            {
                return false;
            }

            // 

            if (position.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.ElementStart &&
                position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementEnd)
            {
                return true;
            }

            // Check if there is no any formatting tags in the given direction
            if (TextSchema.IsFormattingType(position.GetElementType(direction)))
            {
                position = position.CreatePointer();
                while (TextSchema.IsFormattingType(position.GetElementType(direction)))
                {
                    position.MoveToNextContextPosition(direction);
                }

                if (IsAtNormalizedPosition(position, respectCaretUnitBoundaries))
                {
                    // So there is a possibility to move over formatting tags only
                    // and reach some insertion position. This means
                    // that our position was not normalized in the given direction.
                    return false;
                }
            }

            return true;
        }
Пример #24
0
        /// <summary>
        /// </summary>
        void ITextSelection.SetCaretToPosition(ITextPointer caretPosition, LogicalDirection direction, bool allowStopAtLineEnd, bool allowStopNearSpace)
        {
            // We need a pointer with appropriate direction,
            // becasue it will be used in textRangeBase.Select method for
            // pointer normalization.
            caretPosition = caretPosition.CreatePointer(direction);

            // Normalize the position in its logical direction - to get to text content over there.
            caretPosition.MoveToInsertionPosition(direction);

            // We need a pointer with the reverse direction to confirm
            // the line wrapping position. So we can ensure Bidi caret navigation.
            // Bidi can have the different caret position by setting the
            // logical direction, so we have to only set the logical direction
            // as the forward for the real line wrapping position.
            ITextPointer reversePosition = caretPosition.CreatePointer(direction == LogicalDirection.Forward ? LogicalDirection.Backward : LogicalDirection.Forward);

            // Check line wrapping condition
            if (!allowStopAtLineEnd &&
                ((TextPointerBase.IsAtLineWrappingPosition(caretPosition, this.TextView) &&
                  TextPointerBase.IsAtLineWrappingPosition(reversePosition, this.TextView)) ||
                 TextPointerBase.IsNextToPlainLineBreak(caretPosition, LogicalDirection.Backward) ||
                 TextSchema.IsBreak(caretPosition.GetElementType(LogicalDirection.Backward))))
            {
                // Caret is at wrapping position, and we are not allowed to stay at end of line,
                // so we choose forward direction to appear in the begiinning of a second line
                caretPosition.SetLogicalDirection(LogicalDirection.Forward);
            }
            else
            {
                if (caretPosition.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.Text &&
                    caretPosition.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
                {
                    // This is statistically most typical case. No "smartness" needed
                    // to choose standard Forward orientation for the caret.
                    // NOTE: By using caretPosition's direction we solve BiDi caret orientation case:
                    // The orietnation reflects a direction from where caret has been moved
                    // or orientation where mouse clicked. So we will stick with appropriate
                    // character.

                    // Nothing to do. The caretPosition is good to go.
                }
                else if (!allowStopNearSpace)
                {
                    // There are some tags around, and we are not allowed to choose a side near to space.
                    // So we need to perform some content analysis.

                    char[] charBuffer = new char[1];

                    if (caretPosition.GetPointerContext(direction) == TextPointerContext.Text &&
                        caretPosition.GetTextInRun(direction, charBuffer, 0, 1) == 1 &&
                        Char.IsWhiteSpace(charBuffer[0]))
                    {
                        LogicalDirection oppositeDirection = direction == LogicalDirection.Forward ? LogicalDirection.Backward : LogicalDirection.Forward;

                        // Check formatting switch condition at this position
                        FlowDirection initialFlowDirection = (FlowDirection)caretPosition.GetValue(FrameworkElement.FlowDirectionProperty);

                        bool moved = caretPosition.MoveToInsertionPosition(oppositeDirection);

                        if (moved &&
                            initialFlowDirection == (FlowDirection)caretPosition.GetValue(FrameworkElement.FlowDirectionProperty) &&
                            (caretPosition.GetPointerContext(oppositeDirection) != TextPointerContext.Text ||
                             caretPosition.GetTextInRun(oppositeDirection, charBuffer, 0, 1) != 1 ||
                             !Char.IsWhiteSpace(charBuffer[0])))
                        {
                            // In the opposite direction we have a non-space
                            // character. So we choose that direction
                            direction = oppositeDirection;
                            caretPosition.SetLogicalDirection(direction);
                        }
                    }
                }
            }

            // Now that orientation of a caretPosition is identified,
            // build an empty selection at this position
            TextRangeBase.BeginChange(this);
            try
            {
                TextRangeBase.Select(this, caretPosition, caretPosition);

                // Note how Select method works for the case of empty range:
                // It creates a single instance TextPointer normalized and oriented
                // in a direction taken from caretPosition:
                ITextSelection thisSelection = this;
                Invariant.Assert(thisSelection.Start.LogicalDirection == caretPosition.LogicalDirection); // orientation must be as passed
                Invariant.Assert(this.IsEmpty);
                //Invariant.Assert((object)thisSelection.Start == (object)thisSelection.End); // it must be the same instance of TextPointer
                //Invariant.Assert(TextPointerBase.IsAtInsertionPosition(thisSelection.Start, caretPosition.LogicalDirection)); // normalization must be done in the same diredction as orientation

                // Clear active positions when selection is empty
                SetActivePositions(null, null);
            }
            finally
            {
                TextRangeBase.EndChange(this);
            }
        }
        // Token: 0x06002EDF RID: 11999 RVA: 0x000D3640 File Offset: 0x000D1840
        internal override Rect GetRawRectangleFromTextPosition(ITextPointer position, out Transform transform)
        {
            FixedTextPointer fixedTextPointer = this.Container.VerifyPosition(position);
            Rect             result           = new Rect(0.0, 0.0, 0.0, 10.0);

            transform = Transform.Identity;
            FixedPosition fixedPosition;

            if (fixedTextPointer.FlowPosition.IsBoundary)
            {
                if (!this._GetFirstFixedPosition(fixedTextPointer, out fixedPosition))
                {
                    return(result);
                }
            }
            else if (!this._GetFixedPosition(fixedTextPointer, out fixedPosition))
            {
                if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.None)
                {
                    return(result);
                }
                ITextPointer     position2 = position.CreatePointer(1);
                FixedTextPointer ftp       = this.Container.VerifyPosition(position2);
                if (!this._GetFixedPosition(ftp, out fixedPosition))
                {
                    return(result);
                }
            }
            if (fixedPosition.Page != this.PageIndex)
            {
                return(result);
            }
            DependencyObject element = this.FixedPage.GetElement(fixedPosition.Node);

            if (element is Glyphs)
            {
                Glyphs glyphs = (Glyphs)element;
                result = FixedTextView._GetGlyphRunDesignRect(glyphs, fixedPosition.Offset, fixedPosition.Offset);
                GeneralTransform transform2 = glyphs.TransformToAncestor(this.FixedPage);
                result = this._GetTransformedCaretRect(transform2, result.TopLeft, result.Height);
            }
            else if (element is Image)
            {
                Image            image      = (Image)element;
                GeneralTransform transform3 = image.TransformToAncestor(this.FixedPage);
                Point            origin     = new Point(0.0, 0.0);
                if (fixedPosition.Offset > 0)
                {
                    origin.X += image.ActualWidth;
                }
                result = this._GetTransformedCaretRect(transform3, origin, image.ActualHeight);
            }
            else if (element is Path)
            {
                Path             path       = (Path)element;
                GeneralTransform transform4 = path.TransformToAncestor(this.FixedPage);
                Rect             bounds     = path.Data.Bounds;
                Point            topLeft    = bounds.TopLeft;
                if (fixedPosition.Offset > 0)
                {
                    topLeft.X += bounds.Width;
                }
                result = this._GetTransformedCaretRect(transform4, topLeft, bounds.Height);
            }
            return(result);
        }
Пример #26
0
        private void TextPositionsFromITfRange(UnsafeNativeMethods.ITfRange range, out ITextPointer start, out ITextPointer end)
        {
            UnsafeNativeMethods.ITfRangeACP rangeACP;
            int startIndex;
            int length;

            rangeACP = range as UnsafeNativeMethods.ITfRangeACP;
            rangeACP.GetExtent(out startIndex, out length);

            start = CreatePointerAtCharOffset(startIndex, LogicalDirection.Backward);
            end = CreatePointerAtCharOffset(startIndex + length, LogicalDirection.Forward);

            while (start.CompareTo(end) < 0 && start.GetPointerContext(LogicalDirection.Forward) != TextPointerContext.Text)
            {
                start.MoveToNextContextPosition(LogicalDirection.Forward);
            }
        }
Пример #27
0
        internal Rect GetRectangleFromTextPosition(ITextPointer position)
        { 
            Rect rect = System.Windows.Rect.Empty;
 
            int cp = Paragraph.StructuralCache.TextContainer.Start.GetOffsetToPosition((TextPointer)position); 
            int dcp = cp - Paragraph.ParagraphStartCharacterPosition;
            int originalDcp = dcp; 
            if (position.LogicalDirection == LogicalDirection.Backward && dcp > 0)
            {
                --dcp;
            } 

            // Query paragraph details 
            PTS.FSTEXTDETAILS textDetails; 
            PTS.Validate(PTS.FsQueryTextDetails(PtsContext.Context, _paraHandle.Value, out textDetails));
 
            // There are 3 different types of text paragraphs:
            // (a) full with simple lines
            // (b) full with composite lines - when figures/floaters are present
            // (c) cached - when using ParaChache 
            if (textDetails.fsktd == PTS.FSKTEXTDETAILS.fsktdFull)
            { 
                if (textDetails.u.full.cLines > 0) 
                {
                    int vrBaseline = 0; 

                    if (!PTS.ToBoolean(textDetails.u.full.fLinesComposite))
                    {
                        // (a) full with simple lines 
                        RectFromDcpSimpleLines(dcp, originalDcp, position.LogicalDirection, position.GetPointerContext(position.LogicalDirection), ref textDetails.u.full, ref rect, ref vrBaseline);
                    } 
                    else 
                    {
                        // (b) full with composite lines - when figures/floaters are present 
                        RectFromDcpCompositeLines(dcp, originalDcp, position.LogicalDirection, position.GetPointerContext(position.LogicalDirection), ref textDetails.u.full, ref rect, ref vrBaseline);
                    }
                }
            } 
            else
            { 
                // (c) cached - when using ParaChache 
                Debug.Assert(textDetails.fsktd == PTS.FSKTEXTDETAILS.fsktdCached);
                Debug.Assert(false, "Should not get here. ParaCache is not currently used."); 
            }

            // Mirror back to page flow direction
            if(ThisFlowDirection != PageFlowDirection) 
            {
                PTS.FSRECT pageRect = _pageContext.PageRect; 
                PTS.FSRECT rectTransform = new PTS.FSRECT(rect); 
                PTS.Validate(PTS.FsTransformRectangle(PTS.FlowDirectionToFswdir(ThisFlowDirection), ref pageRect, ref rectTransform, PTS.FlowDirectionToFswdir(PageFlowDirection), out rectTransform));
                rect = rectTransform.FromTextDpi(); 
            }

            return rect;
        } 
        /// <summary>
        /// Advances this TextNavigator by a count number of characters.
        /// </summary>
        /// <param name="thisNavigator">ITextPointer to advance.</param>
        /// <param name="direction">
        /// A direction in which to search a next characters.
        /// </param>
        /// <returns>
        /// True if the navigator is advanced, false if the end of document is
        /// encountered and the navigator is not repositioned.
        /// </returns>
        /// <remarks>
        /// A "character" in this context is a sequence of one or several text
        /// symbols: one or more Unicode code points may be a character, every
        /// embedded object is a character, a sequence of closing block tags
        /// followed by opening block tags may also be a unit. Formatting tags
        /// do not contribute in any unit.
        /// </remarks>
        internal static bool MoveToNextInsertionPosition(ITextPointer thisNavigator, LogicalDirection direction)
        {
            Invariant.Assert(!thisNavigator.IsFrozen, "Can't reposition a frozen pointer!");

            bool moved = true;

            int increment = direction == LogicalDirection.Forward ? +1 : -1;

            ITextPointer initialPosition = thisNavigator.CreatePointer();

            if (!IsAtInsertionPosition(thisNavigator))
            {
                // If the TextPointer is not currently at an insertion position,
                // move the TextPointer to the next insertion position in
                // the indicated direction, just like the MoveToInsertionPosition method.

                if (!MoveToInsertionPosition(thisNavigator, direction))
                {
                    // No insertion position in all content. MoveToInsertionPosition() guarantees that navigator is moved back to initial position.
                    moved = false;
                    goto Exit;
                }

                if ((direction == LogicalDirection.Forward && initialPosition.CompareTo(thisNavigator) < 0) ||
                    (direction == LogicalDirection.Backward && thisNavigator.CompareTo(initialPosition) < 0))
                {
                    // We have found an insertion position in requested direction.
                    goto Exit;
                }
            }

            // Start with skipping character formatting tags in this direction
            while (TextSchema.IsFormattingType(thisNavigator.GetElementType(direction)))
            {
                thisNavigator.MoveByOffset(increment);
            }

            do
            {
                if (thisNavigator.GetPointerContext(direction) != TextPointerContext.None)
                {
                    thisNavigator.MoveByOffset(increment);
                }
                else
                {
                    // No insertion position in this direction; Move back
                    thisNavigator.MoveToPosition(initialPosition);
                    moved = false;
                    goto Exit;
                }
            }
            while (!IsAtInsertionPosition(thisNavigator));

            // We must leave position normalized in backward direction
            if (direction == LogicalDirection.Backward)
            {
                // For this we must skip character formatting tags if we have any
                while (TextSchema.IsFormattingType(thisNavigator.GetElementType(direction)))
                {
                    thisNavigator.MoveByOffset(increment);
                }

                // However if it is block start we should back off
                TextPointerContext context = thisNavigator.GetPointerContext(direction);
                if (context == TextPointerContext.ElementStart || context == TextPointerContext.None)
                {
                    increment = -increment;
                    while (TextSchema.IsFormattingType(thisNavigator.GetElementType(LogicalDirection.Forward))
                           && !IsAtInsertionPosition(thisNavigator))
                    {
                        thisNavigator.MoveByOffset(increment);
                    }
                }
            }

        Exit:
            if (moved)
            {
                if (direction == LogicalDirection.Forward)
                {
                    Invariant.Assert(thisNavigator.CompareTo(initialPosition) > 0, "thisNavigator is expected to be moved from initialPosition - 1");
                }
                else
                {
                    Invariant.Assert(thisNavigator.CompareTo(initialPosition) < 0, "thisNavigator is expected to be moved from initialPosition - 2");
                }
            }
            else
            {
                Invariant.Assert(thisNavigator.CompareTo(initialPosition) == 0, "thisNavigator must stay at initial position");
            }
            return moved;
        }
Пример #29
0
        // GetText handler for object runs.
        private static bool WalkObjectRun(ITextPointer navigator, ITextPointer limit, char[] text, int cchReq, ref int charsCopied, UnsafeNativeMethods.TS_RUNINFO[] runInfo, int cRunInfoReq, ref int cRunInfoRcv)
        {
            bool hitLimit;

            Invariant.Assert(navigator.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.EmbeddedElement);
            Invariant.Assert(limit == null || navigator.CompareTo(limit) <= 0);

            if (limit != null && navigator.CompareTo(limit) == 0)
            {
                return true;
            }

            hitLimit = false;

            navigator.MoveToNextContextPosition(LogicalDirection.Forward);

            if (cchReq >= 1)
            {
                text[charsCopied] = UnsafeNativeMethods.TS_CHAR_EMBEDDED;
                charsCopied++;
            }

            if (cRunInfoReq > 0)
            {
                // Be sure to merge this text run with the previous run, if they are both text runs.
                // (A good robustness fix would be to make cicero handle this, if we ever get the chance.)
                if (cRunInfoRcv > 0 && runInfo[cRunInfoRcv - 1].type == UnsafeNativeMethods.TsRunType.TS_RT_PLAIN)
                {
                    runInfo[cRunInfoRcv - 1].count++;
                }
                else
                {
                    runInfo[cRunInfoRcv].count = 1;
                    runInfo[cRunInfoRcv].type = UnsafeNativeMethods.TsRunType.TS_RT_PLAIN;
                    cRunInfoRcv++;
                }
            }

            return hitLimit;
        }
        private static ITextPointer RestrictWithinBlock(ITextPointer position, ITextPointer limit, LogicalDirection direction)
        {
            Invariant.Assert(!(direction == LogicalDirection.Backward) || position.CompareTo(limit) >= 0, "for backward direction position must be >= than limit");
            Invariant.Assert(!(direction == LogicalDirection.Forward) || position.CompareTo(limit) <= 0, "for forward direcion position must be <= than linit");

            while (direction == LogicalDirection.Backward ? position.CompareTo(limit) > 0 : position.CompareTo(limit) < 0)
            {
                TextPointerContext context = position.GetPointerContext(direction);
                if (context == TextPointerContext.ElementStart || context == TextPointerContext.ElementEnd)
                {
                    Type elementType = position.GetElementType(direction);
                    if (!typeof(Inline).IsAssignableFrom(elementType))
                    {
                        limit = position;
                        break;
                    }
                }
                else if (context == TextPointerContext.EmbeddedElement)
                {
                    limit = position;
                    break;
                }
                position = position.GetNextContextPosition(direction);
            }

            // Return normalized position - in the direction towards a center position.
            return limit.GetInsertionPosition(direction == LogicalDirection.Backward ? LogicalDirection.Forward : LogicalDirection.Backward);
        }
 // Position at document end - after the last paragraph/list/table is
 // considered as valid insertion point position.
 // It has though a special behavior for caret positioning and text insertion
 internal static bool IsAfterLastParagraph(ITextPointer thisPosition)
 {
     return thisPosition.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.None &&
            thisPosition.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.ElementEnd &&
            !typeof(Inline).IsAssignableFrom(thisPosition.GetElementType(LogicalDirection.Backward));
 }
        /// <summary>
        /// Return true if rangeEnd is not at the end of an element.
        /// 
        /// textReader must already be at the start of the element.
        /// </summary>        
        private static bool IsPartialNonTypographic(ITextPointer textReader, ITextPointer rangeEnd)
        {
            bool isPartial = false;

            Invariant.Assert(textReader.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementStart);

            ITextPointer elementNavigation = textReader.CreatePointer();
            ITextPointer elementEnd = textReader.CreatePointer();

            elementEnd.MoveToNextContextPosition(LogicalDirection.Forward);

            // Find the end position
            elementEnd.MoveToElementEdge(ElementEdge.AfterEnd);

            if (elementEnd.CompareTo(rangeEnd) > 0)
            {
                isPartial = true;
            }

            return isPartial;
        }
        // -------------------------------------------------------------
        //
        // Private Methods
        //
        // -------------------------------------------------------------

        #region Private Methods

        // .............................................................
        //
        // Serialization
        //
        // .............................................................

        /// <summary>
        /// This function serializes text segment formed by rangeStart and rangeEnd to valid xml using xmlWriter.
        /// </summary>        
        /// <SecurityNote>
        /// To mask the security exception from XamlWriter.Save in partial trust case, 
        /// this function checks if the current call stack has the all clipboard permission.
        /// </SecurityNote>
        private static void WriteXamlTextSegment(XmlWriter xmlWriter, ITextPointer rangeStart, ITextPointer rangeEnd, XamlTypeMapper xamlTypeMapper, ref int elementLevel, WpfPayload wpfPayload, bool ignoreWriteHyperlinkEnd, List<int> ignoreList, bool preserveTextElements)
        {
            // Special case for pure text selection - we need a Run wrapper for it.
            if (elementLevel == EmptyDocumentDepth && typeof(Run).IsAssignableFrom(rangeStart.ParentType))
            {
                elementLevel++;
                xmlWriter.WriteStartElement(typeof(Run).Name);
            }

            // Create text navigator for reading the range's content
            ITextPointer textReader = rangeStart.CreatePointer();

            // Exclude last opening tag from serialization - we don't need to create extra element
            // is cases when we have whole paragraphs/cells selected.
            // NOTE: We do this slightly differently than in TextRangeEdit.AdjustRangeEnd, where we use normalization for adjusted position.
            // In this case normalized position does not work, because we need to keep information about crossed paragraph boundary.
            while (rangeEnd.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.ElementStart)
            {
                rangeEnd = rangeEnd.GetNextContextPosition(LogicalDirection.Backward);
            }

            // Write the range internal contents
            while (textReader.CompareTo(rangeEnd) < 0)
            {
                TextPointerContext runType = textReader.GetPointerContext(LogicalDirection.Forward);

                switch (runType)
                {
                    case TextPointerContext.ElementStart:
                        TextElement nextElement = (TextElement)textReader.GetAdjacentElement(LogicalDirection.Forward);
                        if (nextElement is Hyperlink)
                        {
                            // Don't write Hyperlink start element if Hyperlink is invalid
                            // in case of having a UiElement except Image or stated the range end
                            // position before the end position of the Hyperlink.
                            if (IsHyperlinkInvalid(textReader, rangeEnd))
                            {
                                ignoreWriteHyperlinkEnd = true;
                                textReader.MoveToNextContextPosition(LogicalDirection.Forward);

                                continue;
                            }
                        }
                        else if (nextElement != null)
                        {
                            // 

                            
                            TextElementEditingBehaviorAttribute att = (TextElementEditingBehaviorAttribute)Attribute.GetCustomAttribute(nextElement.GetType(), typeof(TextElementEditingBehaviorAttribute));
                            if (att != null && !att.IsTypographicOnly)
                            {
                                if (IsPartialNonTypographic(textReader, rangeEnd))
                                {
                                    // Add pointer to ignore list
                                    ITextPointer ptr = textReader.CreatePointer();
                                    ptr.MoveToElementEdge(ElementEdge.BeforeEnd);
                                    ignoreList.Add(ptr.Offset);

                                    textReader.MoveToNextContextPosition(LogicalDirection.Forward);

                                    continue;
                                }
                            }
                        }

                        elementLevel++;
                        textReader.MoveToNextContextPosition(LogicalDirection.Forward);
                        WriteStartXamlElement(/*range:*/null, textReader, xmlWriter, xamlTypeMapper, /*reduceElement:*/wpfPayload == null, preserveTextElements);

                        break;

                    case TextPointerContext.ElementEnd:
                        // Don't write Hyperlink end element if Hyperlink include the invalid
                        // in case of having a UiElement except Image or stated the range end
                        // before the end position of the Hyperlink or Hyperlink opening tag is 
                        // skipped from WriteOpeningTags by selecting of the partial of Hyperlink.
                        if (ignoreWriteHyperlinkEnd && (textReader.GetAdjacentElement(LogicalDirection.Forward) is Hyperlink))
                        {
                            // Reset the flag to keep walk up the next Hyperlink tag
                            ignoreWriteHyperlinkEnd = false;
                            textReader.MoveToNextContextPosition(LogicalDirection.Forward);
                            
                            continue;
                        }

                        // Check the ignore list
                        ITextPointer endPointer = textReader.CreatePointer();
                        endPointer.MoveToElementEdge(ElementEdge.BeforeEnd);  // 
                        if (ignoreList.Contains(endPointer.Offset))
                        {
                            ignoreList.Remove(endPointer.Offset);
                            textReader.MoveToNextContextPosition(LogicalDirection.Forward);

                            continue;
                        }

                        elementLevel--;
                        if (TextSchema.IsBreak(textReader.ParentType))
                        {
                            // For LineBreak, etc. use empty element syntax
                            xmlWriter.WriteEndElement();
                        }
                        else
                        {   // 
                            // For all other textelements use explicit closing tag.
                            xmlWriter.WriteFullEndElement();
                        }
                        textReader.MoveToNextContextPosition(LogicalDirection.Forward);
                        break;

                    case TextPointerContext.Text:
                        int textLength = textReader.GetTextRunLength(LogicalDirection.Forward);
                        char[] text = new Char[textLength];

                        textLength = TextPointerBase.GetTextWithLimit(textReader, LogicalDirection.Forward, text, 0, textLength, rangeEnd);

                        // XmlWriter will throw an ArgumentException if text contains
                        // any invalid surrogates, so strip them out now.
                        textLength = StripInvalidSurrogateChars(text, textLength);

                        xmlWriter.WriteChars(text, 0, textLength);
                        textReader.MoveToNextContextPosition(LogicalDirection.Forward);
                        break;

                    case TextPointerContext.EmbeddedElement:
                        object embeddedObject = textReader.GetAdjacentElement(LogicalDirection.Forward);
                        textReader.MoveToNextContextPosition(LogicalDirection.Forward);

                        WriteEmbeddedObject(embeddedObject, xmlWriter, wpfPayload);
                        break;

                    default:
                        Invariant.Assert(false, "unexpected value of runType");
                        textReader.MoveToNextContextPosition(LogicalDirection.Forward);
                        break;
                }
            }
        }
Пример #34
0
        // Token: 0x06002C1F RID: 11295 RVA: 0x000C8584 File Offset: 0x000C6784
        private static bool xGapAwareScan(DocumentSequenceTextPointer thisTp, int distance)
        {
            ChildDocumentBlock childDocumentBlock = thisTp.ChildBlock;
            bool         flag        = true;
            ITextPointer textPointer = thisTp.ChildPointer;

            if (textPointer == null)
            {
                flag        = false;
                textPointer = thisTp.ChildPointer.CreatePointer();
            }
            LogicalDirection logicalDirection = (distance > 0) ? LogicalDirection.Forward : LogicalDirection.Backward;

            distance = Math.Abs(distance);
            while (distance > 0)
            {
                switch (textPointer.GetPointerContext(logicalDirection))
                {
                case TextPointerContext.None:
                    if ((childDocumentBlock.IsHead && logicalDirection == LogicalDirection.Backward) || (childDocumentBlock.IsTail && logicalDirection == LogicalDirection.Forward))
                    {
                        return(false);
                    }
                    childDocumentBlock = ((logicalDirection == LogicalDirection.Forward) ? childDocumentBlock.NextBlock : childDocumentBlock.PreviousBlock);
                    textPointer        = ((logicalDirection == LogicalDirection.Forward) ? childDocumentBlock.ChildContainer.Start.CreatePointer(textPointer.LogicalDirection) : childDocumentBlock.ChildContainer.End.CreatePointer(textPointer.LogicalDirection));
                    break;

                case TextPointerContext.Text:
                {
                    int textRunLength = textPointer.GetTextRunLength(logicalDirection);
                    int num           = (textRunLength < distance) ? textRunLength : distance;
                    distance -= num;
                    if (logicalDirection == LogicalDirection.Backward)
                    {
                        num *= -1;
                    }
                    textPointer.MoveByOffset(num);
                    break;
                }

                case TextPointerContext.EmbeddedElement:
                    textPointer.MoveToNextContextPosition(logicalDirection);
                    distance--;
                    break;

                case TextPointerContext.ElementStart:
                    textPointer.MoveToNextContextPosition(logicalDirection);
                    distance--;
                    break;

                case TextPointerContext.ElementEnd:
                    textPointer.MoveToNextContextPosition(logicalDirection);
                    distance--;
                    break;
                }
            }
            thisTp.ChildBlock = childDocumentBlock;
            if (flag)
            {
                thisTp.ChildPointer = textPointer;
            }
            else
            {
                thisTp.ChildPointer = textPointer.CreatePointer();
            }
            return(true);
        }
Пример #35
0
            // Returns true if pointer preceeds an Inline start or end edge. 
            private bool IsAdjacentToFormatElement(ITextPointer pointer)
            { 
                TextPointerContext context; 
                bool isAdjacentToFormatElement;
 
                isAdjacentToFormatElement = false;

                context = pointer.GetPointerContext(LogicalDirection.Forward);
 
                if (context == TextPointerContext.ElementStart &&
                    TextSchema.IsFormattingType(pointer.GetElementType(LogicalDirection.Forward))) 
                { 
                    isAdjacentToFormatElement = true;
                } 
                else if (context == TextPointerContext.ElementEnd &&
                         TextSchema.IsFormattingType(pointer.ParentType))
                {
                    isAdjacentToFormatElement = true; 
                }
 
                return isAdjacentToFormatElement; 
            }
Пример #36
0
        private void ExpandToWordBreakAndContext(ITextPointer position, LogicalDirection direction, XmlLanguage language,
            out ITextPointer contentPosition, out ITextPointer contextPosition) 
        {
            ITextPointer start; 
            ITextPointer end; 
            ITextPointer outwardPosition;
            ITextPointer inwardPosition; 
            TextMap textMap;
            ArrayList segments;
            SpellerInterop.STextRange sTextRange;
            LogicalDirection inwardDirection; 
            int i;
 
            contentPosition = position; 
            contextPosition = position;
 
            if (position.GetPointerContext(direction) == TextPointerContext.None)
            {
                // There is no following context, we're at document start/end.
                return; 
            }
 
            // Disable spell checking functionality since we're only 
            // interested in word breaks here.  This greatly cuts down
            // the engine's workload. 
            _spellerInterop.SetContextOption("IsSpellChecking", false);

            //
            // Build an array of wordbreak offsets surrounding the position. 
            //
 
            // 1. Search outward, into surrounding text.  We need MinWordBreaksForContext 
            // word breaks to handle multi-word errors.
            outwardPosition = SearchForWordBreaks(position, direction, language, MinWordBreaksForContext, true /* stopOnError */); 

            // 2. Search inward, towards content.  We just need one word break inward.
            inwardDirection = direction == LogicalDirection.Forward ? LogicalDirection.Backward : LogicalDirection.Forward;
            inwardPosition = SearchForWordBreaks(position, inwardDirection, language, 1, false /* stopOnError */); 

            // Get combined word breaks.  This may not be the same as we calculated 
            // in two parts above, since we don't know yet whether or not position is 
            // on a word break.
            if (direction == LogicalDirection.Backward) 
            {
                start = outwardPosition;
                end = inwardPosition;
            } 
            else
            { 
                start = inwardPosition; 
                end = outwardPosition;
            } 
            textMap = new TextMap(start, end, position, position);
            segments = new ArrayList(MinWordBreaksForContext + 1);
            _spellerInterop.EnumTextSegments(textMap.Text, textMap.TextLength, null,
                new SpellerInterop.EnumTextSegmentsCallback(ExpandToWordBreakCallback), segments); 

            // 
            // Use our table of word breaks to calculate context and content positions. 
            //
            if (segments.Count == 0) 
            {
                // No segments.  This can happen if position is surrounded by
                // nothing but white space.  We've already initialized contentPosition
                // and contextPosition so there's nothing to do. 
            }
            else 
            { 
                int leftWordBreak;
                int rightWordBreak; 
                int contentOffset;
                int contextOffset;

                // Figure out where position lives in the segment list. 
                i = FindPositionInSegmentList(textMap, direction, segments, out leftWordBreak, out rightWordBreak);
 
                // contentPosition should be an edge on the segment we found. 
                if (direction == LogicalDirection.Backward)
                { 
                    contentOffset = textMap.ContentStartOffset == rightWordBreak ? rightWordBreak : leftWordBreak;
                }
                else
                { 
                    contentOffset = textMap.ContentStartOffset == leftWordBreak ? leftWordBreak : rightWordBreak;
                } 
                contentPosition = textMap.MapOffsetToPosition(contentOffset); 

                // contextPosition should be MinWordBreaksForContext - 1 words away. 
                if (direction == LogicalDirection.Backward)
                {
                    i -= (MinWordBreaksForContext - 1);
                    sTextRange = (SpellerInterop.STextRange)segments[Math.Max(i, 0)]; 
                    // We might actually follow contentOffset if we're at the document edge.
                    // Don't let that happen. 
                    contextOffset = Math.Min(sTextRange.Start, contentOffset); 
                }
                else 
                {
                    i += MinWordBreaksForContext;
                    sTextRange = (SpellerInterop.STextRange)segments[Math.Min(i, segments.Count-1)];
                    // We might actually preceed contentOffset if we're at the document edge. 
                    // Don't let that happen.
                    contextOffset = Math.Max(sTextRange.Start + sTextRange.Length, contentOffset); 
                } 
                contextPosition = textMap.MapOffsetToPosition(contextOffset);
            } 

            // Final fixup: if the dirty range covers only formatting (which is not passed
            // to the speller engine) then we might actually "expand" in the wrong
            // direction, since the TextMap will jump over formatting. 
            // Backup if necessary.
            if (direction == LogicalDirection.Backward) 
            { 
                if (position.CompareTo(contentPosition) < 0)
                { 
                    contentPosition = position;
                }
                if (position.CompareTo(contextPosition) < 0)
                { 
                    contextPosition = position;
                } 
            } 
            else
            { 
                if (position.CompareTo(contentPosition) > 0)
                {
                    contentPosition = position;
                } 
                if (position.CompareTo(contextPosition) > 0)
                { 
                    contextPosition = position; 
                }
            } 
        }
Пример #37
0
        // Part of plain text converter: called from GetTextInternal when processing ElementEnd for Paragraph elements. 
        // Outputs \n - for regular paragraphs and TableRow ends or \t for TableCell ends.
        private static void PlainConvertParagraphEnd(StringBuilder textBuffer, ITextPointer navigator)
        {
            // Check for a special case for a single paragraph within a TableCell 
            // which must be serialized as "\t" character.
            navigator.MoveToElementEdge(ElementEdge.BeforeStart); 
            bool theParagraphIsTheFirstInCollection = navigator.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.ElementStart; 
            navigator.MoveToNextContextPosition(LogicalDirection.Forward);
            navigator.MoveToElementEdge(ElementEdge.AfterEnd); 
            TextPointerContext symbolType = navigator.GetPointerContext(LogicalDirection.Forward);

            if (theParagraphIsTheFirstInCollection && symbolType == TextPointerContext.ElementEnd &&
                typeof(TableCell).IsAssignableFrom(navigator.ParentType)) 
            {
                // This is an end of a table cell 
 
                navigator.MoveToNextContextPosition(LogicalDirection.Forward);
                symbolType = navigator.GetPointerContext(LogicalDirection.Forward); 
                if (symbolType == TextPointerContext.ElementStart)
                {
                    // Next table cell starts after this one. Use '\t' as a cell separator
                    textBuffer.Append('\t'); 
                }
                else 
                { 
                    // This was the last cell in a row. Use '\r\n' as a line separator
                    textBuffer.Append(Environment.NewLine); 
                }
            }
            else
            { 
                // Ordinary paragraph end
                textBuffer.Append(Environment.NewLine); 
            } 
        }
Пример #38
0
        /// <summary>
        /// Retrieves the range of a child object.
        /// </summary>
        /// <param name="childElementProvider">The child element.  A provider should check that the
        /// passed element is a child of the text container, and should throw an
        /// InvalidOperationException if it is not.</param>
        /// <returns>A range that spans the child element.</returns>
        ITextRangeProvider ITextProvider.RangeFromChild(IRawElementProviderSimple childElementProvider)
        {
            if (childElementProvider == null)
            {
                throw new ArgumentNullException("childElementProvider");
            }

            // Retrieve DependencyObject from AutomationElement
            DependencyObject childElement;

            if (_textPeer is TextAutomationPeer)
            {
                childElement = ((TextAutomationPeer)_textPeer).ElementFromProvider(childElementProvider);
            }
            else
            {
                childElement = ((ContentTextAutomationPeer)_textPeer).ElementFromProvider(childElementProvider);
            }

            TextRangeAdaptor range = null;

            if (childElement != null)
            {
                ITextPointer rangeStart = null;
                ITextPointer rangeEnd   = null;

                // Retrieve start and end positions for given element.
                // If element is TextElement, retrieve its Element Start and End positions.
                // If element is UIElement hosted by UIContainer (Inlien of Block),
                // retrieve content Start and End positions of the container.
                // Otherwise scan ITextContainer to find a range for given element.
                if (childElement is TextElement)
                {
                    rangeStart = ((TextElement)childElement).ElementStart;
                    rangeEnd   = ((TextElement)childElement).ElementEnd;
                }
                else
                {
                    DependencyObject parent = LogicalTreeHelper.GetParent(childElement);
                    if (parent is InlineUIContainer || parent is BlockUIContainer)
                    {
                        rangeStart = ((TextElement)parent).ContentStart;
                        rangeEnd   = ((TextElement)parent).ContentEnd;
                    }
                    else
                    {
                        ITextPointer position = _textContainer.Start.CreatePointer();
                        while (position.CompareTo(_textContainer.End) < 0)
                        {
                            TextPointerContext context = position.GetPointerContext(LogicalDirection.Forward);
                            if (context == TextPointerContext.ElementStart)
                            {
                                if (childElement == position.GetAdjacentElement(LogicalDirection.Forward))
                                {
                                    rangeStart = position.CreatePointer(LogicalDirection.Forward);
                                    position.MoveToElementEdge(ElementEdge.AfterEnd);
                                    rangeEnd = position.CreatePointer(LogicalDirection.Backward);
                                    break;
                                }
                            }
                            else if (context == TextPointerContext.EmbeddedElement)
                            {
                                if (childElement == position.GetAdjacentElement(LogicalDirection.Forward))
                                {
                                    rangeStart = position.CreatePointer(LogicalDirection.Forward);
                                    position.MoveToNextContextPosition(LogicalDirection.Forward);
                                    rangeEnd = position.CreatePointer(LogicalDirection.Backward);
                                    break;
                                }
                            }
                            position.MoveToNextContextPosition(LogicalDirection.Forward);
                        }
                    }
                }
                // Create range
                if (rangeStart != null && rangeEnd != null)
                {
                    range = new TextRangeAdaptor(this, rangeStart, rangeEnd, _textPeer);
                }
            }
            if (range == null)
            {
                throw new InvalidOperationException(SR.Get(SRID.TextProvider_InvalidChildElement));
            }
            return(range);
        }
 // Position at row end (immediately before Row closing tag) is a valid stopper for a caret.
 // Editing operations are restricted here (e.g. typing should automatically jump
 // to the following character position.
 // This property identifies such special position.
 internal static bool IsAtRowEnd(ITextPointer thisPosition)
 {
     return typeof(TableRow).IsAssignableFrom(thisPosition.ParentType) &&
            thisPosition.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementEnd &&
            thisPosition.GetPointerContext(LogicalDirection.Backward) != TextPointerContext.ElementStart;
     // Note that only non-empty TableRows are good for insertion positions.
     // Totally empty TableRow is treated as any other incomplete content - not an insertion.
 }
        // Token: 0x060039BC RID: 14780 RVA: 0x00106178 File Offset: 0x00104378
        private static int SetFindTextAndFindTextPositionMap(ITextPointer startPosition, ITextPointer endPosition, ITextPointer navigator, LogicalDirection direction, bool matchLast, char[] findText, int[] findTextPositionMap)
        {
            Invariant.Assert(startPosition.CompareTo(navigator) <= 0);
            Invariant.Assert(endPosition.CompareTo(navigator) >= 0);
            int num  = 0;
            int num2 = 0;

            if (matchLast && num2 == 0)
            {
                findTextPositionMap[findTextPositionMap.Length - 1] = 0;
            }
            while ((matchLast ? startPosition.CompareTo(navigator) : navigator.CompareTo(endPosition)) < 0)
            {
                switch (navigator.GetPointerContext(direction))
                {
                case TextPointerContext.None:
                case TextPointerContext.ElementStart:
                case TextPointerContext.ElementEnd:
                    if (TextFindEngine.IsAdjacentToFormatElement(navigator, direction))
                    {
                        num++;
                    }
                    else if (!matchLast)
                    {
                        findText[num2]            = '\n';
                        findTextPositionMap[num2] = num2 + num;
                        num2++;
                    }
                    else
                    {
                        num2++;
                        findText[findText.Length - num2]            = '\n';
                        findTextPositionMap[findText.Length - num2] = num2 + num;
                    }
                    navigator.MoveToNextContextPosition(direction);
                    break;

                case TextPointerContext.Text:
                {
                    int num3 = navigator.GetTextRunLength(direction);
                    num3 = Math.Min(num3, findText.Length - num2);
                    if (!matchLast)
                    {
                        num3 = Math.Min(num3, navigator.GetOffsetToPosition(endPosition));
                        navigator.GetTextInRun(direction, findText, num2, num3);
                        for (int i = num2; i < num2 + num3; i++)
                        {
                            findTextPositionMap[i] = i + num;
                        }
                    }
                    else
                    {
                        num3 = Math.Min(num3, startPosition.GetOffsetToPosition(navigator));
                        navigator.GetTextInRun(direction, findText, findText.Length - num2 - num3, num3);
                        int num4 = findText.Length - num2 - 1;
                        for (int j = num2; j < num2 + num3; j++)
                        {
                            findTextPositionMap[num4--] = j + num + 1;
                        }
                    }
                    navigator.MoveByOffset(matchLast ? (-num3) : num3);
                    num2 += num3;
                    break;
                }

                case TextPointerContext.EmbeddedElement:
                    if (!matchLast)
                    {
                        findText[num2]            = '';
                        findTextPositionMap[num2] = num2 + num;
                        num2++;
                    }
                    else
                    {
                        num2++;
                        findText[findText.Length - num2]            = '';
                        findTextPositionMap[findText.Length - num2] = num2 + num;
                    }
                    navigator.MoveToNextContextPosition(direction);
                    break;
                }
                if (num2 >= findText.Length)
                {
                    break;
                }
            }
            if (!matchLast)
            {
                if (num2 > 0)
                {
                    findTextPositionMap[num2] = findTextPositionMap[num2 - 1] + 1;
                }
                else
                {
                    findTextPositionMap[0] = 0;
                }
            }
            return(num2);
        }
        // Returns true if pointer is at the start of a paragraph.
        internal static bool IsAtParagraphOrBlockUIContainerStart(ITextPointer pointer)
        {
            // Is pointer at a potential paragraph position?
            if (IsAtPotentialParagraphPosition(pointer))
            {
                return true;
            }

            // Can you find a <Paragraph> start tag looking backwards? 
            // Loop to skip multiple formatting opening tags, never crossing parent element boundary.
            while (pointer.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.ElementStart)
            {
                if (TextSchema.IsParagraphOrBlockUIContainer(pointer.ParentType))
                {
                    return true;
                }
                pointer = pointer.GetNextContextPosition(LogicalDirection.Backward);
            }
            return false;
        }
        // Tests for the presence of a non-mergeable Inline bordering a position.
        // Helper for IsAtNonMergeableInlineEdge.
        private static BorderingElementCategory GetBorderingElementCategory(ITextPointer position, LogicalDirection direction)
        {
            TextPointerContext context = (direction == LogicalDirection.Forward) ? TextPointerContext.ElementEnd : TextPointerContext.ElementStart;
            BorderingElementCategory category;

            if (position.GetPointerContext(direction) != context ||
                !typeof(Inline).IsAssignableFrom(position.ParentType))
            {
                category = BorderingElementCategory.NotScopingInline;
            }
            else if (TextSchema.IsMergeableInline(position.ParentType))
            {
                category = BorderingElementCategory.MergeableScopingInline;
            }
            else
            {
                category = BorderingElementCategory.NonMergeableScopingInline;
            }

            return category;
        }
Пример #43
0
        // GetText handler for text runs.
        private static bool WalkTextRun(ITextPointer navigator, ITextPointer limit, char[] text, int cchReq, ref int charsCopied, UnsafeNativeMethods.TS_RUNINFO[] runInfo, int cRunInfoReq, ref int cRunInfoRcv)
        {
            int runCount;
            int offset;
            bool hitLimit;

            Invariant.Assert(navigator.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text);
            Invariant.Assert(limit == null || navigator.CompareTo(limit) <= 0);

            hitLimit = false;

            if (cchReq > 0)
            {
                runCount = TextPointerBase.GetTextWithLimit(navigator, LogicalDirection.Forward, text, charsCopied, Math.Min(cchReq, text.Length - charsCopied), limit);
                navigator.MoveByOffset(runCount);
                charsCopied += runCount;
                hitLimit = (text.Length == charsCopied) || (limit != null && navigator.CompareTo(limit) == 0);
            }
            else
            {
                // Caller doesn't want text, just run info.
                // Advance the navigator.
                runCount = navigator.GetTextRunLength(LogicalDirection.Forward);
                navigator.MoveToNextContextPosition(LogicalDirection.Forward);

                // If the caller passed in a non-null limit, backup to the limit if
                // we've passed it.
                if (limit != null)
                {
                    if (navigator.CompareTo(limit) >= 0)
                    {
                        offset = limit.GetOffsetToPosition(navigator);
                        Invariant.Assert(offset >= 0 && offset <= runCount, "Bogus offset -- extends past run!");
                        runCount -= offset;
                        navigator.MoveToPosition(limit);
                        hitLimit = true;
                    }
                }
            }

            if (cRunInfoReq > 0 && runCount > 0)
            {
                // Be sure to merge this text run with the previous run, if they are both text runs.
                // (A good robustness fix would be to make cicero handle this, if we ever get the chance.)
                if (cRunInfoRcv > 0 && runInfo[cRunInfoRcv - 1].type == UnsafeNativeMethods.TsRunType.TS_RT_PLAIN)
                {
                    runInfo[cRunInfoRcv - 1].count += runCount;
                }
                else
                {
                    runInfo[cRunInfoRcv].count = runCount;
                    runInfo[cRunInfoRcv].type = UnsafeNativeMethods.TsRunType.TS_RT_PLAIN;
                    cRunInfoRcv++;
                }
            }

            return hitLimit;
        }
        // Tests if a position is between structural symbols where Paragraph is potentially insertable,
        // but not present.
        // Positions in empty list item, table cell or flow document.
        internal static bool IsAtPotentialParagraphPosition(ITextPointer position)
        {
            Type parentType = position.ParentType;
            TextPointerContext backwardContext = position.GetPointerContext(LogicalDirection.Backward);
            TextPointerContext forwardContext = position.GetPointerContext(LogicalDirection.Forward);

            if (backwardContext == TextPointerContext.ElementStart && forwardContext == TextPointerContext.ElementEnd)
            {
                return
                    typeof(ListItem).IsAssignableFrom(parentType) ||
                    typeof(TableCell).IsAssignableFrom(parentType);                    
            }
            else if (backwardContext == TextPointerContext.None && forwardContext == TextPointerContext.None)
            {
                return
                    typeof(FlowDocumentView).IsAssignableFrom(parentType) ||
                    typeof(FlowDocument).IsAssignableFrom(parentType);
            }

            return false;
        }
Пример #45
0
        // GetText handler for Blocks and TableCell to add '\n' or TS_CHAR_REGION.
        private static bool WalkRegionBoundary(ITextPointer navigator, ITextPointer limit, char[] text, int cchReq, ref int charsCopied, UnsafeNativeMethods.TS_RUNINFO[] runInfo, int cRunInfoReq, ref int cRunInfoRcv)
        {
            bool hitLimit;

            Invariant.Assert(navigator.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementStart || navigator.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementEnd);
            Invariant.Assert(limit == null || navigator.CompareTo(limit) <= 0);

            // If the caller passed in a non-null limit, we don't do anything and just return true.
            // we've passed it.
            if (limit != null)
            {
                if (navigator.CompareTo(limit) >= 0)
                {
                    return true;
                }
            }

            hitLimit = false;

            if (cchReq > 0)
            {
                // Add one TS_CHAR_REGION (TableCell) or '\n' (everything else) char.
                char ch = (navigator.GetAdjacentElement(LogicalDirection.Forward) is TableCell) ? UnsafeNativeMethods.TS_CHAR_REGION : '\n';
                text[charsCopied] = ch;
                navigator.MoveByOffset(1);
                charsCopied += 1;
                hitLimit = (text.Length == charsCopied) || (limit != null && navigator.CompareTo(limit) == 0);
            }
            else
            {
                // Caller doesn't want text, just run info.
                // Advance the navigator.
                // Add one TS_CHAR_REGION char.
                navigator.MoveByOffset(1);
            }

            if (cRunInfoReq > 0)
            {
                // Be sure to merge this text run with the previous run, if they are both text runs.
                // (A good robustness fix would be to make cicero handle this, if we ever get the chance.)
                if (cRunInfoRcv > 0 && runInfo[cRunInfoRcv - 1].type == UnsafeNativeMethods.TsRunType.TS_RT_PLAIN)
                {
                    runInfo[cRunInfoRcv - 1].count += 1;
                }
                else
                {
                    runInfo[cRunInfoRcv].count = 1;
                    runInfo[cRunInfoRcv].type = UnsafeNativeMethods.TsRunType.TS_RT_PLAIN;
                    cRunInfoRcv++;
                }
            }

            return hitLimit;
        }
        // Tests if position is before the first Table element in a collection of Blocks at that level.
        // We treat this as a potential insertion position to allow editing operations before the table.
        // This property identifies such a position.
        internal static bool IsBeforeFirstTable(ITextPointer position)
        {
            TextPointerContext forwardContext = position.GetPointerContext(LogicalDirection.Forward);
            TextPointerContext backwardContext = position.GetPointerContext(LogicalDirection.Backward);

            return (forwardContext == TextPointerContext.ElementStart &&
                    (backwardContext == TextPointerContext.ElementStart || backwardContext == TextPointerContext.None) &&
                    typeof(Table).IsAssignableFrom(position.GetElementType(LogicalDirection.Forward)));
        }
Пример #47
0
        // Normalizes a range:
        //
        // -The start position is advanced over all element edges not visible
        //  to the IMEs.
        // -Start and end positions are moved to insertion positions.
        private void GetNormalizedRange(int startCharOffset, int endCharOffset, out ITextPointer start, out ITextPointer end)
        {
            start = CreatePointerAtCharOffset(startCharOffset, LogicalDirection.Forward);
            end = (startCharOffset == endCharOffset) ? start : CreatePointerAtCharOffset(endCharOffset, LogicalDirection.Backward);

            // Skip over hidden element edges.
            while (start.CompareTo(end) < 0)
            {
                TextPointerContext forwardContext = start.GetPointerContext(LogicalDirection.Forward);

                if (forwardContext == TextPointerContext.ElementStart)
                {
                    TextElement element = start.GetAdjacentElement(LogicalDirection.Forward) as TextElement;

                    if (element == null)
                        break;
                    if (element.IMELeftEdgeCharCount != 0)
                        break;
                }
                else if (forwardContext != TextPointerContext.ElementEnd)
                {
                    break;
                }

                start.MoveToNextContextPosition(LogicalDirection.Forward);
            }

            // Move to insertion positions.
            // If the positions are already adjacent to text, we must respect
            // the IME's decision in regards to exact placement.
            // MoveToInsertionPosition will skip over surrogates and combining
            // marks, but the IME needs fine-grained control over these positions.

            if (start.CompareTo(end) == 0)
            {
                start = start.GetFormatNormalizedPosition(LogicalDirection.Backward);
                end = start;
            }
            else
            {
                start = start.GetFormatNormalizedPosition(LogicalDirection.Backward);
                end = end.GetFormatNormalizedPosition(LogicalDirection.Backward);
            }
        }
 internal static bool IsAtBlockUIContainerStart(ITextPointer position)
 {
     return IsInBlockUIContainer(position) &&
         position.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.ElementStart;
 }
Пример #49
0
        //......................................................
        //
        //  Selection Building With Mouse
        //
        //......................................................

        // Moves the selection to the mouse cursor position.
        // If the cursor is facing a UIElement, select the UIElement.
        // Sets new selection anchor to a given cursorPosition.
        private void MoveSelectionByMouse(ITextPointer cursorPosition, Point cursorMousePoint)
        {
            ITextSelection thisSelection = (ITextSelection)this;

            if (this.TextView == null)
            {
                return;
            }
            Invariant.Assert(this.TextView.IsValid); // We just checked RenderScope. We'll use TextView below

            ITextPointer movingPosition = null;

            if (cursorPosition.GetPointerContext(cursorPosition.LogicalDirection) == TextPointerContext.EmbeddedElement)
            {
                Rect objectEdgeRect = this.TextView.GetRectangleFromTextPosition(cursorPosition);

                // Check for embedded object.
                // If the click happend inside of it we need to select it as a whole, when content is not read-only.
                if (!_textEditor.IsReadOnly && ShouldSelectEmbeddedObject(cursorPosition, cursorMousePoint, objectEdgeRect))
                {
                    movingPosition = cursorPosition.GetNextContextPosition(cursorPosition.LogicalDirection);
                }
            }

            // Move selection to this position
            if (movingPosition == null)
            {
                thisSelection.SetCaretToPosition(cursorPosition, cursorPosition.LogicalDirection, /*allowStopAtLineEnd:*/true, /*allowStopNearSpace:*/false);
            }
            else
            {
                thisSelection.Select(cursorPosition, movingPosition);
            }
        }
 internal static bool IsAtBlockUIContainerEnd(ITextPointer position)
 {
     return IsInBlockUIContainer(position) &&
         position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementEnd;
 }
        // Worker implementing IsAtPotentialRunPosition(position) method.
        // It is used for testing whether an empty Run element is at potential run potision.
        // For this purpose the method is supposed to be called with
        // backwardPosition==run.ElementStart and forwardPosition==run.ElementEnd.
        private static bool IsAtPotentialRunPosition(ITextPointer backwardPosition, ITextPointer forwardPosition)
        {
            Invariant.Assert(backwardPosition.HasEqualScope(forwardPosition));

            if (TextSchema.IsValidChild(/*position*/backwardPosition, /*childType*/typeof(Run)))
            {
                Type forwardType = forwardPosition.GetElementType(LogicalDirection.Forward);
                Type backwardType = backwardPosition.GetElementType(LogicalDirection.Backward);
                if (forwardType != null && backwardType != null)
                {
                    TextPointerContext forwardContext = forwardPosition.GetPointerContext(LogicalDirection.Forward);
                    TextPointerContext backwardContext = backwardPosition.GetPointerContext(LogicalDirection.Backward);
                    if (// Test if the position inside empty Paragraph or Span
                        backwardContext == TextPointerContext.ElementStart &&
                        forwardContext == TextPointerContext.ElementEnd
                        ||
                        // Test if the position between opening tag and an embedded object
                        backwardContext == TextPointerContext.ElementStart && TextSchema.IsNonFormattingInline(forwardType) &&
                        !IsAtNonMergeableInlineStart(backwardPosition)
                        ||
                        // Test if the position between an embedded object and a closing tag
                        forwardContext == TextPointerContext.ElementEnd && TextSchema.IsNonFormattingInline(backwardType) &&
                        !IsAtNonMergeableInlineEnd(forwardPosition)
                        ||
                        // Test if the position between two embedded objects
                        backwardContext == TextPointerContext.ElementEnd && forwardContext == TextPointerContext.ElementStart &&
                        TextSchema.IsNonFormattingInline(backwardType) && TextSchema.IsNonFormattingInline(forwardType)
                        ||
                        // Test if the position is adjacent to a non-mergeable inline (Hyperlink).
                        backwardContext == TextPointerContext.ElementEnd &&
                        typeof(Inline).IsAssignableFrom(backwardType) && !TextSchema.IsMergeableInline(backwardType) && !typeof(Run).IsAssignableFrom(forwardType) &&
                        (forwardContext != TextPointerContext.ElementEnd || !IsAtNonMergeableInlineEnd(forwardPosition))
                        ||
                        forwardContext == TextPointerContext.ElementStart &&
                        typeof(Inline).IsAssignableFrom(forwardType) && !TextSchema.IsMergeableInline(forwardType) && !typeof(Run).IsAssignableFrom(backwardType) &&
                        (backwardContext != TextPointerContext.ElementStart || !IsAtNonMergeableInlineStart(backwardPosition))
                        )
                    {
                        return true;
                    }
                }
            }

            return false;
        }
Пример #52
0
        /// <summary>
        /// Determine paragraph type at the current TextPointer and
        /// create it. Only ListItem elements are considered. Any other
        /// content is skipped.
        /// </summary>
        /// <param name="textPointer">
        /// TextPointer at which paragraph is to be created
        /// </param>
        /// <param name="fEmptyOk">
        /// True if empty paragraph is acceptable
        /// </param>
        /// <returns>
        /// BaseParagraph that was created
        /// </returns>
        protected override BaseParagraph GetParagraph(ITextPointer textPointer, bool fEmptyOk)
        {
            Invariant.Assert(textPointer is TextPointer);

            BaseParagraph paragraph = null;

            while (paragraph == null)
            {
                TextPointerContext runType = textPointer.GetPointerContext(LogicalDirection.Forward);
                if (runType == TextPointerContext.ElementStart)
                {
                    TextElement element = ((TextPointer)textPointer).GetAdjacentElementFromOuterPosition(LogicalDirection.Forward);
                    if (element is ListItem)
                    {
                        //      Need to handle visibility collapsed.
                        //Visibility visibility = Retriever.Visibility(treePtr.CPPtr.Element);
                        //if (visibility != Visibility.Collapsed)
                        //{
                        //    para = new
                        //}
                        //else skip the element
                        paragraph = new ListItemParagraph(element, StructuralCache);
                        break;
                    }
                    else if (element is List)
                    {
                        //      Need to handle visibility collapsed.
                        //Visibility visibility = Retriever.Visibility(treePtr.CPPtr.Element);
                        //if (visibility != Visibility.Collapsed)
                        //{
                        //    para = new
                        //}
                        //else skip the element
                        paragraph = new ListParagraph(element, StructuralCache);
                        break;
                    }
                    // Skip all elements, which are not valid list item children
                    if (((TextPointer)textPointer).IsFrozen)
                    {
                        // Need to clone TextPointer before moving it.
                        textPointer = textPointer.CreatePointer();
                    }
                    textPointer.MoveToPosition(element.ElementEnd);
                }
                else if (runType == TextPointerContext.ElementEnd)
                {
                    // End of list, if the same as Owner of associated element
                    // Skip content otherwise
                    if (Element == ((TextPointer)textPointer).Parent)
                    {
                        break;
                    }
                    if (((TextPointer)textPointer).IsFrozen)
                    {
                        // Need to clone TextPointer before moving it.
                        textPointer = textPointer.CreatePointer();
                    }
                    textPointer.MoveToNextContextPosition(LogicalDirection.Forward);
                }
                else
                {
                    // Skip content
                    if (((TextPointer)textPointer).IsFrozen)
                    {
                        // Need to clone TextPointer before moving it.
                        textPointer = textPointer.CreatePointer();
                    }
                    textPointer.MoveToNextContextPosition(LogicalDirection.Forward);
                }
            }

            if (paragraph != null)
            {
                StructuralCache.CurrentFormatContext.DependentMax = (TextPointer)textPointer;
            }

            return(paragraph);
        }
Пример #53
0
        /// <summary>
        /// Set the find text content from reading the text on the current text position.
        /// </summary>
        /// <returns>
        /// Returns the number of characters actually loaded into the findText array.
        /// </returns>
        private static int SetFindTextAndFindTextPositionMap(
            ITextPointer startPosition,
            ITextPointer endPosition,
            ITextPointer navigator,
            LogicalDirection direction,
            bool matchLast,
            char[] findText,
            int[] findTextPositionMap)
        {
            Invariant.Assert(startPosition.CompareTo(navigator) <= 0);
            Invariant.Assert(endPosition.CompareTo(navigator) >= 0);

            int runCount;
            int inlineCount    = 0;
            int findTextLength = 0;

            // Set the first offset which is zero on TextBufferSize + 1 location of
            // the text position map in case of the backward searching
            if (matchLast && findTextLength == 0)
            {
                findTextPositionMap[findTextPositionMap.Length - 1] = 0;
            }

            while ((matchLast ? startPosition.CompareTo(navigator) : navigator.CompareTo(endPosition)) < 0)
            {
                switch (navigator.GetPointerContext(direction))
                {
                case TextPointerContext.Text:
                    runCount = navigator.GetTextRunLength(direction);
                    runCount = Math.Min(runCount, findText.Length - findTextLength);

                    if (!matchLast)
                    {
                        runCount = Math.Min(runCount, navigator.GetOffsetToPosition(endPosition));
                        navigator.GetTextInRun(direction, findText, findTextLength, runCount);

                        for (int i = findTextLength; i < findTextLength + runCount; i++)
                        {
                            findTextPositionMap[i] = i + inlineCount;
                        }
                    }
                    else
                    {
                        runCount = Math.Min(runCount, startPosition.GetOffsetToPosition(navigator));
                        navigator.GetTextInRun(
                            direction,
                            findText,
                            findText.Length - findTextLength - runCount,
                            runCount);

                        // Set the text offest for the amount of runCount from the last index
                        // of text position map
                        int mapIndex = findText.Length - findTextLength - 1;
                        for (int i = findTextLength; i < findTextLength + runCount; i++)
                        {
                            findTextPositionMap[mapIndex--] = i + inlineCount + 1;
                        }
                    }

                    // Move the navigator position for the amount of runCount
                    navigator.MoveByOffset(matchLast ? -runCount : runCount);
                    findTextLength += runCount;
                    break;

                case TextPointerContext.None:
                case TextPointerContext.ElementStart:
                case TextPointerContext.ElementEnd:
                    if (IsAdjacentToFormatElement(navigator, direction))
                    {
                        // Filter out formatting tags since find text content is plain.
                        inlineCount++;
                    }
                    else
                    {
                        if (!matchLast)
                        {
                            // Stick in a line break to account for the block element.
                            findText[findTextLength]            = '\n';
                            findTextPositionMap[findTextLength] = findTextLength + inlineCount;
                            findTextLength++;
                        }
                        else
                        {
                            // Increse the find text length first since adding text and map reversely
                            findTextLength++;

                            // Stick in a line break to account for the block element and
                            // add text offset on the last index of text position map
                            findText[findText.Length - findTextLength]            = '\n';
                            findTextPositionMap[findText.Length - findTextLength] = findTextLength + inlineCount;
                        }
                    }

                    navigator.MoveToNextContextPosition(direction);
                    break;

                case TextPointerContext.EmbeddedElement:
                    if (!matchLast)
                    {
                        findText[findTextLength]            = '\xf8ff'; // Unicode private use.
                        findTextPositionMap[findTextLength] = findTextLength + inlineCount;
                        findTextLength++;
                    }
                    else
                    {
                        // Increse the find text length first since adding text and map reversely
                        findTextLength++;

                        // Set the private unicode value and text offset
                        findText[findText.Length - findTextLength]            = '\xf8ff';
                        findTextPositionMap[findText.Length - findTextLength] = findTextLength + inlineCount;
                    }

                    navigator.MoveToNextContextPosition(direction);
                    break;
                }

                if (findTextLength >= findText.Length)
                {
                    break;
                }
            }

            // Complete the adding the find text position to the position map for only the forward finding.
            // The backward finding(matchLast) is already added initially as the zero offset at the end of
            // text position map.
            if (!matchLast)
            {
                if (findTextLength > 0)
                {
                    findTextPositionMap[findTextLength] = findTextPositionMap[findTextLength - 1] + 1;
                }
                else
                {
                    findTextPositionMap[0] = 0;
                }
            }

            return(findTextLength);
        }
Пример #54
0
        /// <summary>
        /// Retrieves the height and offset, in pixels, of the edge of 
        /// the object/character represented by position.
        /// </summary>
        /// <param name="position">
        /// Position of an object/character.
        /// </param>
        /// <param name="transform">
        /// Transform to be applied to returned rect
        /// </param>
        /// <returns>
        /// The height, in pixels, of the edge of the object/character 
        /// represented by position.
        /// </returns>
        /// <exception cref="System.InvalidOperationException">
        /// Throws InvalidOperationException if IsValid is false.
        /// If IsValid returns false, Validate method must be called before 
        /// calling this method.
        /// </exception>
        /// <remarks>
        /// Rect.Width is always 0.
        /// Output parameter Transform is always Identity. It is not expected that editing scenarios 
        /// will require speparate transform with raw rectangle for this case.
        /// If the document is empty, then this method returns the expected
        /// height of a character, if placed at the specified position.
        /// </remarks>
        internal override Rect GetRawRectangleFromTextPosition(ITextPointer position, out Transform transform)
        {
#if DEBUG
            DocumentsTrace.FixedTextOM.TextView.Trace(string.Format("GetRectFromTextPosition {0}, {1}", (FixedTextPointer)position, position.LogicalDirection));
#endif

            FixedTextPointer ftp = Container.VerifyPosition(position);
            FixedPosition fixedp;

            // need a default caret size, otherwise infinite corners cause text editor and MultiPageTextView problems.
            // Initialize transform to Identity. This function always returns Identity transform.
            Rect designRect = new Rect(0, 0, 0, 10);
            transform = Transform.Identity;

            Debug.Assert(ftp != null);
            if (ftp.FlowPosition.IsBoundary)
            {
                if  (!_GetFirstFixedPosition(ftp, out fixedp))
                {
                    return designRect;
                }
            }

            else if (!_GetFixedPosition(ftp, out fixedp))
            {
                //
                // This is the start/end element, we need to find out the next element and return the next element
                // start offset/height.
                //
                if (position.GetPointerContext(LogicalDirection.Forward) != TextPointerContext.None)
                {
                    ITextPointer psNext = position.CreatePointer(1);
                    FixedTextPointer ftpNext = Container.VerifyPosition(psNext);
                    if (!_GetFixedPosition(ftpNext, out fixedp))
                    {
                        return designRect;
                    }
                }
                else
                {
                    return designRect;
                }
                
            }

            if (fixedp.Page != this.PageIndex)
            {
                return designRect;
            }

            DependencyObject element = this.FixedPage.GetElement(fixedp.Node);
            if (element is Glyphs)
            {
                Glyphs g = (Glyphs)element;
                designRect = _GetGlyphRunDesignRect(g, fixedp.Offset, fixedp.Offset);
                // need to do transform
                GeneralTransform tran = g.TransformToAncestor(this.FixedPage);
                designRect = _GetTransformedCaretRect(tran, designRect.TopLeft, designRect.Height);
            }
            else if (element is Image)
            {
                Image image = (Image)element;
                GeneralTransform tran = image.TransformToAncestor(this.FixedPage);
                Point offset = new Point(0, 0);
                if (fixedp.Offset > 0)
                {
                    offset.X += image.ActualWidth;
                }
                designRect = _GetTransformedCaretRect(tran, offset, image.ActualHeight);
            }
            else if (element is Path)
            {
                Path path = (Path)element;
                GeneralTransform tran = path.TransformToAncestor(this.FixedPage);
                Rect bounds = path.Data.Bounds;
                Point offset = bounds.TopLeft;
                if (fixedp.Offset > 0)
                {
                    offset.X += bounds.Width;
                }
                designRect = _GetTransformedCaretRect(tran, offset, bounds.Height);
            }

            return designRect;
        }
        /// <summary>
        /// Return true if Hyperlink range is invalid.
        /// Hyperlink is invalid if it include a UiElement except Image or the range end position
        /// is stated before the end position of hyperlink.
        /// This must be called before Hyperlink start element position.
        /// </summary>        
        private static bool IsHyperlinkInvalid(ITextPointer textReader, ITextPointer rangeEnd)
        {
            // TextRead must be on the position before the element start position of Hyperlink
            Invariant.Assert(textReader.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementStart);
            Invariant.Assert(typeof(Hyperlink).IsAssignableFrom(textReader.GetElementType(LogicalDirection.Forward)));

            bool hyperlinkInvalid = false;

            // Get the forward adjacent element and cast Hyperlink hardly since it must be Hyperlink
            Hyperlink hyperlink = (Hyperlink)textReader.GetAdjacentElement(LogicalDirection.Forward);

            ITextPointer hyperlinkNavigation = textReader.CreatePointer();
            ITextPointer hyperlinkEnd = textReader.CreatePointer();

            hyperlinkEnd.MoveToNextContextPosition(LogicalDirection.Forward);

            // Find the hyperlink end position
            hyperlinkEnd.MoveToElementEdge(ElementEdge.AfterEnd);

            // Hyperlink end position is stated after the range end position.
            if (hyperlinkEnd.CompareTo(rangeEnd) > 0)
            {
                hyperlinkInvalid = true;
            }
            else
            {
                // Check whether the hyperlink having a UiElement except Image until hyperlink end position
                while (hyperlinkNavigation.CompareTo(hyperlinkEnd) < 0)
                {
                    InlineUIContainer inlineUIContainer = hyperlinkNavigation.GetAdjacentElement(LogicalDirection.Forward) as InlineUIContainer;
                    if (inlineUIContainer != null && !(inlineUIContainer.Child is Image))
                    {
                        hyperlinkInvalid = true;
                        break;
                    }

                    hyperlinkNavigation.MoveToNextContextPosition(LogicalDirection.Forward);
                }
            }

            return hyperlinkInvalid;
        }
Пример #56
0
        /// <summary> 
        /// Determine paragraph type at the current TextPointer and
        /// create it. Only ListItem elements are considered. Any other 
        /// content is skipped.
        /// </summary>
        /// <param name="textPointer">
        /// TextPointer at which paragraph is to be created 
        /// </param>
        /// <param name="fEmptyOk"> 
        /// True if empty paragraph is acceptable 
        /// </param>
        /// <returns> 
        /// BaseParagraph that was created
        /// </returns>
        protected override BaseParagraph GetParagraph(ITextPointer textPointer, bool fEmptyOk)
        { 
            Invariant.Assert(textPointer is TextPointer);
 
            BaseParagraph paragraph = null; 

            while (paragraph == null) 
            {
                TextPointerContext runType = textPointer.GetPointerContext(LogicalDirection.Forward);
                if (runType == TextPointerContext.ElementStart)
                { 
                    TextElement element = ((TextPointer)textPointer).GetAdjacentElementFromOuterPosition(LogicalDirection.Forward);
                    if (element is ListItem) 
                    { 
                        //
 



 

 
                        paragraph = new ListItemParagraph(element, StructuralCache); 
                        break;
                    } 
                    else if (element is List)
                    {
                        //
 

 
 

 

                        paragraph = new ListParagraph(element, StructuralCache);
                        break;
                    } 
                    // Skip all elements, which are not valid list item children
                    if (((TextPointer)textPointer).IsFrozen) 
                    { 
                        // Need to clone TextPointer before moving it.
                        textPointer = textPointer.CreatePointer(); 
                    }
                    textPointer.MoveToPosition(element.ElementEnd);
                }
                else if (runType == TextPointerContext.ElementEnd) 
                {
                    // End of list, if the same as Owner of associated element 
                    // Skip content otherwise 
                    if (Element == ((TextPointer)textPointer).Parent)
                    { 
                        break;
                    }
                    if (((TextPointer)textPointer).IsFrozen)
                    { 
                        // Need to clone TextPointer before moving it.
                        textPointer = textPointer.CreatePointer(); 
                    } 
                    textPointer.MoveToNextContextPosition(LogicalDirection.Forward);
                } 
                else
                {
                    // Skip content
                    if (((TextPointer)textPointer).IsFrozen) 
                    {
                        // Need to clone TextPointer before moving it. 
                        textPointer = textPointer.CreatePointer(); 
                    }
                    textPointer.MoveToNextContextPosition(LogicalDirection.Forward); 
                }
            }

            if (paragraph != null) 
            {
                StructuralCache.CurrentFormatContext.DependentMax = (TextPointer)textPointer; 
            } 

            return paragraph; 
        }
Пример #57
0
        // Move this TP by distance, and respect virtualization of child TextContainer
        // Return true if distance is within boundary of the aggregated container, false otherwise
        private static bool xGapAwareScan(DocumentSequenceTextPointer thisTp, int distance)
        {
            //
            // Note: To calculate distance between thisTp.ChildPointer to
            // it container Start/End position would have been devastating
            // for those who implemented vitualization.
            // Ideally we would need a new API on ITextPointer
            //      ITextPointer.IsDistanceOutOfRange
            ChildDocumentBlock cdb   = thisTp.ChildBlock;
            bool         isNavigator = true;
            ITextPointer childTn     = thisTp.ChildPointer;

            if (childTn == null)
            {
                isNavigator = false;
                childTn     = thisTp.ChildPointer.CreatePointer();
            }
            LogicalDirection scanDir = (distance > 0 ? LogicalDirection.Forward : LogicalDirection.Backward);

            distance = Math.Abs(distance);
            while (distance > 0)
            {
                TextPointerContext tst = childTn.GetPointerContext(scanDir);
                switch (tst)
                {
                case TextPointerContext.ElementStart:
                    childTn.MoveToNextContextPosition(scanDir);
                    distance--;
                    break;

                case TextPointerContext.ElementEnd:
                    childTn.MoveToNextContextPosition(scanDir);
                    distance--;
                    break;

                case TextPointerContext.EmbeddedElement:
                    childTn.MoveToNextContextPosition(scanDir);
                    distance--;
                    break;

                case TextPointerContext.Text:
                    int runLength  = childTn.GetTextRunLength(scanDir);
                    int moveLength = runLength < distance ? runLength : distance;
                    distance -= moveLength;
                    //agurcan: Fix for 1098225
                    //We need to propagate direction info to MoveByOffset
                    if (scanDir == LogicalDirection.Backward)
                    {
                        moveLength *= -1;
                    }
                    childTn.MoveByOffset(moveLength);
                    break;

                case TextPointerContext.None:
                    if (!((cdb.IsHead && scanDir == LogicalDirection.Backward) ||
                          (cdb.IsTail && scanDir == LogicalDirection.Forward)
                          )
                        )
                    {
                        cdb     = (scanDir == LogicalDirection.Forward ? cdb.NextBlock : cdb.PreviousBlock);
                        childTn = (scanDir == LogicalDirection.Forward ?
                                   cdb.ChildContainer.Start.CreatePointer(childTn.LogicalDirection)
                                    : cdb.ChildContainer.End.CreatePointer(childTn.LogicalDirection)
                                   );
                    }
                    else
                    {
                        return(false);
                    }
                    break;

                default:
                    Debug.Assert(false, "invalid TextPointerContext");
                    break;
                }
            }

            // Re-position thisTp to the new location.
            thisTp.ChildBlock = cdb;
            if (isNavigator)
            {
                thisTp.ChildPointer = childTn;
            }
            else
            {
                thisTp.ChildPointer = childTn.CreatePointer();
            }
            return(true);
        }
        //------------------------------------------------------
        //
        //  Private Methods
        //
        //------------------------------------------------------

        #region Private Methods

        // Worker for MoveToNextFormatNormalizedPosition/MoveToNextInsertionPosition.
        private static bool NormalizePosition(ITextPointer thisNavigator, LogicalDirection direction, bool respectCaretUnitBoundaries)
        {
            Invariant.Assert(!thisNavigator.IsFrozen, "Can't reposition a frozen pointer!");

            int symbolCount = 0;
            int increment;
            LogicalDirection oppositeDirection;
            TextPointerContext directEnterScope;
            TextPointerContext oppositeEnterScope;

            if (direction == LogicalDirection.Forward)
            {
                increment = +1;
                oppositeDirection = LogicalDirection.Backward;
                directEnterScope = TextPointerContext.ElementStart;
                oppositeEnterScope = TextPointerContext.ElementEnd;
            }
            else
            {
                increment = -1;
                oppositeDirection = LogicalDirection.Forward;
                directEnterScope = TextPointerContext.ElementEnd;
                oppositeEnterScope = TextPointerContext.ElementStart;
            }

            // When the pointer appears in between structural tags we need to start
            // from sliding into the deepest possible position without
            // leaving any structural units. We need to do that only
            // if we are not at insertion position already.
            if (!IsAtNormalizedPosition(thisNavigator, respectCaretUnitBoundaries))
            {
                // Go inside an innermost structured element (non-inline)
                while (
                    thisNavigator.GetPointerContext(direction) == directEnterScope &&
                    !typeof(Inline).IsAssignableFrom(thisNavigator.GetElementType(direction)) &&
                    !IsAtNormalizedPosition(thisNavigator, respectCaretUnitBoundaries))
                {
                    thisNavigator.MoveToNextContextPosition(direction);
                    symbolCount += increment;
                }
                while (
                    thisNavigator.GetPointerContext(oppositeDirection) == oppositeEnterScope &&
                    !typeof(Inline).IsAssignableFrom(thisNavigator.GetElementType(oppositeDirection)) &&
                    !IsAtNormalizedPosition(thisNavigator, respectCaretUnitBoundaries))
                {
                    thisNavigator.MoveToNextContextPosition(oppositeDirection);
                    symbolCount -= increment;
                }
            }

            // Get out of a Hyperlink, etc. inner edge.
            symbolCount = LeaveNonMergeableInlineBoundary(thisNavigator, direction, symbolCount);

            // Get out of a compound sequence if any.
            if (respectCaretUnitBoundaries)
            {
                while (!IsAtCaretUnitBoundary(thisNavigator))
                {
                    symbolCount += increment;
                    thisNavigator.MoveByOffset(increment);
                }
            }

            // Here is the core part of this method's logic - skipping all formatting tags in the given direction.
            // Skip character formatting tags if they are present in this direction.
            // Even if an insertion position can be in the middle of this formatting sequence,
            // we want to skip it all and reach the farthest possible insertion position in that direction.
            // Such approach guarantees that repeated calls of this normalization will give the same reauls.
            // In case if there is an inserrtion position in the middle (say, in empty Run),
            // the loop moving in opposite direction below will find it if needed.
            while (TextSchema.IsMergeableInline(thisNavigator.GetElementType(direction)))
            {
                thisNavigator.MoveToNextContextPosition(direction);
                symbolCount += increment;
            }

            if (!IsAtNormalizedPosition(thisNavigator, respectCaretUnitBoundaries))
            {
                // If still not at insertion point, try skipping inline tags in the opposite direction
                // now possibly stopping inside of empty element
                while (!IsAtNormalizedPosition(thisNavigator, respectCaretUnitBoundaries) &&
                    TextSchema.IsMergeableInline(thisNavigator.GetElementType(oppositeDirection)))
                {
                    thisNavigator.MoveToNextContextPosition(oppositeDirection);
                    symbolCount -= increment;
                }

                // If still not at insertion point, then try harder - skipping block tags
                // First in "preferred" direction
                while (!IsAtNormalizedPosition(thisNavigator, respectCaretUnitBoundaries) &&
                    thisNavigator.MoveToNextContextPosition(direction))
                {
                    symbolCount += increment;
                }

                // And finally in apposite direction
                while (!IsAtNormalizedPosition(thisNavigator, respectCaretUnitBoundaries) &&
                    thisNavigator.MoveToNextContextPosition(oppositeDirection))
                {
                    symbolCount -= increment;
                }

                if (!IsAtNormalizedPosition(thisNavigator, respectCaretUnitBoundaries))
                {
                    // When there is no insertion positions in the whole document
                    // we return the position back to its original place.
                    thisNavigator.MoveByOffset(-symbolCount);
                }
            }

            return symbolCount != 0;
        }
Пример #59
0
        /// <summary>
        /// Retrieves the height and offset, in pixels, of the edge of
        /// the object/character represented by position.
        /// </summary>
        /// <param name="position">
        /// Position of an object/character.
        /// </param>
        /// <param name="transform">
        /// Transform to be applied to returned rect
        /// </param>
        /// <returns>
        /// The height, in pixels, of the edge of the object/character
        /// represented by position.
        /// </returns>
        /// <exception cref="System.InvalidOperationException">
        /// Throws InvalidOperationException if IsValid is false.
        /// If IsValid returns false, Validate method must be called before
        /// calling this method.
        /// </exception>
        /// <remarks>
        /// Rect.Width is always 0.
        /// Output parameter Transform is always Identity. It is not expected that editing scenarios
        /// will require speparate transform with raw rectangle for this case.
        /// If the document is empty, then this method returns the expected
        /// height of a character, if placed at the specified position.
        /// </remarks>
        internal override Rect GetRawRectangleFromTextPosition(ITextPointer position, out Transform transform)
        {
#if DEBUG
            DocumentsTrace.FixedTextOM.TextView.Trace(string.Format("GetRectFromTextPosition {0}, {1}", (FixedTextPointer)position, position.LogicalDirection));
#endif

            FixedTextPointer ftp = Container.VerifyPosition(position);
            FixedPosition    fixedp;

            // need a default caret size, otherwise infinite corners cause text editor and MultiPageTextView problems.
            // Initialize transform to Identity. This function always returns Identity transform.
            Rect designRect = new Rect(0, 0, 0, 10);
            transform = Transform.Identity;

            Debug.Assert(ftp != null);
            if (ftp.FlowPosition.IsBoundary)
            {
                if (!_GetFirstFixedPosition(ftp, out fixedp))
                {
                    return(designRect);
                }
            }

            else if (!_GetFixedPosition(ftp, out fixedp))
            {
                //
                // This is the start/end element, we need to find out the next element and return the next element
                // start offset/height.
                //
                if (position.GetPointerContext(LogicalDirection.Forward) != TextPointerContext.None)
                {
                    ITextPointer     psNext  = position.CreatePointer(1);
                    FixedTextPointer ftpNext = Container.VerifyPosition(psNext);
                    if (!_GetFixedPosition(ftpNext, out fixedp))
                    {
                        return(designRect);
                    }
                }
                else
                {
                    return(designRect);
                }
            }

            if (fixedp.Page != this.PageIndex)
            {
                return(designRect);
            }

            DependencyObject element = this.FixedPage.GetElement(fixedp.Node);
            if (element is Glyphs)
            {
                Glyphs g = (Glyphs)element;
                designRect = _GetGlyphRunDesignRect(g, fixedp.Offset, fixedp.Offset);
                // need to do transform
                GeneralTransform tran = g.TransformToAncestor(this.FixedPage);
                designRect = _GetTransformedCaretRect(tran, designRect.TopLeft, designRect.Height);
            }
            else if (element is Image)
            {
                Image            image  = (Image)element;
                GeneralTransform tran   = image.TransformToAncestor(this.FixedPage);
                Point            offset = new Point(0, 0);
                if (fixedp.Offset > 0)
                {
                    offset.X += image.ActualWidth;
                }
                designRect = _GetTransformedCaretRect(tran, offset, image.ActualHeight);
            }
            else if (element is Path)
            {
                Path             path   = (Path)element;
                GeneralTransform tran   = path.TransformToAncestor(this.FixedPage);
                Rect             bounds = path.Data.Bounds;
                Point            offset = bounds.TopLeft;
                if (fixedp.Offset > 0)
                {
                    offset.X += bounds.Width;
                }
                designRect = _GetTransformedCaretRect(tran, offset, bounds.Height);
            }

            return(designRect);
        }
        // Returns true if the position is on the caret unit boundary.
        // Call TextView's IsAtCaretUnitBoundary if TextView is valid for this position
        // and it appears strictly within text run.
        // We consider all markup-boundary positions as caret unit boundaries.
        // If TextView information is not available call IsInsideCompoundSequence.
        private static bool IsAtCaretUnitBoundary(ITextPointer position)
        {
            bool isAtCaretUnitBoundary;

            TextPointerContext forwardContext = position.GetPointerContext(LogicalDirection.Forward);
            TextPointerContext backwardContext = position.GetPointerContext(LogicalDirection.Backward);

            if (backwardContext == TextPointerContext.Text && forwardContext == TextPointerContext.Text)
            {
                if (position.HasValidLayout)
                {
                    // Check the insertion position with TextView's IsAtCaretUnitBoundary
                    // that will acurately check the caret unit bounday for surrogate and international
                    // characters
                    isAtCaretUnitBoundary = position.IsAtCaretUnitBoundary;
                }
                else
                {
                    // Check the insertion position with the internal compound sequence
                    isAtCaretUnitBoundary = !IsInsideCompoundSequence(position);
                }
            }
            else
            {
                isAtCaretUnitBoundary = true;
            }

            return isAtCaretUnitBoundary;
        }