コード例 #1
0
        // Token: 0x06007247 RID: 29255 RVA: 0x0020ABF0 File Offset: 0x00208DF0
        internal static AutomationPeer GetEnclosingAutomationPeer(ITextPointer start, ITextPointer end, out ITextPointer elementStart, out ITextPointer elementEnd)
        {
            List <object>       list        = new List <object>();
            List <ITextPointer> list2       = new List <ITextPointer>();
            ITextPointer        textPointer = start.CreatePointer();

            while (typeof(TextElement).IsAssignableFrom(textPointer.ParentType))
            {
                textPointer.MoveToElementEdge(ElementEdge.BeforeStart);
                object obj = textPointer.GetAdjacentElement(LogicalDirection.Forward);
                if (obj != null)
                {
                    list.Insert(0, obj);
                    list2.Insert(0, textPointer.CreatePointer(LogicalDirection.Forward));
                }
            }
            List <object>       list3 = new List <object>();
            List <ITextPointer> list4 = new List <ITextPointer>();

            textPointer = end.CreatePointer();
            while (typeof(TextElement).IsAssignableFrom(textPointer.ParentType))
            {
                textPointer.MoveToElementEdge(ElementEdge.AfterEnd);
                object obj = textPointer.GetAdjacentElement(LogicalDirection.Backward);
                if (obj != null)
                {
                    list3.Insert(0, obj);
                    list4.Insert(0, textPointer.CreatePointer(LogicalDirection.Backward));
                }
            }
            AutomationPeer automationPeer = null;
            ITextPointer   textPointer2;

            elementEnd   = (textPointer2 = null);
            elementStart = textPointer2;
            for (int i = Math.Min(list.Count, list3.Count); i > 0; i--)
            {
                if (list[i - 1] == list3[i - 1])
                {
                    object obj = list[i - 1];
                    if (obj is UIElement)
                    {
                        automationPeer = UIElementAutomationPeer.CreatePeerForElement((UIElement)obj);
                    }
                    else if (obj is ContentElement)
                    {
                        automationPeer = ContentElementAutomationPeer.CreatePeerForElement((ContentElement)obj);
                    }
                    if (automationPeer != null)
                    {
                        elementStart = list2[i - 1];
                        elementEnd   = list4[i - 1];
                        break;
                    }
                }
            }
            return(automationPeer);
        }
コード例 #2
0
        // Token: 0x060039B3 RID: 14771 RVA: 0x00105B0C File Offset: 0x00103D0C
        internal static TextRange InternalFind(ITextPointer startPosition, ITextPointer endPosition, string findPattern, CultureInfo cultureInfo, bool matchCase, bool matchWholeWord, bool matchLast, bool matchDiacritics, bool matchKashida, bool matchAlefHamza)
        {
            Invariant.Assert(startPosition.CompareTo(endPosition) <= 0);
            ITextPointer     textPointer;
            LogicalDirection direction;

            if (matchLast)
            {
                textPointer = endPosition;
                direction   = LogicalDirection.Backward;
            }
            else
            {
                textPointer = startPosition;
                direction   = LogicalDirection.Forward;
            }
            int num = Math.Max(64, findPattern.Length * 2 * 2);

            textPointer = textPointer.CreatePointer();
            while ((matchLast ? startPosition.CompareTo(textPointer) : textPointer.CompareTo(endPosition)) < 0)
            {
                ITextPointer textPointer2 = textPointer.CreatePointer();
                char[]       array        = new char[num];
                int[]        array2       = new int[num + 1];
                int          num2         = TextFindEngine.SetFindTextAndFindTextPositionMap(startPosition, endPosition, textPointer, direction, matchLast, array, array2);
                if (!matchDiacritics || num2 >= findPattern.Length)
                {
                    int  num3 = matchLast ? (array.Length - num2) : 0;
                    bool hasPreceedingSeparatorChar = false;
                    bool hasFollowingSeparatorChar  = false;
                    if (matchWholeWord)
                    {
                        TextFindEngine.GetContextualInformation(textPointer2, matchLast ? (-array2[array2.Length - num2 - 1]) : array2[num2], out hasPreceedingSeparatorChar, out hasFollowingSeparatorChar);
                    }
                    string textString = new string(array, num3, num2);
                    int    num5;
                    int    num4 = TextFindEngine.FindMatchIndexFromFindContent(textString, findPattern, cultureInfo, matchCase, matchWholeWord, matchLast, matchDiacritics, matchKashida, matchAlefHamza, hasPreceedingSeparatorChar, hasFollowingSeparatorChar, out num5);
                    if (num4 != -1)
                    {
                        ITextPointer textPointer3 = textPointer2.CreatePointer();
                        textPointer3.MoveByOffset(matchLast ? (-array2[num3 + num4]) : array2[num4]);
                        ITextPointer textPointer4 = textPointer2.CreatePointer();
                        textPointer4.MoveByOffset(matchLast ? (-array2[num3 + num4 + num5]) : array2[num4 + num5]);
                        return(new TextRange(textPointer3, textPointer4));
                    }
                    if (num2 > findPattern.Length)
                    {
                        textPointer = textPointer2.CreatePointer();
                        textPointer.MoveByOffset(matchLast ? (-array2[array.Length - num2 + findPattern.Length]) : array2[num2 - findPattern.Length]);
                    }
                }
            }
            return(null);
        }
コード例 #3
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);
        }
コード例 #4
0
        // Token: 0x06007C33 RID: 31795 RVA: 0x0022EB24 File Offset: 0x0022CD24
        public static IList <DependencyObject> GetSelectedNodes(object selection)
        {
            if (selection == null)
            {
                throw new ArgumentNullException("selection");
            }
            ITextPointer        textPointer = null;
            ITextPointer        position    = null;
            IList <TextSegment> list;

            TextSelectionHelper.CheckSelection(selection, out textPointer, out position, out list);
            IList <DependencyObject> list2 = new List <DependencyObject>();

            if (textPointer.CompareTo(position) == 0)
            {
                list2.Add(((TextPointer)textPointer).Parent);
                return(list2);
            }
            TextPointer textPointer2 = (TextPointer)textPointer.CreatePointer();

            while (((ITextPointer)textPointer2).CompareTo(position) < 0)
            {
                DependencyObject parent = textPointer2.Parent;
                if (!list2.Contains(parent))
                {
                    list2.Add(parent);
                }
                textPointer2.MoveToNextContextPosition(LogicalDirection.Forward);
            }
            return(list2);
        }
コード例 #5
0
        /// <summary>
        /// Is AutometionPeer represented by 'elementStart' is immediate child of AutomationPeer
        /// represented by 'ownerContentStart'.
        /// </summary>
        internal static bool IsImmediateAutomationChild(ITextPointer elementStart, ITextPointer ownerContentStart)
        {
            Invariant.Assert(elementStart.CompareTo(ownerContentStart) >= 0);
            bool immediateChild = true;
            // Walk element tree up looking for AutomationPeers.
            ITextPointer position = elementStart.CreatePointer();

            while (typeof(TextElement).IsAssignableFrom(position.ParentType))
            {
                position.MoveToElementEdge(ElementEdge.BeforeStart);
                if (position.CompareTo(ownerContentStart) <= 0)
                {
                    break;
                }
                AutomationPeer peer    = null;
                object         element = position.GetAdjacentElement(LogicalDirection.Forward);
                if (element is UIElement)
                {
                    peer = UIElementAutomationPeer.CreatePeerForElement((UIElement)element);
                }
                else if (element is ContentElement)
                {
                    peer = ContentElementAutomationPeer.CreatePeerForElement((ContentElement)element);
                }
                if (peer != null)
                {
                    immediateChild = false;
                    break;
                }
            }
            return(immediateChild);
        }
コード例 #6
0
        // Token: 0x06002EE3 RID: 12003 RVA: 0x000D3B5C File Offset: 0x000D1D5C
        internal override ITextPointer GetNextCaretUnitPosition(ITextPointer position, LogicalDirection direction)
        {
            FixedTextPointer ftp = this.Container.VerifyPosition(position);
            FixedPosition    fixedPosition;

            if (this._GetFixedPosition(ftp, out fixedPosition))
            {
                DependencyObject element = this.FixedPage.GetElement(fixedPosition.Node);
                if (element is Glyphs)
                {
                    Glyphs       glyphs       = (Glyphs)element;
                    GlyphRun     glyphRun     = glyphs.ToGlyphRun();
                    int          num          = (glyphRun.Characters == null) ? 0 : glyphRun.Characters.Count;
                    CharacterHit characterHit = (fixedPosition.Offset == num) ? new CharacterHit(fixedPosition.Offset - 1, 1) : new CharacterHit(fixedPosition.Offset, 0);
                    CharacterHit obj          = (direction == LogicalDirection.Forward) ? glyphRun.GetNextCaretCharacterHit(characterHit) : glyphRun.GetPreviousCaretCharacterHit(characterHit);
                    if (!characterHit.Equals(obj))
                    {
                        LogicalDirection edge = LogicalDirection.Forward;
                        if (obj.TrailingLength > 0)
                        {
                            edge = LogicalDirection.Backward;
                        }
                        int offset = obj.FirstCharacterIndex + obj.TrailingLength;
                        return(this._CreateTextPointer(new FixedPosition(fixedPosition.Node, offset), edge));
                    }
                }
            }
            ITextPointer textPointer = position.CreatePointer();

            textPointer.MoveToNextInsertionPosition(direction);
            return(textPointer);
        }
コード例 #7
0
        // Token: 0x06007246 RID: 29254 RVA: 0x0020AB60 File Offset: 0x00208D60
        internal static bool IsImmediateAutomationChild(ITextPointer elementStart, ITextPointer ownerContentStart)
        {
            Invariant.Assert(elementStart.CompareTo(ownerContentStart) >= 0);
            bool         result      = true;
            ITextPointer textPointer = elementStart.CreatePointer();

            while (typeof(TextElement).IsAssignableFrom(textPointer.ParentType))
            {
                textPointer.MoveToElementEdge(ElementEdge.BeforeStart);
                if (textPointer.CompareTo(ownerContentStart) <= 0)
                {
                    break;
                }
                AutomationPeer automationPeer  = null;
                object         adjacentElement = textPointer.GetAdjacentElement(LogicalDirection.Forward);
                if (adjacentElement is UIElement)
                {
                    automationPeer = UIElementAutomationPeer.CreatePeerForElement((UIElement)adjacentElement);
                }
                else if (adjacentElement is ContentElement)
                {
                    automationPeer = ContentElementAutomationPeer.CreatePeerForElement((ContentElement)adjacentElement);
                }
                if (automationPeer != null)
                {
                    result = false;
                    break;
                }
            }
            return(result);
        }
コード例 #8
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);
        }
コード例 #9
0
        // Token: 0x06002B51 RID: 11089 RVA: 0x000C5F3C File Offset: 0x000C413C
        internal void AddAttributeRange(ITextPointer start, ITextPointer end, TextServicesDisplayAttribute textServiceDisplayAttribute)
        {
            ITextPointer start2 = start.CreatePointer(LogicalDirection.Forward);
            ITextPointer end2   = end.CreatePointer(LogicalDirection.Backward);

            this._attributeRanges.Add(new CompositionAdorner.AttributeRange(this._textView, start2, end2, textServiceDisplayAttribute));
        }
コード例 #10
0
 // Token: 0x06002662 RID: 9826 RVA: 0x000B6E68 File Offset: 0x000B5068
 internal override List <AutomationPeer> GetAutomationPeersFromRange(ITextPointer start, ITextPointer end)
 {
     this._childrenStart = start.CreatePointer();
     this._childrenEnd   = end.CreatePointer();
     base.ResetChildrenCache();
     return(base.GetChildren());
 }
コード例 #11
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);
        }
コード例 #12
0
        // Returns the next non-white space character in the forward direction
        // from position, or null if no such position exists.
        // The return value will equal position if position is immediately followed
        // by a non-whitespace char.
        //
        // This method expects that limit is never null.  The scan will halt if
        // limit is encountered.
        private static ITextPointer GetNextNonWhiteSpacePosition(ITextPointer position, ITextPointer limit)
        {
            char character;

            Invariant.Assert(limit != null);

            while (true)
            {
                if (position.CompareTo(limit) == 0)
                {
                    position = null;
                    break;
                }

                position = GetNextTextPosition(position, limit, LogicalDirection.Forward, out character);

                if (position == null)
                {
                    break;
                }

                if (!Char.IsWhiteSpace(character))
                {
                    break;
                }

                position = position.CreatePointer(+1);
            }
            ;

            return(position);
        }
コード例 #13
0
        // 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);
        }
コード例 #14
0
        //------------------------------------------------------
        //
        //  Internal Methods
        //
        //------------------------------------------------------

        #region Internal Methods

        /// <summary>
        /// Add the composition attribute range that will be rendered.
        /// Used in TextServicesDisplayAttributePropertyRanges (for composition display attribute)
        /// </summary>
        internal void AddAttributeRange(ITextPointer start, ITextPointer end, TextServicesDisplayAttribute textServiceDisplayAttribute)
        {
            // Set the range start/end point's logical direction
            ITextPointer rangeStart = start.CreatePointer(LogicalDirection.Forward);
            ITextPointer rangeEnd   = end.CreatePointer(LogicalDirection.Backward);

            // Add the composition attribute range
            _attributeRanges.Add(new AttributeRange(_textView, rangeStart, rangeEnd, textServiceDisplayAttribute));
        }
コード例 #15
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);
        }
コード例 #16
0
        // Token: 0x060039B4 RID: 14772 RVA: 0x00105CA4 File Offset: 0x00103EA4
        private static void GetContextualInformation(ITextPointer position, int oppositeEndOffset, out bool hasPreceedingSeparatorChar, out bool hasFollowingSeparatorChar)
        {
            ITextPointer position2 = position.CreatePointer(oppositeEndOffset, position.LogicalDirection);

            if (oppositeEndOffset < 0)
            {
                hasPreceedingSeparatorChar = TextFindEngine.HasNeighboringSeparatorChar(position2, LogicalDirection.Backward);
                hasFollowingSeparatorChar  = TextFindEngine.HasNeighboringSeparatorChar(position, LogicalDirection.Forward);
                return;
            }
            hasPreceedingSeparatorChar = TextFindEngine.HasNeighboringSeparatorChar(position, LogicalDirection.Backward);
            hasFollowingSeparatorChar  = TextFindEngine.HasNeighboringSeparatorChar(position2, LogicalDirection.Forward);
        }
コード例 #17
0
ファイル: TextFindEngine.cs プロジェクト: yk2012985/wpf
        // Returns true iff there is a character in the specificed direction adjacent to a
        // position which is classified as a separator.  This is useful in detecting word breaks.
        private static bool HasNeighboringSeparatorChar(ITextPointer position, LogicalDirection direction)
        {
            ITextPointer nextPosition = position.GetNextInsertionPosition(direction);

            if (nextPosition == null)
            {
                return(true);
            }

            if (position.CompareTo(nextPosition) > 0)
            {
                ITextPointer temp = position;
                position     = nextPosition;
                nextPosition = temp;
            }

            int maxCharCount = position.GetOffsetToPosition(nextPosition);

            char[] findText            = new char[maxCharCount];
            int [] findTextPositionMap = new int[maxCharCount + 1];
            int    findTextLength;

            findTextLength = SetFindTextAndFindTextPositionMap(
                position,
                nextPosition,
                position.CreatePointer() /* need unfrozen pointer */,
                LogicalDirection.Forward,
                false /* matchLast */,
                findText,
                findTextPositionMap);

            if (findTextLength == 0)
            {
                return(true);
            }

            bool hasNeighboringSeparatorChar;

            if (direction == LogicalDirection.Forward)
            {
                hasNeighboringSeparatorChar = IsSeparatorChar(findText[0]);
            }
            else
            {
                hasNeighboringSeparatorChar = IsSeparatorChar(findText[findTextLength - 1]);
            }

            return(hasNeighboringSeparatorChar);
        }
コード例 #18
0
 // Token: 0x060038DC RID: 14556 RVA: 0x0010101C File Offset: 0x000FF21C
 private static ITextPointer GetNextNonWhiteSpacePosition(ITextPointer position, ITextPointer limit)
 {
     Invariant.Assert(limit != null);
     while (position.CompareTo(limit) != 0)
     {
         char c;
         position = TextEditorSpelling.GetNextTextPosition(position, limit, LogicalDirection.Forward, out c);
         if (position == null || !char.IsWhiteSpace(c))
         {
             return(position);
         }
         position = position.CreatePointer(1);
     }
     return(null);
 }
コード例 #19
0
        /// <summary>
        ///     Gets the parent element of ITextPointer.
        /// </summary>
        /// <param name="pointer">the pointer to examine</param>
        /// <returns>the parent element of this pointer; can be null</returns>
        /// <exception cref="ArgumentNullException">pointer is null</exception>
        public static UIElement GetParent(ITextPointer pointer)
        {
            if (pointer == null)
            {
                throw new ArgumentNullException("pointer");
            }

            DependencyObject document = pointer.TextContainer.Parent;
            DependencyObject parent   = PathNode.GetParent(document);

            FlowDocumentScrollViewer scrollViewer = parent as FlowDocumentScrollViewer;

            if (scrollViewer != null)
            {
                return((UIElement)scrollViewer.ScrollViewer.Content);
            }

            // Special case - for paginated content we want the DocumentPageHost for the
            // specific page instead of the viewer.
            DocumentViewerBase documentViewerBase = parent as DocumentViewerBase;

            if (documentViewerBase != null)
            {
                int pageNumber;

                // We get the content again here GetPointerPage handles
                // special cases like FixedDocumentSequences
                IDocumentPaginatorSource content = GetPointerPage(pointer.CreatePointer(LogicalDirection.Forward), out pageNumber);

                if (pageNumber >= 0)
                {
                    foreach (DocumentPageView dpv in documentViewerBase.PageViews)
                    {
                        if (dpv.PageNumber == pageNumber)
                        {
                            // DPVs always have one child - the DocumentPageHost
                            int count = VisualTreeHelper.GetChildrenCount(dpv);
                            Invariant.Assert(count == 1);
                            return(VisualTreeHelper.GetChild(dpv, 0) as DocumentPageHost);
                        }
                    }
                    // Page must not be visible.
                    return(null);
                }
            }

            return(parent as UIElement);
        }
コード例 #20
0
        // 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);
        }
コード例 #21
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;
                }
            }
コード例 #22
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);
        }
コード例 #23
0
ファイル: FixedTextView.cs プロジェクト: dox0/DotNet471RS3
        /// <summary>
        /// Finds the next position at the edge of a caret unit in
        /// specified direction.
        /// </summary>
        /// <param name="position">
        /// Initial text position of an object/character.
        /// </param>
        /// <param name="direction">
        /// If Forward, this method returns the "caret unit" position following
        /// the initial position.
        /// If Backward, this method returns the caret unit" position preceding
        /// the initial position.
        /// </param>
        /// <returns>
        /// The next caret unit break position in specified direction.
        /// </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>
        /// In the context of this method, "caret unit" refers to a group of one
        /// or more Unicode code points that map to a single rendered glyph.
        ///
        /// If position is located between two caret units, this method returns
        /// a new position located at the opposite edge of the caret unit in
        /// the indicated direction.
        /// If position is located within a group of Unicode code points that map
        /// to a single caret unit, this method returns a new position at
        /// the indicated edge of the containing caret unit.
        /// If position is located at the beginning of end of content -- there is
        /// no content in the indicated direction -- then this method returns
        /// a position located at the same location as initial position.
        /// </remarks>
        internal override ITextPointer GetNextCaretUnitPosition(ITextPointer position, LogicalDirection direction)
        {
            FixedTextPointer ftp = Container.VerifyPosition(position);
            FixedPosition    fixedp;

            if (_GetFixedPosition(ftp, out fixedp))
            {
                DependencyObject element = this.FixedPage.GetElement(fixedp.Node);
                if (element is Glyphs)
                {
                    Glyphs   g   = (Glyphs)element;
                    GlyphRun run = g.ToGlyphRun();

                    int          characterCount = (run.Characters == null) ? 0 : run.Characters.Count;
                    CharacterHit start          = (fixedp.Offset == characterCount) ?
                                                  new CharacterHit(fixedp.Offset - 1, 1) :
                                                  new CharacterHit(fixedp.Offset, 0);
                    CharacterHit next = (direction == LogicalDirection.Forward) ?
                                        run.GetNextCaretCharacterHit(start) :
                                        run.GetPreviousCaretCharacterHit(start);

                    if (!start.Equals(next))
                    {
                        LogicalDirection edge = LogicalDirection.Forward;
                        if (next.TrailingLength > 0)
                        {
                            edge = LogicalDirection.Backward;
                        }

                        int index = next.FirstCharacterIndex + next.TrailingLength;

                        return(_CreateTextPointer(new FixedPosition(fixedp.Node, index), edge));
                    }
                }
            }
            //default behavior is to simply move textpointer
            ITextPointer pointer = position.CreatePointer();

            pointer.MoveToNextInsertionPosition(direction);
            return(pointer);
        }
コード例 #24
0
        /// <summary>
        ///     Gets the tree elements spanned by the selection.
        /// </summary>
        /// <param name="selection">the selection to examine</param>
        /// <returns>a list of elements spanned by the selection; never returns
        /// null</returns>
        /// <exception cref="ArgumentNullException">selection is null</exception>
        /// <exception cref="ArgumentException">selection is of wrong type</exception>
        public static IList <DependencyObject> GetSelectedNodes(Object selection)
        {
            if (selection == null)
            {
                throw new ArgumentNullException("selection");
            }

            IList <TextSegment> segments;
            ITextPointer        start = null;
            ITextPointer        end   = null;

            CheckSelection(selection, out start, out end, out segments);

            IList <DependencyObject> list = new List <DependencyObject>();

            // If the selection is of length 0, then we simply add the parent of the
            // text container and return.
            if (start.CompareTo(end) == 0)
            {
                list.Add(((TextPointer)start).Parent);

                return(list);
            }

            TextPointer current = (TextPointer)start.CreatePointer();

            while (((ITextPointer)current).CompareTo(end) < 0)
            {
                DependencyObject node = current.Parent;

                if (!list.Contains(node))
                {
                    list.Add(node);
                }

                current.MoveToNextContextPosition(LogicalDirection.Forward);
            }

            return(list);
        }
コード例 #25
0
        // Token: 0x0600535A RID: 21338 RVA: 0x00172AC8 File Offset: 0x00170CC8
        private void Select(int start, int length)
        {
            if (start < 0)
            {
                throw new ArgumentOutOfRangeException("start", SR.Get("ParameterCannotBeNegative"));
            }
            if (length < 0)
            {
                throw new ArgumentOutOfRangeException("length", SR.Get("ParameterCannotBeNegative"));
            }
            ITextPointer textPointer = this.TextContainer.Start.CreatePointer();

            while (start-- > 0 && textPointer.MoveToNextInsertionPosition(LogicalDirection.Forward))
            {
            }
            ITextPointer textPointer2 = textPointer.CreatePointer();

            while (length-- > 0 && textPointer2.MoveToNextInsertionPosition(LogicalDirection.Forward))
            {
            }
            this.Selection.Select(textPointer, textPointer2);
        }
コード例 #26
0
        // -------------------------------------------------------------
        //
        // 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;
                }
            }
        }
コード例 #27
0
        /// <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;
        }
コード例 #28
0
ファイル: CompositionAdorner.cs プロジェクト: JianwenSun/cc
            //------------------------------------------------------
            //
            //  Private Methods
            //
            //------------------------------------------------------

            #region Private Methods

            private void AddMultipleCompositionLines(ITextPointer start, ITextPointer end)
            {
                // Initalize the start/end line pointer
                ITextPointer startLinePointer = start;
                ITextPointer endLinePointer = startLinePointer;

                // Get all composition lines that includes the start/end pointer
                while (endLinePointer.CompareTo(end) < 0)
                {
                    TextSegment textSegment = _textView.GetLineRange(endLinePointer);

                    if (textSegment.IsNull)
                    {
                        // endLinePointer is not within the TextView's definition of a line.
                        // Skip ahead to text on the next iteration.
                        startLinePointer = endLinePointer;
                    }
                    else
                    {
                        Debug.Assert(start.CompareTo(startLinePointer) <= 0, "The start pointer is positioned after the composition start line pointer!");

                        if (startLinePointer.CompareTo(textSegment.Start) < 0)
                        {
                            // Update the start line pointer
                            startLinePointer = textSegment.Start;
                        }

                        if (endLinePointer.CompareTo(textSegment.End) < 0)
                        {
                            if (end.CompareTo(textSegment.End) < 0)
                            {
                                // Update the end line pointer
                                endLinePointer = end.CreatePointer();
                            }
                            else
                            {
                                // Update the end line pointer
                                endLinePointer = textSegment.End.CreatePointer(LogicalDirection.Backward);
                            }
                        }
                        else
                        {
                            Debug.Assert(endLinePointer.CompareTo(textSegment.End) == 0, "The end line pointer is positioned after the composition text range end pointer!");
                        }

                        // Get the rectangle for start/end position
                        Rect startRect = _textView.GetRectangleFromTextPosition(startLinePointer);
                        Rect endRect = _textView.GetRectangleFromTextPosition(endLinePointer);

                        // Add the composition line to be rendered
                        _compositionLines.Add(new CompositionLine(startRect, endRect, _textServicesDisplayAttribute.GetLineColor(startLinePointer)));

                        startLinePointer = textSegment.End.CreatePointer(LogicalDirection.Forward);
                    }

                    // Move the start pointer to the next text line. startLinePointer must be a pointer to start 
                    // text.
                    while ((startLinePointer.GetPointerContext(LogicalDirection.Forward) != TextPointerContext.None) &&
                           (startLinePointer.GetPointerContext(LogicalDirection.Forward) != TextPointerContext.Text))
                    {
                        startLinePointer.MoveToNextContextPosition(LogicalDirection.Forward);
                    }
                    endLinePointer = startLinePointer;
                }
            }
コード例 #29
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);
        }
コード例 #30
0
ファイル: TextSelection.cs プロジェクト: JianwenSun/cc
        // Part of ExtendSelectionByMouse method:
        // Checks whether selection has been started and initiates selection process
        // Usually always returns true,
        // returns false only as a special value indicating that we need to return without executing selection expansion code.
        private bool BeginMouseSelectionProcess(ITextPointer cursorPosition)
        {
            if (_previousCursorPosition == null)
            {
                // This is a beginning of mouse selection guesture.
                // Initialize the guesture state
                // initially autoword expansion of both ends is enabled
                _anchorWordRangeHasBeenCrossedOnce = false;
                _allowWordExpansionOnAnchorEnd = true;
                _reenterPosition = null;

                if (this.GetUIElementSelected() != null)
                {
                    // This means that we have just received mousedown event and selected embedded element in this event.
                    // MoveMove event is sent immediately, but we don't want to loose UIElement selection,
                    // so we do not extend to the cursorPosition now.
                    _previousCursorPosition = cursorPosition.CreatePointer();
                    return false;
                }
            }

            return true;
        }
コード例 #31
0
ファイル: FixedTextView.cs プロジェクト: dox0/DotNet471RS3
        /// <summary>
        /// Retrieves an oriented text position matching position advanced by
        /// a number of lines from its initial position.
        /// </summary>
        /// <param name="position">
        /// Initial text position of an object/character.
        /// </param>
        /// <param name="suggestedX">
        /// The suggested X offset, in pixels, of text position on the destination
        /// line. If suggestedX is set to Double.NaN it will be ignored, otherwise
        /// the method will try to find a position on the destination line closest
        /// to suggestedX.
        /// </param>
        /// <param name="count">
        /// Number of lines to advance. Negative means move backwards.
        /// </param>
        /// <param name="newSuggestedX">
        /// newSuggestedX is the offset at the position moved (useful when moving
        /// between columns or pages).
        /// </param>
        /// <param name="linesMoved">
        /// linesMoved indicates the number of lines moved, which may be less
        /// than count if there is no more content.
        /// </param>
        /// <returns>
        /// A TextPointer and its orientation matching suggestedX on the
        /// destination line.
        /// </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>
        internal override ITextPointer GetPositionAtNextLine(ITextPointer position, double suggestedX, int count, out double newSuggestedX, out int linesMoved)
        {
            newSuggestedX = suggestedX;
            linesMoved    = 0;
#if DEBUG
            DocumentsTrace.FixedTextOM.TextView.Trace(string.Format("FixedTextView.MoveToLine {0}, {1}, {2}, {3}", (FixedTextPointer)position, position.LogicalDirection, suggestedX, count));
#endif

            FixedPosition    fixedp;
            LogicalDirection edge    = position.LogicalDirection;
            LogicalDirection scanDir = LogicalDirection.Forward;
            ITextPointer     pos     = position;

            FixedTextPointer ftp = Container.VerifyPosition(position);
            FixedTextPointer nav = new FixedTextPointer(true, edge, (FlowPosition)ftp.FlowPosition.Clone());

            //Skip any formatting tags
            _SkipFormattingTags(nav);
            bool gotFixedPosition = false;
            if (count == 0 ||
                ((gotFixedPosition = _GetFixedPosition(nav, out fixedp)) &&
                 fixedp.Page != this.PageIndex)
                )
            {
                //Invalid text position, so do nothing. PS #963924
                return(position);
            }

            if (count < 0)
            {
                count   = -count;
                scanDir = LogicalDirection.Backward;
            }

            if (!gotFixedPosition)
            {
                // move to next insertion position in direction, provided we're in this view
                if (this.Contains(position))
                {
                    nav = new FixedTextPointer(true, scanDir, (FlowPosition)ftp.FlowPosition.Clone());
                    ((ITextPointer)nav).MoveToInsertionPosition(scanDir);
                    ((ITextPointer)nav).MoveToNextInsertionPosition(scanDir);
                    if (this.Contains(nav))
                    {
                        // make sure we haven't changed pages
                        linesMoved = (scanDir == LogicalDirection.Forward) ? 1 : -1;
                        return(nav);
                    }
                }
                return(position);
            }

            if (DoubleUtil.IsNaN(suggestedX))
            {
                suggestedX = 0;
            }

            while (count > linesMoved)
            {
                if (!_GetNextLineGlyphs(ref fixedp, ref edge, suggestedX, scanDir))
                {
                    break;
                }
                linesMoved++;
            }

            if (linesMoved == 0)
            {
                pos = position.CreatePointer();
                return(pos);
            }

            if (scanDir == LogicalDirection.Backward)
            {
                linesMoved = -linesMoved;
            }

            pos = _CreateTextPointer(fixedp, edge);
            Debug.Assert(pos != null);

            if (pos.CompareTo(position) == 0)
            {
                linesMoved = 0;
            }

            return(pos);
        }
コード例 #32
0
        /// <summary>
        /// Retrieves an oriented text position matching position advanced by 
        /// a number of lines from its initial position.
        /// </summary>
        /// <param name="position">
        /// Initial text position of an object/character.
        /// </param>
        /// <param name="suggestedX">
        /// The suggested X offset, in pixels, of text position on the destination 
        /// line. If suggestedX is set to Double.NaN it will be ignored, otherwise 
        /// the method will try to find a position on the destination line closest 
        /// to suggestedX.
        /// </param>
        /// <param name="count">
        /// Number of lines to advance. Negative means move backwards.
        /// </param>
        /// <param name="newSuggestedX">
        /// newSuggestedX is the offset at the position moved (useful when moving 
        /// between columns or pages).
        /// </param>
        /// <param name="linesMoved">
        /// linesMoved indicates the number of lines moved, which may be less 
        /// than count if there is no more content.
        /// </param>
        /// <returns>
        /// A TextPointer and its orientation matching suggestedX on the 
        /// destination line.
        /// </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>
        internal override ITextPointer GetPositionAtNextLine(ITextPointer position, double suggestedX, int count, out double newSuggestedX, out int linesMoved)
        {
            newSuggestedX = suggestedX;
            linesMoved = 0;
#if DEBUG
            DocumentsTrace.FixedTextOM.TextView.Trace(string.Format("FixedTextView.MoveToLine {0}, {1}, {2}, {3}", (FixedTextPointer)position, position.LogicalDirection, suggestedX, count));
#endif

            FixedPosition fixedp;
            LogicalDirection edge = position.LogicalDirection;
            LogicalDirection scanDir = LogicalDirection.Forward;
            ITextPointer pos = position;

            FixedTextPointer ftp = Container.VerifyPosition(position);
            FixedTextPointer nav = new FixedTextPointer(true, edge, (FlowPosition)ftp.FlowPosition.Clone());

            //Skip any formatting tags
            _SkipFormattingTags(nav);
            bool gotFixedPosition = false;
            if (   count == 0
                || ((gotFixedPosition = _GetFixedPosition(nav, out fixedp))
                && fixedp.Page != this.PageIndex )
                )
            {
                //Invalid text position, so do nothing. PS #963924
                return position;
            }

            if (count < 0)
            {
                count   = -count;
                scanDir = LogicalDirection.Backward;
            }

            if (!gotFixedPosition)
            {
                // move to next insertion position in direction, provided we're in this view
                if (this.Contains(position))
                {
                    nav = new FixedTextPointer(true, scanDir, (FlowPosition)ftp.FlowPosition.Clone());
                    ((ITextPointer)nav).MoveToInsertionPosition(scanDir);
                    ((ITextPointer)nav).MoveToNextInsertionPosition(scanDir);
                    if (this.Contains(nav))
                    {
                        
                        // make sure we haven't changed pages
                        linesMoved = (scanDir == LogicalDirection.Forward) ? 1 : -1;
                        return nav;
                    }
                }
                return position;
            }

            if (DoubleUtil.IsNaN(suggestedX))
            {
                suggestedX = 0;
            }

            while (count > linesMoved)
            {
                if (!_GetNextLineGlyphs(ref fixedp, ref edge, suggestedX, scanDir))
                    break;
                linesMoved++;
            }

            if (linesMoved == 0)
            {
                pos = position.CreatePointer();
                return pos;
            }

            if (scanDir == LogicalDirection.Backward)
            {
                linesMoved = -linesMoved;
            }
            
            pos = _CreateTextPointer(fixedp, edge);
            Debug.Assert(pos != null);

            if (pos.CompareTo(position) == 0)
            {
                linesMoved = 0;
            }
            
            return pos;
        }
コード例 #33
0
        // Worker for IsAtNonMergeableInlineStart/IsAtNonMergeableInlineEnd.
        private static bool IsAtNonMergeableInlineEdge(ITextPointer position, LogicalDirection direction)
        {
            BorderingElementCategory elementType = GetBorderingElementCategory(position, direction);

            if (elementType == BorderingElementCategory.MergeableScopingInline)
            {
                ITextPointer navigator = position.CreatePointer();

                do
                {
                    navigator.MoveToNextContextPosition(direction);
                }
                while ((elementType = GetBorderingElementCategory(navigator, direction)) == BorderingElementCategory.MergeableScopingInline);
            }

            return (elementType == BorderingElementCategory.NonMergeableScopingInline);
        }
コード例 #34
0
        // Initializes an array with the minimum necessary text to support a call to
        // SelectionWordBreaker.IsAtWordBoundary.
        //
        // position on exit holds the offset into the text array corresponding to
        // pointer's location in the document.
        //
        // Called by IsAtWordBoundary.
        private static void GetWordBreakerText(ITextPointer pointer, out char[] text, out int position)
        {
            char[] preceedingText = new char[SelectionWordBreaker.MinContextLength];
            char[] followingText = new char[SelectionWordBreaker.MinContextLength];
            int preceedingCount = 0;
            int followingCount = 0;
            int runLength;
            ITextPointer navigator;

            navigator = pointer.CreatePointer();

            // Try to back up SelectionWordBreaker.MinContextLength chars, ignoring formatting.
            do
            {
                runLength = Math.Min(navigator.GetTextRunLength(LogicalDirection.Backward), SelectionWordBreaker.MinContextLength - preceedingCount);
                preceedingCount += runLength;

                navigator.MoveByOffset(-runLength);
                navigator.GetTextInRun(LogicalDirection.Forward, preceedingText, SelectionWordBreaker.MinContextLength - preceedingCount, runLength);

                if (preceedingCount == SelectionWordBreaker.MinContextLength)
                    break;

                // Skip over any formatting.
                navigator.MoveToInsertionPosition(LogicalDirection.Backward);
            }
            while (navigator.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.Text);

            navigator.MoveToPosition(pointer);

            // Try to advance SelectionWordBreaker.MinContextLength chars, ignoring formatting.
            do
            {
                runLength = Math.Min(navigator.GetTextRunLength(LogicalDirection.Forward), SelectionWordBreaker.MinContextLength - followingCount);

                navigator.GetTextInRun(LogicalDirection.Forward, followingText, followingCount, runLength);

                followingCount += runLength;

                if (followingCount == SelectionWordBreaker.MinContextLength)
                    break;

                navigator.MoveByOffset(runLength);
                // Skip over any formatting.
                navigator.MoveToInsertionPosition(LogicalDirection.Forward);
            }
            while (navigator.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text);

            // Combine the preceeding and following text into a single array.
            text = new char[preceedingCount + followingCount];
            Array.Copy(preceedingText, SelectionWordBreaker.MinContextLength - preceedingCount, text, 0, preceedingCount);
            Array.Copy(followingText, 0, text, preceedingCount, followingCount);

            position = preceedingCount;
        }
コード例 #35
0
        // <see cref="System.Windows.Documents.TextPointer.GetFrozenPointer"/>
        internal static ITextPointer GetFrozenPointer(ITextPointer thisPointer, LogicalDirection logicalDirection)
        {
            ITextPointer frozenPointer;

            if (thisPointer.IsFrozen && thisPointer.LogicalDirection == logicalDirection)
            {
                frozenPointer = thisPointer;
            }
            else
            {
                frozenPointer = thisPointer.CreatePointer(logicalDirection);
                frozenPointer.Freeze();
            }

            return frozenPointer;
        }
コード例 #36
0
        /// <summary>
        /// Moves the navigator in the given direction to a position of the next
        /// word boundary.
        /// </summary>
        /// <param name="thisNavigator">ITextPointer to advance.</param>
        /// <param name="movingDirection">
        /// Direction to move.
        /// </param>
        /// <returns></returns>
        // 




        internal static bool MoveToNextWordBoundary(ITextPointer thisNavigator, LogicalDirection movingDirection)
        {
            int moveCounter = 0;

            Invariant.Assert(!thisNavigator.IsFrozen, "Can't reposition a frozen pointer!");
            ITextPointer startPosition = thisNavigator.CreatePointer();

            while (thisNavigator.MoveToNextInsertionPosition(movingDirection))
            {
                moveCounter++;

                // Need to break the loop for weird case when there is no word break in text content.
                // When the word looks too long, consider end of textRun as a word break.
                // 
                if (moveCounter > 64) // 64 was taken as a random number. Probably not big enough though...
                {
                    thisNavigator.MoveToPosition(startPosition);
                    thisNavigator.MoveToNextContextPosition(movingDirection);
                    break;
                }

                if (IsAtWordBoundary(thisNavigator, /*insideWordDirection:*/LogicalDirection.Forward))
                {
                    // Note that we always use Forward direction for word orientation.
                    break;
                }
            }

            return moveCounter > 0;
        }
コード例 #37
0
ファイル: ListParagraph.cs プロジェクト: sjyanxin/WPFSource
        /// <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; 
        }
コード例 #38
0
        // Writes a collection of attributes representing inheritable properties
        // whose values has been affected by this element.
        // Parameter onlyAffected=true means that we serialize only properties affected by
        // the current element; otherwise we output all known inheritable properties.
        private static void WriteInheritableProperties(Type elementTypeStandardized, ITextPointer context, XmlWriter xmlWriter, bool onlyAffected, DependencyObject complexProperties)
        {
            // Create a pointer positioned immediately outside the element
            ITextPointer outerContext = null;
            if (onlyAffected)
            {
                outerContext = context.CreatePointer();
                outerContext.MoveToElementEdge(ElementEdge.BeforeStart);
            }

            DependencyProperty[] inheritableProperties = TextSchema.GetInheritableProperties(elementTypeStandardized);

            for (int i = 0; i < inheritableProperties.Length; i++)
            {
                DependencyProperty property = inheritableProperties[i];

                object innerValue = context.GetValue(property);
                if (innerValue == null)
                {
                    // Some properties like Foreground may have null as default value.
                    // Skip them.
                    continue;
                }

                object outerValue = null;
                if (onlyAffected)
                {
                    outerValue = outerContext.GetValue(property);
                }
                
                // The property must appear in markup if the element
                if (!onlyAffected ||  // all properties requested for saving context on root
                    !TextSchema.ValuesAreEqual(innerValue, outerValue)) // or the element really affects the property
                {
                    string stringValue = DPTypeDescriptorContext.GetStringValue(property, innerValue);

                    if (stringValue != null)
                    {
                        stringValue = FilterNaNStringValueForDoublePropertyType(stringValue, property.PropertyType);

                        string propertyName;
                        if (property == FrameworkContentElement.LanguageProperty)
                        {
                            // Special case for CultureInfo property that must be represented in xaml as xml:lang attribute
                            propertyName = "xml:lang";
                        }
                        else
                        {
                            // Regular case: serialize a property with its own name
                            propertyName = GetPropertyNameForElement(property, elementTypeStandardized, /*forceComplexName:*/false);
                        }
                        xmlWriter.WriteAttributeString(propertyName, stringValue);
                    }
                    else
                    {
                        complexProperties.SetValue(property, innerValue);
                    }
                }
            }
        }
コード例 #39
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);
        }
コード例 #40
0
        // If position is before the start boundary of a non-mergeable inline (Hyperlink),
        // this method returns a position immediately preceding its content (which is not an insertion position).
        // This method will skip past leading InlineUIContainers and BlockUIContainers. Otherwise returns null.
        internal static ITextPointer GetFollowingNonMergeableInlineContentStart(ITextPointer position)
        {
            ITextPointer navigator = position.CreatePointer();
            bool moved = false;
            Type elementType;
            
            while (true)
            {
                BorderingElementCategory category = GetBorderingElementCategory(navigator, LogicalDirection.Forward);

                // If position is before formatting closing scope, skip to outside the formatting scope.
                if (category == BorderingElementCategory.MergeableScopingInline)
                {
                    do
                    {
                        navigator.MoveToNextContextPosition(LogicalDirection.Forward);
                    }
                    while (GetBorderingElementCategory(navigator, LogicalDirection.Forward) == BorderingElementCategory.MergeableScopingInline);

                    moved = true;
                }

                // Skip all InlineUIContainers and BlockUIContainers.
                elementType = navigator.GetElementType(LogicalDirection.Forward);
                if (elementType == typeof(InlineUIContainer) || elementType == typeof(BlockUIContainer))
                {
                    // We are next to an InlineUIContainer/BlockUIContainer. Skip the following element.
                    navigator.MoveToNextContextPosition(LogicalDirection.Forward);
                    navigator.MoveToElementEdge(ElementEdge.AfterEnd);
                }
                else if (navigator.ParentType == typeof(InlineUIContainer) || navigator.ParentType == typeof(BlockUIContainer))
                {
                    // We are inside an InlineUIContainer/BlockUIContainer. Skip this element.
                    navigator.MoveToElementEdge(ElementEdge.AfterEnd);
                }
                else
                {
                    break;
                }

		// Move to next insertion position if we are done skipping a string of sequential UICs to get a
		// valid selection start pointer. We need to make sure we land at a position that would be given 
		// to this function had the UICs not been there. This ensures that we end up inside Runs that
		// follow instead of before them, e.g. </Span><Run>|abc</Run> instead of |</Span><Run>abc</Run>.
                elementType = navigator.GetElementType(LogicalDirection.Forward);
                if (!(elementType == typeof(InlineUIContainer)) && !(elementType == typeof(BlockUIContainer)))
                {
                    navigator.MoveToNextInsertionPosition(LogicalDirection.Forward);
                }

                moved = true;
            }

            if (typeof(Inline).IsAssignableFrom(elementType) && !TextSchema.IsMergeableInline(elementType))
            {
                // We are adjacent to a nonmergeable inline.  Find its content.

                // Just skip over all opening contexts.
                do
                {
                    navigator.MoveToNextContextPosition(LogicalDirection.Forward);
                }
                while (navigator.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementStart);

                moved = true;
            }

            return moved ? navigator : null;
        }
コード例 #41
0
        /// <summary>
        /// Finds the next position at the edge of a caret unit in 
        /// specified direction.
        /// </summary>
        /// <param name="position">
        /// Initial text position of an object/character.
        /// </param>
        /// <param name="direction">
        /// If Forward, this method returns the "caret unit" position following 
        /// the initial position.
        /// If Backward, this method returns the caret unit" position preceding 
        /// the initial position.
        /// </param>
        /// <returns>
        /// The next caret unit break position in specified direction.
        /// </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>
        /// In the context of this method, "caret unit" refers to a group of one 
        /// or more Unicode code points that map to a single rendered glyph.
        /// 
        /// If position is located between two caret units, this method returns 
        /// a new position located at the opposite edge of the caret unit in 
        /// the indicated direction.
        /// If position is located within a group of Unicode code points that map 
        /// to a single caret unit, this method returns a new position at 
        /// the indicated edge of the containing caret unit.
        /// If position is located at the beginning of end of content -- there is 
        /// no content in the indicated direction -- then this method returns 
        /// a position located at the same location as initial position.
        /// </remarks>
        internal override ITextPointer GetNextCaretUnitPosition(ITextPointer position, LogicalDirection direction)
        {
            FixedTextPointer ftp = Container.VerifyPosition(position);
            FixedPosition fixedp;

            if (_GetFixedPosition(ftp, out fixedp))
            {
                DependencyObject element = this.FixedPage.GetElement(fixedp.Node);
                if (element is Glyphs)
                {
                    Glyphs g = (Glyphs)element;
                    GlyphRun run = g.ToGlyphRun();

                    int characterCount = (run.Characters == null) ? 0 : run.Characters.Count;
                    CharacterHit start = (fixedp.Offset == characterCount) ?
                        new CharacterHit(fixedp.Offset - 1, 1) :
                        new CharacterHit(fixedp.Offset, 0);
                    CharacterHit next = (direction == LogicalDirection.Forward) ?
                        run.GetNextCaretCharacterHit(start) :
                        run.GetPreviousCaretCharacterHit(start);

                    if (!start.Equals(next))
                    {
                        LogicalDirection edge = LogicalDirection.Forward;
                        if (next.TrailingLength > 0)
                        {
                            edge = LogicalDirection.Backward;
                        }

                        int index = next.FirstCharacterIndex + next.TrailingLength;

                        return _CreateTextPointer(new FixedPosition(fixedp.Node, index), edge);
                    }
                }
            }
            //default behavior is to simply move textpointer
            ITextPointer pointer = position.CreatePointer();
            pointer.MoveToNextInsertionPosition(direction);
            return pointer;
        }
コード例 #42
0
        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;
        }
コード例 #43
0
ファイル: TextSelection.cs プロジェクト: JianwenSun/cc
        // Part of ExtendSelectionByMouse method:
        // Identifies words on selection ends.
        private void IdentifyWordsOnSelectionEnds(ITextPointer anchorPosition, ITextPointer cursorPosition, bool forceWordSelection, out TextSegment anchorWordRange, out TextSegment cursorWordRange)
        {
            if (forceWordSelection)
            {
                anchorWordRange = TextPointerBase.GetWordRange(anchorPosition);
                cursorWordRange = TextPointerBase.GetWordRange(cursorPosition, cursorPosition.LogicalDirection);
            }
            else
            {
                // Define whether word adjustment is allowed. Pressing Shift+Control prevents from auto-word expansion.
                bool disableWordExpansion = _textEditor.AutoWordSelection == false || ((Keyboard.Modifiers & ModifierKeys.Shift) != 0 && (Keyboard.Modifiers & ModifierKeys.Control) != 0);

                if (disableWordExpansion)
                {
                    anchorWordRange = new TextSegment(anchorPosition, anchorPosition);
                    cursorWordRange = new TextSegment(cursorPosition, cursorPosition);
                }
                else
                {
                    // Autoword expansion heuristics
                    // -----------------------------

                    // Word autoword heuristics:
                    // a) After active end returned to selected area, autoword expansion on active end is disabled
                    // b) After active end returned to the very first word, expansion on anchor word is disabled either
                    //    We do this though only if selection has crossed initial word boundary at least once.
                    // c) After active end crosses new word, autoword expansion of active end is enabled again

                    // Calculate a word range for anchor position
                    anchorWordRange = TextPointerBase.GetWordRange(anchorPosition);

                    // Check if we re-entering selection or moving outside
                    // and set autoexpansion flags accordingly
                    if (_previousCursorPosition != null &&
                        (anchorPosition.CompareTo(cursorPosition) < 0 && cursorPosition.CompareTo(_previousCursorPosition) < 0 ||
                        _previousCursorPosition.CompareTo(cursorPosition) < 0 && cursorPosition.CompareTo(anchorPosition) < 0))
                    {
                        // Re-entering selection.

                        // Store position of reentering
                        _reenterPosition = cursorPosition.CreatePointer();

                        // When re-entering reaches initial word, disable word expansion on anchor end either
                        if (_anchorWordRangeHasBeenCrossedOnce && anchorWordRange.Contains(cursorPosition))
                        {
                            _allowWordExpansionOnAnchorEnd = false;
                        }
                    }
                    else
                    {
                        // Extending the selection.

                        // Check if we are crossing a boundary of last reentered word to re-enable word expansion on moving end
                        if (_reenterPosition != null)
                        {
                            TextSegment lastReenteredWordRange = TextPointerBase.GetWordRange(_reenterPosition);
                            if (!lastReenteredWordRange.Contains(cursorPosition))
                            {
                                _reenterPosition = null;
                            }
                        }
                    }

                    // Identify expanded range on both ends
                    // 

                    if (anchorWordRange.Contains(cursorPosition) ||
                        anchorWordRange.Contains(cursorPosition.GetInsertionPosition(LogicalDirection.Forward)) ||
                        anchorWordRange.Contains(cursorPosition.GetInsertionPosition(LogicalDirection.Backward)))
                    {
                        // Selection does not cross word boundary, so shrink selection to exact anchor/cursor positions
                        anchorWordRange = new TextSegment(anchorPosition, anchorPosition);
                        cursorWordRange = new TextSegment(cursorPosition, cursorPosition);
                    }
                    else
                    {
                        // Selection crosses word boundary.
                        _anchorWordRangeHasBeenCrossedOnce = true;

                        if (!_allowWordExpansionOnAnchorEnd || //
                            TextPointerBase.IsAtWordBoundary(anchorPosition, /*insideWordDirection:*/LogicalDirection.Forward))
                        {
                            // We collapse anchorPosition in two cases:
                            // If we have been re-entering the initial word before -
                            // then we treat it as an indicator that user wants exact position on anchor end
                            // or
                            // if selection starts exactly on word boundary -
                            // then we should not include the following word (when selection extends backward).
                            //
                            // So in the both cases we collapse anchorWordRange to exact _anchorPosition
                            anchorWordRange = new TextSegment(anchorPosition, anchorPosition);
                        }

                        if (TextPointerBase.IsAfterLastParagraph(cursorPosition) ||
                            TextPointerBase.IsAtWordBoundary(cursorPosition, /*insideWordDirection:*/LogicalDirection.Forward))
                        {
                            cursorWordRange = new TextSegment(cursorPosition, cursorPosition);
                        }
                        else
                        {
                            if (_reenterPosition == null)
                            {
                                // We are not in re-entering mode; expand moving end to word boundary
                                cursorWordRange = TextPointerBase.GetWordRange(cursorPosition, cursorPosition.LogicalDirection);
                            }
                            else
                            {
                                // We are in re-entering mode; use exact moving end position
                                cursorWordRange = new TextSegment(cursorPosition, cursorPosition);
                            }
                        }
                    }
                }
            }
        }
コード例 #44
0
        /// <summary>
        /// Returns true if the position is at the word boundary
        /// in the given direction.
        /// </summary>
        /// <param name="thisPosition">ITextPointer to examine.</param>
        /// <param name="insideWordDirection">
        /// If insideWordDirection == LogicalDirection.Forward, returns true iff the
        /// position is at the beginning of a word.
        /// 
        /// If direction == LogicalDirection.Backward, returns true iff the
        /// position is at the end of a word.
        /// </param>
        /// <returns></returns>
        internal static bool IsAtWordBoundary(ITextPointer thisPosition, LogicalDirection insideWordDirection)
        {
            bool isAtWordBoundary;
            ITextPointer navigator = thisPosition.CreatePointer();

            // Skip over any formatting.
            if (navigator.GetPointerContext(insideWordDirection) != TextPointerContext.Text)
            {
                navigator.MoveToInsertionPosition(insideWordDirection);
            }

            if (navigator.GetPointerContext(insideWordDirection) == TextPointerContext.Text)
            {
                // We're adjacent to text, so use the word breaker.

                char[] text;
                int position;

                GetWordBreakerText(thisPosition, out text, out position);

                isAtWordBoundary = SelectionWordBreaker.IsAtWordBoundary(text, position, insideWordDirection);
            }
            else
            {
                // If we're not adjacent to text then we always want to consider this
                // position a "word break" -- as far as selection is concerned.  In practice,
                // we're most likely next to an embedded object or block boundary.
                isAtWordBoundary = true;
            }

            return isAtWordBoundary;
        }
コード例 #45
0
ファイル: CompositionAdorner.cs プロジェクト: JianwenSun/cc
        //------------------------------------------------------
        //
        //  Internal Methods
        //
        //------------------------------------------------------

        #region Internal Methods

        /// <summary>
        /// Add the composition attribute range that will be rendered.
        /// Used in TextServicesDisplayAttributePropertyRanges (for composition display attribute)
        /// </summary>
        internal void AddAttributeRange(ITextPointer start, ITextPointer end, TextServicesDisplayAttribute textServiceDisplayAttribute)
        {
            // Set the range start/end point's logical direction
            ITextPointer rangeStart = start.CreatePointer(LogicalDirection.Forward);
            ITextPointer rangeEnd = end.CreatePointer(LogicalDirection.Backward);

            // Add the composition attribute range
            _attributeRanges.Add(new AttributeRange(_textView, rangeStart, rangeEnd, textServiceDisplayAttribute));
        }
コード例 #46
0
        /// <summary>
        /// Returns a TextSegment covering the word containing this TextPointer.
        /// </summary>
        /// <remarks>
        /// If this TextPointer is between two words, direction specifies whether
        /// the preceeding or following word is returned.
        /// 
        /// The return value includes trailing whitespace, if any.
        /// </remarks>
        internal static TextSegment GetWordRange(ITextPointer thisPosition, LogicalDirection direction)
        {
            if (!thisPosition.IsAtInsertionPosition)
            {
                // Normalize original text pointer so it is at an insertion position.
                thisPosition = thisPosition.GetInsertionPosition(direction);
            }

            if (!thisPosition.IsAtInsertionPosition)
            {
                // In case there is no insertion position in the entire document, return an empty segment.
                // GetInsertionPosition() guarantees that navigator is moved back to original position.
                return new TextSegment(thisPosition, thisPosition);
            }

            // Find the next word end edge.
            ITextPointer navigator = thisPosition.CreatePointer();
            bool moved = MoveToNextWordBoundary(navigator, direction);

            ITextPointer wordEnd = navigator;

            // Find the corresponding word start edge.
            ITextPointer wordStart;
            if (moved && IsAtWordBoundary(thisPosition, /*insideWordDirection:*/LogicalDirection.Forward))
            {
                wordStart = thisPosition;
            }
            else
            {
                navigator = thisPosition.CreatePointer();
                MoveToNextWordBoundary(navigator, direction == LogicalDirection.Backward ? LogicalDirection.Forward : LogicalDirection.Backward);
                wordStart = navigator;
            }

            if (direction == LogicalDirection.Backward)
            {
                // If this is a backward search, need to swap start/end pointers.
                navigator = wordStart;
                wordStart = wordEnd;
                wordEnd = navigator;
            }

            // Make sure that we are not crossing any block boundaries.
            wordStart = RestrictWithinBlock(thisPosition, wordStart, LogicalDirection.Backward);
            wordEnd = RestrictWithinBlock(thisPosition, wordEnd, LogicalDirection.Forward);

            // Make sure that positions do not cross - as in TextRangeBase.cs
            if (wordStart.CompareTo(wordEnd) < 0)
            {
                wordStart = wordStart.GetFrozenPointer(LogicalDirection.Backward);
                wordEnd = wordEnd.GetFrozenPointer(LogicalDirection.Forward);
            }
            else
            {
                wordStart = wordEnd.GetFrozenPointer(LogicalDirection.Backward);
                wordEnd = wordStart;
            }

            Invariant.Assert(wordStart.CompareTo(wordEnd) <= 0, "expecting wordStart <= wordEnd");
            return new TextSegment(wordStart, wordEnd);
        }
コード例 #47
0
ファイル: TextFindEngine.cs プロジェクト: yk2012985/wpf
        //---------------------------------------------------------------------
        //
        // Private methods
        //
        //---------------------------------------------------------------------

        #region Private Methods

        // Find the text with the specified find options.
        internal static TextRange InternalFind(
            ITextPointer startPosition,
            ITextPointer endPosition,
            string findPattern,
            CultureInfo cultureInfo,
            bool matchCase,
            bool matchWholeWord,
            bool matchLast,
            bool matchDiacritics,
            bool matchKashida,
            bool matchAlefHamza)
        {
            Invariant.Assert(startPosition.CompareTo(endPosition) <= 0);

            ITextPointer     navigator;
            LogicalDirection direction;

            char[] findText;
            int[]  findTextPositionMap;
            int    findTextLength;

            if (matchLast)
            {
                navigator = endPosition;
                direction = LogicalDirection.Backward;
            }
            else
            {
                navigator = startPosition;
                direction = LogicalDirection.Forward;
            }

            // Set the text block size to read the find text content.
            // The block size must be bigger than the double of find pattern size
            // so that we can find matches intersected by neighboring blocks.
            // We need an additional x2 fudge factor to account for the matchDiacritics
            // option -- the findPattern may lack diacritics that will be ignored in
            // the text.
            int textBlockLength = Math.Max(TextBlockLength, findPattern.Length * 2 * 2);

            navigator = navigator.CreatePointer();

            while ((matchLast ? startPosition.CompareTo(navigator) : navigator.CompareTo(endPosition)) < 0)
            {
                ITextPointer startFindTextPosition = navigator.CreatePointer();

                findText            = new char[textBlockLength];
                findTextPositionMap = new int[textBlockLength + 1];

                // Set the find text content from reading text of the current text position.
                // Set the find text position map as well to track of the text pointer of the text content.
                findTextLength = SetFindTextAndFindTextPositionMap(
                    startPosition,
                    endPosition,
                    navigator,
                    direction,
                    matchLast,
                    findText,
                    findTextPositionMap);

                if (!matchDiacritics || findTextLength >= findPattern.Length)
                {
                    int textStartIndex = matchLast ? findText.Length - findTextLength : 0;

                    // Track whether or not the text array findText is bounded by
                    // separator chars.  We only look at these values when matchWholeWord
                    // is true.
                    bool hasPreceedingSeparatorChar = false;
                    bool hasFollowingSeparatorChar  = false;

                    if (matchWholeWord)
                    {
                        GetContextualInformation(startFindTextPosition, matchLast ? -findTextPositionMap[findTextPositionMap.Length - findTextLength - 1] : findTextPositionMap[findTextLength],
                                                 out hasPreceedingSeparatorChar, out hasFollowingSeparatorChar);
                    }

                    string textString = new string(findText, textStartIndex, findTextLength);
                    int    matchLength;

                    // Now find text the matched index for the find pattern from the find text content
                    int matchIndex = FindMatchIndexFromFindContent(
                        textString,
                        findPattern,
                        cultureInfo,
                        matchCase,
                        matchWholeWord,
                        matchLast,
                        matchDiacritics,
                        matchKashida,
                        matchAlefHamza,
                        hasPreceedingSeparatorChar,
                        hasFollowingSeparatorChar,
                        out matchLength);

                    if (matchIndex != -1)
                    {
                        // Found the find pattern string from the find text content!
                        // Return the text range for the matched find text position.

                        ITextPointer startMatchPosition = startFindTextPosition.CreatePointer();
                        startMatchPosition.MoveByOffset(matchLast ? -findTextPositionMap[textStartIndex + matchIndex] : findTextPositionMap[matchIndex]);

                        ITextPointer endMatchPosition = startFindTextPosition.CreatePointer();
                        endMatchPosition.MoveByOffset(matchLast ? -findTextPositionMap[textStartIndex + matchIndex + matchLength] : findTextPositionMap[matchIndex + matchLength]);

                        return(new TextRange(startMatchPosition, endMatchPosition));
                    }

                    // Move the text position for the size of finding pattern string not to miss
                    // the matching text that is located on the boundary of the find text block.
                    // Move back the position to N(findTextLength) - findPattern.Length
                    if (findTextLength > findPattern.Length)
                    {
                        // Need to set new pointer to jump the correct place of backing offset of the findPattern length
                        navigator = startFindTextPosition.CreatePointer();
                        navigator.MoveByOffset(matchLast ? -findTextPositionMap[findText.Length - findTextLength + findPattern.Length] : findTextPositionMap[findTextLength - findPattern.Length]);
                    }
                }
            }

            return(null);
        }
コード例 #48
0
        // <see cref="TextPointer.GetCharacterRect"/>
        internal static Rect GetCharacterRect(ITextPointer thisPointer, LogicalDirection direction, bool transformToUiScope)
        {
            ITextView textView = thisPointer.TextContainer.TextView;

            Invariant.Assert(textView != null, "Null TextView!"); // Did you check ITextPointer.HasValidLayout?
            Invariant.Assert(textView.RenderScope != null, "Null RenderScope");
            Invariant.Assert(thisPointer.TextContainer != null, "Null TextContainer");
            Invariant.Assert(thisPointer.TextContainer.Parent != null, "Null parent of TextContainer");

            // Try to ask for a Rect from an insertion position.
            if (!thisPointer.IsAtInsertionPosition)
            {
                ITextPointer insertionPosition = thisPointer.GetInsertionPosition(direction);

                if (insertionPosition != null)
                {
                    thisPointer = insertionPosition;
                }
            }

            Rect rect = textView.GetRectangleFromTextPosition(thisPointer.CreatePointer(direction));

            if (transformToUiScope)
            {
                Visual templatedParent;

                if (thisPointer.TextContainer.Parent is FlowDocument && textView.RenderScope is FlowDocumentView)
                {
                    // 
                    templatedParent = ((FlowDocumentView)textView.RenderScope).TemplatedParent as Visual;
                    if (templatedParent == null && ((FlowDocumentView)textView.RenderScope).Parent is FrameworkElement)
                    {
                        templatedParent = ((FrameworkElement)((FlowDocumentView)textView.RenderScope).Parent).TemplatedParent as Visual;
                    }
                }
                else if (thisPointer.TextContainer.Parent is Visual)
                {
                    Invariant.Assert(textView.RenderScope == thisPointer.TextContainer.Parent || ((Visual)thisPointer.TextContainer.Parent).IsAncestorOf( /*descendant:*/textView.RenderScope),
                        "Unexpected location of RenderScope within visual tree");
                    templatedParent = (Visual)thisPointer.TextContainer.Parent;
                }
                else
                {
                    templatedParent = null;
                }

                if (templatedParent != null && templatedParent.IsAncestorOf( /*descendant:*/textView.RenderScope))
                {
                    // translate the rect from renderscope to uiscope coordinate system (from FlowDocumentView to RichTextBox)
                    GeneralTransform transformFromRenderToUiScope = textView.RenderScope.TransformToAncestor(/*ancestor:*/templatedParent);

                    rect = transformFromRenderToUiScope.TransformBounds(rect);
                }
            }

            return rect;
        }
コード例 #49
0
        // Verify that a pointer is an acceptable ancestor.  Some types can't be ancestors at all, while
        // non-typographic-only elements are unacceptable if the range being serialized does not include the
        // element's start and end (because we don't want to serialize properties on such an element).
        private static bool IsAcceptableAncestor(ITextPointer commonAncestor, ITextRange range)
        {
            if (typeof(TableRow).IsAssignableFrom(commonAncestor.ParentType) ||
                typeof(TableRowGroup).IsAssignableFrom(commonAncestor.ParentType) ||
                typeof(Table).IsAssignableFrom(commonAncestor.ParentType) ||
                typeof(BlockUIContainer).IsAssignableFrom(commonAncestor.ParentType) ||
                typeof(List).IsAssignableFrom(commonAncestor.ParentType) ||
                typeof(Inline).IsAssignableFrom(commonAncestor.ParentType) && TextSchema.HasTextDecorations(commonAncestor.GetValue(Inline.TextDecorationsProperty)))
            {
                return false;
            }

            // We don't want to use any formatting from within a non-typographic-only element unless the entire
            // element is selected (in which case, the ancestor candidate will already be outside that element.
            // If there is such an element ANYWHERE in the ancestry, the only acceptable
            // ancestor is outside the outermost such element.
            ITextPointer navigator = commonAncestor.CreatePointer();
            while (typeof(TextElement).IsAssignableFrom(navigator.ParentType))
            {
                TextElementEditingBehaviorAttribute behaviorAttribute = (TextElementEditingBehaviorAttribute)Attribute.GetCustomAttribute(navigator.ParentType, typeof(TextElementEditingBehaviorAttribute));
                if (behaviorAttribute != null && !behaviorAttribute.IsTypographicOnly)
                {
                    return false;
                }
                navigator.MoveToElementEdge(ElementEdge.BeforeStart);
            }

            return true;
        }
コード例 #50
0
        /// <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;
        }
コード例 #51
0
        /// <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;
        }
コード例 #52
0
ファイル: TextStore.cs プロジェクト: mind0n/hive
        /// <summary>
        /// Computes the bounds for a given text segment, provided that the entire segment
        /// is located on a single text line.
        /// </summary>
        private static Rect GetLineBounds(ITextPointer start, ITextPointer end)
        {
            // Get the line range.
            if (!start.HasValidLayout || !end.HasValidLayout)
            {
                return Rect.Empty;
            }

            // Get the left and the width of the range bounds.
            Rect lineBounds = start.GetCharacterRect(LogicalDirection.Forward);
            lineBounds.Union(end.GetCharacterRect(LogicalDirection.Backward));

            // Scan the line range and compute the top and the height of the bounding rectangle.
            ITextPointer navigator = start.CreatePointer(LogicalDirection.Forward);
            while (navigator.MoveToNextContextPosition(LogicalDirection.Forward) == true && navigator.CompareTo(end) < 0)
            {
                TextPointerContext context = navigator.GetPointerContext(LogicalDirection.Backward);
                switch (context)
                {
                    case TextPointerContext.ElementStart:
                        lineBounds.Union(navigator.GetCharacterRect(LogicalDirection.Backward));
                        navigator.MoveToElementEdge(ElementEdge.AfterEnd);
                        break;
                    case TextPointerContext.ElementEnd:
                    case TextPointerContext.EmbeddedElement:
                        lineBounds.Union(navigator.GetCharacterRect(LogicalDirection.Backward));
                        break;
                    case TextPointerContext.Text:
                        break;
                    default:
                        // Unexpected
                        Invariant.Assert(context != TextPointerContext.None);
                        break;
                }
            }

            return lineBounds;
        }
コード例 #53
0
        /// <summary>
        /// Walks the tree up from current position and writes all scoping tags
        /// in their natural order - from root to leafs.
        /// </summary>
        /// <param name="range">
        /// Range identifying the whole selection.
        /// Needed for
        /// - table cell range case: proper column processing: to output only columns related to the selection
        /// - text segement case: hyperlink serialization heuristics
        /// </param>
        /// <param name="thisElement">
        /// ITextPointer identifying an element.
        /// </param>
        /// <param name="scope">
        /// A position identifying the scope which should be used for serialization.
        /// All tags outside of this scope will be ignored.
        /// </param>
        /// <param name="xmlWriter">
        /// XmlWriter to write element tags.
        /// </param>
        /// <param name="xamlTypeMapper"></param>
        /// <param name="reduceElement">
        /// <see cref="WriteStartXamlElement"/>
        /// </param>
        /// <param name="ignoreWriteHyperlinkEnd"></param>
        /// <param name="ignoreList"></param>
        /// <param name="preserveTextElements"></param>
        /// /// <returns>
        /// Number of opening tags written into XmlWriter.
        /// This number should be used afterwards to close all opened tags.
        /// </returns>
        private static int WriteOpeningTags(ITextRange range, ITextPointer thisElement, ITextPointer scope, XmlWriter xmlWriter, XamlTypeMapper xamlTypeMapper, bool reduceElement, out bool ignoreWriteHyperlinkEnd, ref List<int> ignoreList, bool preserveTextElements)
        {
            ignoreWriteHyperlinkEnd = false;

            // Recursion ends when we reach the scope level. We will write tags on returing path from the recursion
            if (thisElement.HasEqualScope(scope))
            {
                return 0; // no elements have opened at this level. Return elementCount==0.
            }

            Invariant.Assert(typeof(TextElement).IsAssignableFrom(thisElement.ParentType), "thisElement is expected to be a TextElement");

            ITextPointer previousLevel = thisElement.CreatePointer();
            previousLevel.MoveToElementEdge(ElementEdge.BeforeStart);

            // Recurse into the parent element
            int elementLevel = WriteOpeningTags(range, previousLevel, scope, xmlWriter, xamlTypeMapper, reduceElement, out ignoreWriteHyperlinkEnd, ref ignoreList, preserveTextElements);

            // After returning from the recursion - when all parent tags have been written,
            // write the opening tag for this element

            // Hyperlink open tag will be skipped since the range selection of Hyperlink is the partial
            // of Hyperlink range or Hyperlink include invalid UIElement except Image.
            bool ignoreHyperlink = false;
            bool isPartialNonTypographic = false;

            if (thisElement.ParentType == typeof(Hyperlink))
            {
                if (TextPointerBase.IsAtNonMergeableInlineStart(range.Start))
                {
                    ITextPointer position = thisElement.CreatePointer();
                    position.MoveToElementEdge(ElementEdge.BeforeStart);

                    ignoreHyperlink = IsHyperlinkInvalid(position, range.End);
                }
                else
                {
                    ignoreHyperlink = true;
                }
            }
            else
            {
                // 

                TextElementEditingBehaviorAttribute att = (TextElementEditingBehaviorAttribute)Attribute.GetCustomAttribute(thisElement.ParentType, typeof(TextElementEditingBehaviorAttribute));
                if (att != null && !att.IsTypographicOnly)
                {
                    if (TextPointerBase.IsAtNonMergeableInlineStart(range.Start))
                    {
                        ITextPointer position = thisElement.CreatePointer();
                        position.MoveToElementEdge(ElementEdge.BeforeStart);

                        isPartialNonTypographic = IsPartialNonTypographic(position, range.End);
                    }
                    else
                    {
                        isPartialNonTypographic = true;
                    }
                }
            }
            int count;

            if (ignoreHyperlink)
            {
                // Ignore writing Hyperlink opening tag
                ignoreWriteHyperlinkEnd = true;

                // Set elementLevel without adding it
                count = elementLevel;
            }
            else if (isPartialNonTypographic)
            {
                // Add the end pointer to the list
                ITextPointer position = thisElement.CreatePointer();
                position.MoveToElementEdge(ElementEdge.BeforeEnd);
                ignoreList.Add(position.Offset);

                // Set elementLevel without adding to it
                count = elementLevel;
            }
            else
            {
                // Write the opening tag 
                WriteStartXamlElement(range, thisElement, xmlWriter, xamlTypeMapper, reduceElement, preserveTextElements);

                // Each opening tag adds one to the level count
                count = elementLevel + 1;
            }

            // Return the opening tag count
            return count;
        }
コード例 #54
0
        /// <summary>
        /// This helper method is used by TextRangeAdaptor to bring the range into view
        /// through multiple nested scroll providers.
        /// </summary>
        internal void ScrollIntoView(ITextPointer start, ITextPointer end, bool alignToTop)
        {
            // Calculate the bounding rectangle for the range
            Rect rangeBounds = Rect.Empty;
            Rect[] lineBounds = GetBoundingRectangles(start, end, false, false);
            foreach (Rect rect in lineBounds)
            {
                rangeBounds.Union(rect);
            }

            ITextView textView = GetUpdatedTextView();
            if (textView != null && !rangeBounds.IsEmpty)
            {
                // Find out the visible portion of the range.
                Rect visibleRect = GetVisibleRectangle(textView);
                Rect rangeVisibleBounds = Rect.Intersect(rangeBounds, visibleRect);
                if (rangeVisibleBounds == rangeBounds)
                {
                    // The range is already in the view. It's probably not aligned as requested, 
                    // but who cares since it's entirely visible anyway.
                    return;
                }

                // Ensure the visibility of the range. 
                // BringIntoView will do most of the magic except the very first scroll
                // in order to satisfy the requested alignment.
                UIElement renderScope = textView.RenderScope;
                Visual visual = renderScope;
                while (visual != null)
                {
                    IScrollInfo isi = visual as IScrollInfo;
                    if (isi != null)
                    {
                        // Transform the bounding rectangle into the IScrollInfo coordinates.
                        if (visual != renderScope)
                        {
                            GeneralTransform childToParent = renderScope.TransformToAncestor(visual);
                            rangeBounds = childToParent.TransformBounds(rangeBounds);
                        }

                        if (isi.CanHorizontallyScroll)
                        {
                            isi.SetHorizontalOffset(alignToTop ? rangeBounds.Left : (rangeBounds.Right - isi.ViewportWidth));
                        }
                        if (isi.CanVerticallyScroll)
                        {
                            isi.SetVerticalOffset(alignToTop ? rangeBounds.Top : (rangeBounds.Bottom - isi.ViewportHeight));
                        }
                        break;
                    }
                    visual = VisualTreeHelper.GetParent(visual) as Visual;
                }

                FrameworkElement fe = renderScope as FrameworkElement;
                if (fe != null)
                {
                    fe.BringIntoView(rangeVisibleBounds);
                }
            }
            else
            {
                // If failed to retrive range bounds, try to Bring into view closes element.
                ITextPointer pointer = alignToTop ? start.CreatePointer() : end.CreatePointer();
                pointer.MoveToElementEdge(alignToTop ? ElementEdge.AfterStart : ElementEdge.AfterEnd);
                FrameworkContentElement element = pointer.GetAdjacentElement(LogicalDirection.Backward) as FrameworkContentElement;
                if (element != null)
                {
                    element.BringIntoView();
                }
            }
        }
コード例 #55
0
        // Writes a collection of attributes representing non-inheritable properties
        // whose values are set inline on the given element instance.
        // When we read properties fromContext we want all values including defaults; from text elements we only want only affected
        private static void WriteNoninheritableProperties(Type elementTypeStandardized, ITextPointer context, XmlWriter xmlWriter, bool onlyAffected, DependencyObject complexProperties)
        {
            DependencyProperty[] elementProperties = TextSchema.GetNoninheritableProperties(elementTypeStandardized);

            // We'll need a pointer to walk the tree up when onlyAffected=false
            ITextPointer parentContext = onlyAffected ? null : context.CreatePointer();

            for (int i = 0; i < elementProperties.Length; i++)
            {
                DependencyProperty property = elementProperties[i];
                Type propertyOwnerType = context.ParentType;

                object propertyValue;
                if (onlyAffected)
                {
                    // 

                    propertyValue = context.GetValue(property);
                }
                else
                {
                    // This is request for contextual properties - use "manual" inheritance to collect values
                    Invariant.Assert(elementTypeStandardized == typeof(Span), "Request for contextual properties is expected for Span wrapper only");

                    // Get property value from this element or from one of its ancestors (the latter in case of !onlyAffeted)
                    propertyValue = context.GetValue(property);

                    // Get property value from its ancestors if the property is not set. 
                    // TextDecorationCollection is special-cased as its default is empty collection, 
                    // and its value source cannot be distinguished from ITextPointer. 
                    if (propertyValue == null || TextDecorationCollection.Empty.ValueEquals(propertyValue as TextDecorationCollection))
                    {
                        if (property == Inline.BaselineAlignmentProperty || property == TextElement.TextEffectsProperty)
                        {
                            // These properties do not make sense as contextual; do not include them into context.
                            continue;
                        }

                        parentContext.MoveToPosition(context);
                        while ((propertyValue == null || TextDecorationCollection.Empty.ValueEquals(propertyValue as TextDecorationCollection))
                            && typeof(Inline).IsAssignableFrom(parentContext.ParentType))
                        {
                            parentContext.MoveToElementEdge(ElementEdge.BeforeStart);
                            propertyValue = parentContext.GetValue(property);
                            propertyOwnerType = parentContext.ParentType;
                        }
                    }
                }

                // 








                if ((property == Block.MarginProperty && (typeof(Paragraph).IsAssignableFrom(propertyOwnerType) || typeof(List).IsAssignableFrom(propertyOwnerType)))
                    ||
                    (property == Block.PaddingProperty) && typeof(List).IsAssignableFrom(propertyOwnerType))
                {
                    Thickness thickness = (Thickness)propertyValue;
                    if (Paragraph.IsMarginAuto(thickness))
                    {
                        continue;
                    }
                }

                // Write the property as attribute string or add it to a list of complex properties.
                WriteNoninheritableProperty(xmlWriter, property, propertyValue, propertyOwnerType, onlyAffected, complexProperties, context.ReadLocalValue(property));
            }
        }
コード例 #56
0
        //-------------------------------------------------------------------
        //
        //  Internal Methods
        //
        //-------------------------------------------------------------------

        #region Internal Methods

        /// <summary>
        /// Retrieves the bounding rectangles for the text lines of a given range.  
        /// </summary>
        /// <param name="start">Start of range to measure</param>
        /// <param name="end">End of range to measure</param>
        /// <param name="clipToView">Specifies whether the caller wants the full bounds (false) or the bounds of visible portions 
        /// of the viewable line only ('true')</param>
        /// <param name="transformToScreen">Requests the results in screen coordinates</param>
        /// <returns>An array of bounding rectangles for each line or portion of a line within the client area of the text provider.
        /// No bounding rectangles will be returned for lines that are empty or scrolled out of view.  Note that even though a
        /// bounding rectangle is returned the corresponding text may not be visible due to overlapping windows.
        /// This will not return null, but may return an empty array.</returns>
        internal Rect[] GetBoundingRectangles(ITextPointer start, ITextPointer end, bool clipToView, bool transformToScreen)
        {
            ITextView textView = GetUpdatedTextView();
            if (textView == null)
            {
                return new Rect[0];
            }

            // If start/end positions are not in the visible range, move them to the first/last visible positions.
            ReadOnlyCollection<TextSegment> textSegments = textView.TextSegments;
            if (textSegments.Count > 0)
            {
                if (!textView.Contains(start) && start.CompareTo(textSegments[0].Start) < 0)
                {
                    start = textSegments[0].Start.CreatePointer(); ;
                }
                if (!textView.Contains(end) && end.CompareTo(textSegments[textSegments.Count-1].End) > 0)
                {
                    end = textSegments[textSegments.Count - 1].End.CreatePointer();
                }
            }
            if (!textView.Contains(start) || !textView.Contains(end))
            {
                return new Rect[0];
            }

            TextRangeAdaptor.MoveToInsertionPosition(start, LogicalDirection.Forward);
            TextRangeAdaptor.MoveToInsertionPosition(end, LogicalDirection.Backward);

            Rect visibleRect = Rect.Empty;
            if (clipToView)
            {
                visibleRect = GetVisibleRectangle(textView);
                // If clipping into view and visible rect is empty, return.
                if (visibleRect.IsEmpty)
                {
                    return new Rect[0];
                }
            }

            List<Rect> rectangles = new List<Rect>();
            ITextPointer position = start.CreatePointer();
            while (position.CompareTo(end) < 0)
            {
                TextSegment lineRange = textView.GetLineRange(position);
                if (!lineRange.IsNull)
                {
                    // Since range is limited to just one line, GetTightBoundingGeometry will return tight bounding
                    // rectangle for given range. It will also work correctly with bidi text.
                    ITextPointer first = (lineRange.Start.CompareTo(start) <= 0) ? start : lineRange.Start;
                    ITextPointer last = (lineRange.End.CompareTo(end) >= 0) ? end : lineRange.End;
                    Rect lineRect = Rect.Empty;
                    Geometry geometry = textView.GetTightBoundingGeometryFromTextPositions(first, last);
                    if (geometry != null)
                    {
                        lineRect = geometry.Bounds;
                        if (clipToView)
                        {
                            lineRect.Intersect(visibleRect);
                        }
                        if (!lineRect.IsEmpty)
                        {
                            if (transformToScreen)
                            {
                                lineRect = new Rect(ClientToScreen(lineRect.TopLeft, textView.RenderScope), ClientToScreen(lineRect.BottomRight, textView.RenderScope));
                            }
                            rectangles.Add(lineRect);
                        }
                    }
                }
                if (position.MoveToLineBoundary(1) == 0)
                {
                    position = end;
                }
            }
            return rectangles.ToArray();
        }
コード例 #57
0
ファイル: FixedTextView.cs プロジェクト: dox0/DotNet471RS3
        /// <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);
        }
コード例 #58
0
ファイル: TextSelection.cs プロジェクト: JianwenSun/cc
        /// <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);
            }
        }
コード例 #59
0
        // Walks parents from this position until it hits limiting ancestor type.
        private static bool IsInAncestorScope(ITextPointer position, Type allowedParentType, Type limitingType)
        {
            ITextPointer navigator = position.CreatePointer();
            Type parentType = navigator.ParentType;

            while (parentType != null && allowedParentType.IsAssignableFrom(parentType))
            {
                if (limitingType.IsAssignableFrom(parentType))
                {
                    return true;
                }
                navigator.MoveToElementEdge(ElementEdge.BeforeStart);
                parentType = navigator.ParentType;
            }

            return false;
        }
コード例 #60
0
ファイル: TextSelection.cs プロジェクト: JianwenSun/cc
        // Extends the selection to the mouse cursor position.
        void ITextSelection.ExtendSelectionByMouse(ITextPointer cursorPosition, bool forceWordSelection, bool forceParagraphSelection)
        {
            ITextSelection thisSelection = (ITextSelection)this;

            // Check whether the cursor has been actually moved - compare with the previous position
            if (forceParagraphSelection || _previousCursorPosition != null && cursorPosition.CompareTo(_previousCursorPosition) == 0)
            {
                // Mouse was not actually moved. Ignore the event.
                return;
            }

            thisSelection.BeginChange();
            try
            {
                if (!BeginMouseSelectionProcess(cursorPosition))
                {
                    return;
                }

                // Get anchor position
                ITextPointer anchorPosition = ((ITextSelection)this).AnchorPosition;

                // Identify words on selection ends
                TextSegment anchorWordRange;
                TextSegment cursorWordRange;
                IdentifyWordsOnSelectionEnds(anchorPosition, cursorPosition, forceWordSelection, out anchorWordRange, out cursorWordRange);

                // Calculate selection boundary positions
                ITextPointer startPosition;
                ITextPointer movingPosition;
                if (anchorWordRange.Start.CompareTo(cursorWordRange.Start) <= 0)
                {
                    startPosition = anchorWordRange.Start.GetFrozenPointer(LogicalDirection.Forward);
                    movingPosition = cursorWordRange.End.GetFrozenPointer(LogicalDirection.Backward); ;
                }
                else
                {
                    startPosition = anchorWordRange.End.GetFrozenPointer(LogicalDirection.Backward);
                    movingPosition = cursorWordRange.Start.GetFrozenPointer(LogicalDirection.Forward); ;
                }

                // Note that we use includeCellAtMovingPosition=true because we want that hit-tested table cell
                // be included into selection no matter whether it's empty or not.
                TextRangeBase.Select(this, startPosition, movingPosition, /*includeCellAtMovingPosition:*/true);
                SetActivePositions(anchorPosition, movingPosition);

                // Store previous cursor position - for the next extension event
                _previousCursorPosition = cursorPosition.CreatePointer();

                Invariant.Assert(thisSelection.Contains(thisSelection.AnchorPosition));
            }
            finally
            {
                thisSelection.EndChange();
            }
        }