GetPositionAtOffset() public method

public GetPositionAtOffset ( int offset, LogicalDirection direction ) : TextPointer
offset int
direction LogicalDirection
return TextPointer
Example #1
0
        TextPointer GetTextPositionAtOffset(TextPointer position, int characterCount)
        {
            while (position != null)
            {
                var context = position.GetPointerContext(LogicalDirection.Forward);
                if (context == TextPointerContext.Text)
                {
                    var count = position.GetTextRunLength(LogicalDirection.Forward);
                    if (characterCount <= count)
                    {
                        return position.GetPositionAtOffset(characterCount);
                    }

                    characterCount -= count;
                }
                else if (position.Parent is LineBreak)
                {
                    var count = 2;
                    if (characterCount <= count)
                    {
                        return position.GetPositionAtOffset(characterCount);
                    }

                    characterCount -= count;
                }
                
                var nextContextPosition = position.GetNextContextPosition(LogicalDirection.Forward);
                if (nextContextPosition == null)
                    return position;

                position = nextContextPosition;
            }

            return position;
        }
Example #2
0
        public static swd.TextPointer GetTextPositionAtOffset(this swd.TextPointer position, int characterCount)
        {
            while (position != null)
            {
                if (position.GetPointerContext(swd.LogicalDirection.Forward) == swd.TextPointerContext.Text)
                {
                    int count = position.GetTextRunLength(swd.LogicalDirection.Forward);
                    if (count >= characterCount)
                    {
                        return(position.GetPositionAtOffset(characterCount));
                    }

                    characterCount -= count;
                }

                var nextContextPosition = position.GetNextContextPosition(swd.LogicalDirection.Forward);
                if (nextContextPosition == null)
                {
                    return(position);
                }

                position = nextContextPosition;
            }

            return(position);
        }
Example #3
0
        internal static TextPointer SafePositionAtOffset(FlowDocument document, TextPointer textPointer, int offsetStart)
        {
            var pointer = textPointer.GetPositionAtOffset(offsetStart);
            if (pointer == null)
                    return document.ContentEnd;

            return pointer;
        }
Example #4
0
        public static TextPointer RemoveHyperlink(TextPointer start)
        {
            var backspacePosition = start.GetNextInsertionPosition(LogicalDirection.Backward);
            Hyperlink hyperlink;
            if (backspacePosition == null || !IsHyperlinkBoundaryCrossed(start, backspacePosition, out hyperlink))
            {
                return null;
            }

            // Remember caretPosition with forward gravity. This is necessary since we are going to delete
            // the hyperlink element preceeding caretPosition and after deletion current caretPosition
            // (with backward gravity) will follow content preceeding the hyperlink.
            // We want to remember content following the hyperlink to set new caret position at.

            var newCaretPosition = start.GetPositionAtOffset(0, LogicalDirection.Forward);

            // Deleting the hyperlink is done using logic below.

            // 1. Copy its children Inline to a temporary array.
            var hyperlinkChildren = hyperlink.Inlines;
            var inlines = new Inline[hyperlinkChildren.Count];
            hyperlinkChildren.CopyTo(inlines, 0);

            // 2. Remove each child from parent hyperlink element and insert it after the hyperlink.
            for (int i = inlines.Length - 1; i >= 0; i--)
            {
                hyperlinkChildren.Remove(inlines[i]);
                hyperlink.SiblingInlines.InsertAfter(hyperlink, inlines[i]);
            }

            // 3. Apply hyperlink's local formatting properties to inlines (which are now outside hyperlink scope).
            var localProperties = hyperlink.GetLocalValueEnumerator();
            var inlineRange = new TextRange(inlines[0].ContentStart, inlines[inlines.Length - 1].ContentEnd);

            while (localProperties.MoveNext())
            {
                var property = localProperties.Current;
                var dp = property.Property;
                object value = property.Value;

                if (!dp.ReadOnly &&
                    dp != Inline.TextDecorationsProperty && // Ignore hyperlink defaults.
                    dp != TextElement.ForegroundProperty &&
                    dp != BaseUriHelper.BaseUriProperty &&
                    !IsHyperlinkProperty(dp))
                {
                    inlineRange.ApplyPropertyValue(dp, value);
                }
            }

            // 4. Delete the (empty) hyperlink element.
            hyperlink.SiblingInlines.Remove(hyperlink);

            return newCaretPosition;
        }
        private static TextRange FindWordFromPosition(TextPointer position, string word)
        {
            while (position != null)
            {
                if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
                {
                    string textRun = position.GetTextInRun(LogicalDirection.Forward);

                    // Find the starting index of any substring that matches "word".
                    int indexInRun = textRun.IndexOf(word);
                    if (indexInRun >= 0)
                    {
                        TextPointer start = position.GetPositionAtOffset(indexInRun);
                        TextPointer end = start.GetPositionAtOffset(word.Length);
                        return new TextRange(start, end);
                    }
                }

                position = position.GetNextContextPosition(LogicalDirection.Forward);
            }

            // position will be null if "word" is not found.
            return null;
        }
Example #6
0
 public Word(TextPointer wordStart, TextPointer wordEnd)
 {
     _wordStart = wordStart.GetPositionAtOffset(0, LogicalDirection.Forward);
     _wordEnd = wordEnd.GetPositionAtOffset(0, LogicalDirection.Backward);
 }
Example #7
0
        public BufferCell GetCell(TextPointer position, LogicalDirection direction)
        {
            TextRange range = null;
            try
            {
                range = new TextRange(position, position.GetPositionAtOffset(1, direction));

                return new BufferCell(
                        (range.IsEmpty || range.Text[0] == '\n') ? ' ' : range.Text[0],
                        ConsoleColorFromBrush((Brush)range.GetPropertyValue(TextElement.ForegroundProperty)),
                        ConsoleColorFromBrush((Brush)range.GetPropertyValue(TextElement.BackgroundProperty)),
                        BufferCellType.Complete);
            }
            catch
            {
                return new BufferCell();
            }
        }
Example #8
0
        // Helper that walks Run and Span elements between start and end positions, 
        // clearing value of passed formattingProperty on them.
        // 
        private static void ClearPropertyValueFromSpansAndRuns(TextPointer start, TextPointer end, DependencyProperty formattingProperty)
        {
            // Normalize start position forward.
            start = start.GetPositionAtOffset(0, LogicalDirection.Forward); 

            // Move to next context position before entering loop below, 
            // since in the loop we look backward. 
            start = start.GetNextContextPosition(LogicalDirection.Forward);
 
            while (start != null && start.CompareTo(end) < 0)
            {
                if (start.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.ElementStart &&
                    TextSchema.IsFormattingType(start.Parent.GetType())) // look for Run/Span elements 
                {
                    start.Parent.ClearValue(formattingProperty); 
 
                    // Remove unnecessary Spans around this position, delete empty formatting elements (if any)
                    // and merge with adjacent inlines if they have identical set of formatting properties. 
                    MergeFormattingInlines(start);
                }

                start = start.GetNextContextPosition(LogicalDirection.Forward); 
            }
        } 
        List<TextRange> FindWordFromPosition(TextPointer position, string word)
        {
            List<TextRange> ranges = new List<TextRange>();
            while (position != null)
            {
                if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
                {
                    string textRun = position.GetTextInRun(LogicalDirection.Forward);

                    // Find the starting index of any substring that matches "word".
                    int indexInRun = textRun.IndexOf(word);
                    if (indexInRun >= 0)
                    {
                        TextPointer start = position.GetPositionAtOffset(indexInRun);
                        TextPointer end = start.GetPositionAtOffset(word.Length);
                        ranges.Add(new TextRange(start, end));
                    }
                }
                position = position.GetNextContextPosition(LogicalDirection.Forward);
            }
            return ranges;
        }
        /// <summary>
        /// Find the corresponding <see cref="TextRange"/> instance 
        /// representing the input string given a specified text pointer position.
        /// </summary>
        /// <param name="position">the current text position</param>
        /// <param name="textToFind">input text</param>
        /// <param name="findOptions">the search option</param>
        /// <returns>An <see cref="TextRange"/> instance represeneting the matching string withing the text container.</returns>
        public TextRange GetTextRangeFromPosition(ref TextPointer position, String input, FindOptions findOptions)
        {
            Boolean matchCase = findOptions.MatchCase;
            Boolean matchWholeWord = findOptions.MatchWholeWord;

            TextRange textRange = null;

            while (position != null)
            {
                if (position.CompareTo(inputDocument.ContentEnd) == 0) //到了文档结尾
                {
                    break;
                }
                //是文本元素
                if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
                {
                    String textRun = position.GetTextInRun(LogicalDirection.Forward);  //读取文本
                    StringComparison stringComparison = matchCase ? StringComparison.CurrentCulture : StringComparison.CurrentCultureIgnoreCase;
                  //进行查找
                    Int32 indexInRun = textRun.IndexOf(input, stringComparison);

                    if (indexInRun >= 0)  //找到了
                    {
                        position = position.GetPositionAtOffset(indexInRun);  //移动文字指针到开头
                        TextPointer nextPointer = position.GetPositionAtOffset(input.Length); //设定匹配项尾文字指针
                        textRange = new TextRange(position, nextPointer);

                        if (matchWholeWord) //是全字匹配的话
                        {
                            if (IsWholeWord(textRange)) // 测试匹配项是否是一个单词
                            {
                                // 是一个完整的单词
                                break;
                            }
                            else
                            {
                                // 找到的不是一个完整的单词,继续在本Run元素中查找
                                position = position.GetPositionAtOffset(input.Length);
                                return GetTextRangeFromPosition(ref position, input, findOptions);
                            }
                        }
                        else
                        {
                            //不要求全字匹配
                            position = position.GetPositionAtOffset(input.Length);
                            break;
                        }
                    }
                    else
                    {
                        // 没找到匹配项,移到当前的Run元素之后 "textRun".
                        position = position.GetPositionAtOffset(textRun.Length);
                    }
                }
                else
                {
                    //如果当前位置不是文本类型的元素,继续"前进",跳过这些非文本元素.
                    position = position.GetNextContextPosition(LogicalDirection.Forward);
                }
            }

            return textRange;
        }
Example #11
0
       /*private static TextPointer GetPointOld(TextPointer start, int x)
       {
           var ret = start;
           var i = 0;
           while (i < x && ret != null)
           {
               if (ret.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.Text || ret.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.None)
                   i++;              
               if (ret.GetPositionAtOffset(1, LogicalDirection.Forward) == null)
                   return ret;
               ret = ret.GetPositionAtOffset(1, LogicalDirection.Forward);
           }
           return ret;
       }*/
       private static TextPointer GetPoint(TextPointer start, int x)
       {                      
           TextPointer ret = start.GetPositionAtOffset(x);           
           while (new TextRange(start, ret).Text.Length < x)
           {
               if (ret.GetPositionAtOffset(1, LogicalDirection.Forward) == null)
                   return ret;
               ret = ret.GetPositionAtOffset(1, LogicalDirection.Forward);
           }

           return ret;
       }
Example #12
0
        public static string GetCharacterAtPosition(RichTextBox rtb, TextPointer position, int offset)
        {
            TextPointer nextPosition = position.GetPositionAtOffset(offset, LogicalDirection.Forward);
            if (nextPosition != null)
            {
                rtb.Selection.Select(position, nextPosition);
                if (rtb.Selection.Text.Length > 0)
                {
                    string c = rtb.Selection.Text;
                    rtb.Selection.Select(position, position); //reset selection
                    return (c);
                }
            }

            return (string.Empty);
        }
Example #13
0
        private TextRange FindWordFromPosition(TextPointer position, string word, SearchDirection searchDirection)
        {
            string wordToFind;

            if (!CaseSensitive)
            {
                wordToFind = word.ToLower();
            }
            else
            {
                wordToFind = word;
            }

            LogicalDirection logicalDirection = SearchDirectionToLogicalDirection(searchDirection);

            while (position != null)
            {
                if (position.Parent is ConversationContentRun)
                {
                    string textRun = position.GetTextInRun(logicalDirection);

                    int indexInRun = FindWordInString(wordToFind, textRun, searchDirection);

                    if (indexInRun >= 0)
                    {
                        int startOffset;

                        if (searchDirection == SearchDirection.Down)
                        {
                            startOffset = indexInRun;
                        }
                        else
                        {
                            startOffset = -1 * (textRun.Length - indexInRun);
                        }

                        TextPointer start = position.GetPositionAtOffset(startOffset, logicalDirection);
                        TextPointer end = start.GetPositionAtOffset(wordToFind.Length, logicalDirection);
                        return new TextRange(start, end);
                    }
                }

                position = position.GetNextContextPosition(logicalDirection);
            }

            return null;
        }
Example #14
0
        private void HighlightText(TextPointer position, string word)
        {
            while (position != null)
            {
                if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
                {
                    string textRun = position.GetTextInRun(LogicalDirection.Forward);

                    // Find the starting index of any substring that matches "word".
                    int indexInRun = textRun.IndexOf(word);
                    if (indexInRun >= 0)
                    {
                        TextPointer start = position.GetPositionAtOffset(indexInRun);
                        TextPointer end = start.GetPositionAtOffset(word.Length);
                        new TextRange(start, end).ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold);
                    }
                }

                position = position.GetNextContextPosition(LogicalDirection.Forward);
            }
        }
 private void CheckWords(string text, TextPointer start)
 {
     List<SyntaxProvider.Range> range = SyntaxProvider.CheckWords(text);
     foreach (SyntaxProvider.Range syntaxRange in range)
     {
         Range item = new Range
         {
             StartPosition = start.GetPositionAtOffset(syntaxRange.Start),
             EndPosition = start.GetPositionAtOffset(syntaxRange.End),
             Foreground = new SolidColorBrush(syntaxRange.Foreground)
         };
         _ranges.Add(item);
     }
 }
Example #16
0
        /// <summary>
        /// Reads the document from the reader into the specified position.
        /// </summary>
        private void ReadDocument(XmlReader reader, TextPointer position)
        {
            // Initialize all fields.
            _cursor = position;
            _dir = LogicalDirection.Forward;
            _otherDir = LogicalDirection.Backward;
            _reader = reader;

            // Set the gravity of the cursor to always look forward.
            _cursor = _cursor.GetPositionAtOffset(0, _dir);

            while (_reader.Read())
            {
                switch (_reader.NodeType)
                {
                    case XmlNodeType.Attribute:
                        System.Diagnostics.Debug.Assert(false,
                            "Attributes should never be processed by top-level convertion loop.");
                        break;
                    case XmlNodeType.EndElement:
                        System.Diagnostics.Trace.WriteLine("WordXmlReader.ReadDocument - EndElement [" +
                            _reader.Name + "]");
                        switch (_reader.Name)
                        {
                            case WordXmlSerializer.WordParagraphTag:
                                MoveOutOfElement(typeof(Paragraph));
                                _inParagraph = false;
                                break;
                            case WordXmlSerializer.WordRangeTag:
                                MoveOutOfElement(typeof(Run));
                                _inRange = false;
                                break;
                            case WordXmlSerializer.WordStyleTag:
                                _currentStyle = null;
                                break;
                            case WordXmlSerializer.WordTextTag:
                                _inText = false;
                                break;
                        }
                        break;
                    case XmlNodeType.Element:
                        System.Diagnostics.Trace.WriteLine("WordXmlReader.ReadDocument - Element [" +
                            _reader.Name + "]");
                        switch (_reader.Name)
                        {
                            case WordXmlSerializer.WordParagraphTag:
                                if (_inParagraph)
                                {
                                    throw CreateUnexpectedNodeException(_reader);
                                }
                                SurroundWithElement(new Paragraph(new Run()));
                                ApplyStyleToParagraph();
                                _inParagraph = true;
                                if (_reader.IsEmptyElement)
                                {
                                    MoveOutOfElement(typeof(Paragraph));
                                    _inParagraph = false;
                                }
                                break;
                            case WordXmlSerializer.WordRangeTag:
                                SurroundWithElement(new Run());
                                _inRange = true;
                                break;
                            case WordXmlSerializer.WordNameTag:
                                if (!IsPopulatingStyle)
                                {
                                    throw new ArgumentException("w:name only supported on styles.");
                                }
                                break;
                            case WordXmlSerializer.WordStyleTag:
                                _currentStyle = new Style();
                                SetupCurrentStyle();
                                break;
                            case WordXmlSerializer.WordTextTag:
                                _inText = true;
                                break;
                            case WordXmlSerializer.WordBreakTag:
                                if (_inRange)
                                {
                                    MoveOutOfElement(typeof(Run));
                                    new LineBreak(_cursor);
                                    SurroundWithElement(new Run());
                                }
                                else
                                {
                                    new LineBreak(_cursor);
                                }
                                break;
                            default:
                                SetSimpleProperty();
                                break;
                        }
                        break;
                    case XmlNodeType.SignificantWhitespace:
                    case XmlNodeType.CDATA:
                    case XmlNodeType.Text:
                        if (_inText)
                        {
                            _cursor.InsertTextInRun(_reader.Value);
                        }
                        break;
                }
            }
        }
        /// <summary>
        /// UpdateAccessKey - Scans forward in the tree looking for the access key marker, replacing it with access key element. We only support one find.
        /// </summary>
        private void UpdateAccessKey()
        {
            TextPointer navigator = new TextPointer(TextContainer.Start);

            while (!_accessKeyLocated && navigator.CompareTo(TextContainer.End) < 0 )
            {
                TextPointerContext symbolType = navigator.GetPointerContext(LogicalDirection.Forward);
                switch (symbolType)
                {
                    case TextPointerContext.Text:
                        string text = navigator.GetTextInRun(LogicalDirection.Forward);
                        int index = FindAccessKeyMarker(text);
                        if(index != -1 && index < text.Length - 1)
                        {
                            string keyText = StringInfo.GetNextTextElement(text, index + 1);
                            TextPointer keyEnd = navigator.GetPositionAtOffset(index + 1 + keyText.Length);

                            _accessKey = new Run(keyText);
                            _accessKey.Style = AccessKeyStyle;

                            RegisterAccessKey();

                            HasCustomSerializationStorage.SetValue(_accessKey, true);
                            _accessKeyLocated = true;

                            UninitializeTextContainerListener();

                            TextContainer.BeginChange();
                            try
                            {
                                TextPointer underlineStart = new TextPointer(navigator, index);
                                TextRangeEdit.DeleteInlineContent(underlineStart, keyEnd);
                                _accessKey.RepositionWithContent(underlineStart);

                            }
                            finally
                            {
                                TextContainer.EndChange();
                                InitializeTextContainerListener();
                            }
                        }

                        break;
                }
                navigator.MoveToNextContextPosition(LogicalDirection.Forward);
            }

            // Convert double _ to single _
            navigator = new TextPointer(TextContainer.Start);
            string accessKeyMarker = AccessKeyMarker.ToString();
            string doubleAccessKeyMarker = accessKeyMarker + accessKeyMarker;
            while (navigator.CompareTo(TextContainer.End) < 0)
            {
                TextPointerContext symbolType = navigator.GetPointerContext(LogicalDirection.Forward);
                switch (symbolType)
                {
                    case TextPointerContext.Text:
                        string text = navigator.GetTextInRun(LogicalDirection.Forward);
                        string nexText = text.Replace(doubleAccessKeyMarker, accessKeyMarker);
                        if (text != nexText)
                        {
                            TextPointer keyStart = new TextPointer(navigator, 0);
                            TextPointer keyEnd = new TextPointer(navigator, text.Length);

                            UninitializeTextContainerListener();
                            TextContainer.BeginChange();
                            try
                            {
                                keyEnd.InsertTextInRun(nexText);
                                TextRangeEdit.DeleteInlineContent(keyStart, keyEnd);
                            }
                            finally
                            {
                                TextContainer.EndChange();
                                InitializeTextContainerListener();
                            }
                        }

                        break;
                }
                navigator.MoveToNextContextPosition(LogicalDirection.Forward);
            }
        }
Example #18
0
        // Wrapper for this.TextView.IsAtCaretUnitBoundary, adds a cache. 
        internal bool IsAtCaretUnitBoundary(TextPointer position)
        { 
            position.DebugAssertGeneration();
            Invariant.Assert(position.HasValidLayout);

            if (_rootNode.CaretUnitBoundaryCacheOffset != position.GetSymbolOffset()) 
            {
                _rootNode.CaretUnitBoundaryCacheOffset = position.GetSymbolOffset(); 
                _rootNode.CaretUnitBoundaryCache = _textview.IsAtCaretUnitBoundary(position); 

                if (!_rootNode.CaretUnitBoundaryCache && position.LogicalDirection == LogicalDirection.Backward) 
                {
                    // In MIL Text and TextView worlds, a position at trailing edge of a newline (with backward gravity)
                    // is not an allowed caret stop.
                    // However, in TextPointer world we must allow such a position to be a valid insertion position, 
                    // since it breaks textrange normalization for empty ranges.
                    // Hence, we need to check for TextView.IsAtCaretUnitBoundary in reverse direction here. 
 
                    TextPointer positionForwardGravity = position.GetPositionAtOffset(0, LogicalDirection.Forward);
                    _rootNode.CaretUnitBoundaryCache = _textview.IsAtCaretUnitBoundary(positionForwardGravity); 
                }
            }

            return _rootNode.CaretUnitBoundaryCache; 
        }
Example #19
0
        public static void getDiffTextArea(ref TextPointer poiStart, ref TextPointer poiEnd, string lastText)
        {
            int tpCount = poiStart.GetOffsetToPosition(poiEnd);
            int tpCountLast = poiEnd.GetOffsetToPosition(poiStart.DocumentEnd);

            if (lastText == null || lastText == "" || (new TextRange(poiStart, poiEnd)).Text == "" ||
                tpCount <= sc_maxTextChangeCheckCount)
            {
                poiEnd = poiStart;

                return;
            }

            TextPointer tpHalf = poiStart.GetPositionAtOffset(tpCount / 2);
            TextPointer tpLastHalf = poiEnd.GetPositionAtOffset(tpCountLast / 2);

            switch (checkDiff(poiStart.DocumentStart, poiEnd, lastText))
            {
                case TextChangedType_E.OLDLARGER_TRUE:
                    {
                        poiStart = poiEnd;
                        poiEnd = tpLastHalf;
                    }
                    break;
                case TextChangedType_E.OLDLARGER_FLASE:
                    {
                        poiEnd = tpHalf;
                    }
                    break;
                case TextChangedType_E.NEWLARGER_TRUE:
                    {
                        poiStart = tpHalf;
                        poiEnd = tpHalf;
                    }
                    break;
                case TextChangedType_E.NEWLARGER_FALSE:
                    {
                        poiEnd = tpHalf;
                    }
                    break;
                default:
                    {

                    }
                    break;
            }
            getDiffTextArea(ref poiStart, ref poiEnd, lastText);
        }
Example #20
0
        /// <summary>
        /// Looks for the provided text from the provided location.
        /// </summary>
        TextRange FindTextFromTextPointerPosition(TextPointer textPointerPosition, string text)
        {
            while (textPointerPosition != null)
            {
                if (textPointerPosition.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
                {
                    string textRun = textPointerPosition.GetTextInRun(LogicalDirection.Forward);

                    int indexInRun = textRun.IndexOf(text);
                    if (indexInRun >= 0)
                    {
                        TextPointer textPointerStartPosition = textPointerPosition.GetPositionAtOffset(indexInRun);
                        TextPointer textPointerEndPosition = textPointerStartPosition.GetPositionAtOffset(text.Length);
                        return new TextRange(textPointerStartPosition, textPointerEndPosition);
                    }
                }

                textPointerPosition = textPointerPosition.GetNextContextPosition(LogicalDirection.Forward);
            }

            return null;
        }
Example #21
0
        // Helper for plain text filtering when pasted into rich or plain destination
        private static bool PastePlainText(TextEditor This, string pastedText)
        {
            pastedText = This._FilterText(pastedText, This.Selection);

            if (pastedText.Length > 0)
            {
                if (This.AcceptsRichContent && This.Selection.Start is TextPointer)
                {
                    // Clear selection content
                    This.Selection.Text = String.Empty;

                    // Ensure that text is insertable at current selection
                    TextPointer start = TextRangeEditTables.EnsureInsertionPosition((TextPointer)This.Selection.Start);

                    // Store boundaries of inserted text
                    start = start.GetPositionAtOffset(0, LogicalDirection.Backward);
                    TextPointer end = start.GetPositionAtOffset(0, LogicalDirection.Forward);

                    // For rich text we need to remove control characters and
                    // replace linebreaks by paragraphs
                    int currentLineStart = 0;
                    for (int i = 0; i < pastedText.Length; i++)
                    {
                        if (pastedText[i] == '\r' || pastedText[i] == '\n')
                        {
                            end.InsertTextInRun(pastedText.Substring(currentLineStart, i - currentLineStart));
                            if (!This.AcceptsReturn)
                            {
                                return(true); // All lined except for the first one are ignored when TextBox does not accept Return key
                            }

                            if (end.HasNonMergeableInlineAncestor)
                            {
                                // We cannot split a Hyperlink or other non-mergeable Inline element,
                                // so insert a space character instead (similar to embedded object).
                                // Note that this means, Paste operation would loose
                                // paragraph break information in this case.
                                end.InsertTextInRun(" ");
                            }
                            else
                            {
                                end = end.InsertParagraphBreak();
                            }

                            if (pastedText[i] == '\r' && i + 1 < pastedText.Length && pastedText[i + 1] == '\n')
                            {
                                i++;
                            }
                            currentLineStart = i + 1;
                        }
                    }
                    end.InsertTextInRun(pastedText.Substring(currentLineStart, pastedText.Length - currentLineStart));

                    // Select all pasted content
                    This.Selection.Select(start, end);
                }
                else
                {
                    // For plain text we insert the content as is (including control characters)
                    This.Selection.Text = pastedText;
                }
                return(true);
            }

            return(false);
        }
        /// <summary>
        /// 获取RichTextBox中光标最近的一个字符(向前)
        /// </summary>
        /// <param name="rtf"></param>
        /// <param name="curLoc"></param>
        /// <returns></returns>
        public TextRange GetPrevChar(TextPointer curLoc)
        {
            //文字指针向前移一个字符
            TextPointer nextLoc = curLoc.GetPositionAtOffset(-1);
            if (nextLoc == null) //找不到对应位置
                return null;

            //现在可获取插入光标最近一个字符
            TextRange nearestChar = new TextRange(curLoc, nextLoc);

            return nearestChar;
        }