public GetPositionAtOffset ( int offset, LogicalDirection direction ) : |
||
offset | int | |
direction | LogicalDirection | |
return |
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; }
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); }
internal static TextPointer SafePositionAtOffset(FlowDocument document, TextPointer textPointer, int offsetStart) { var pointer = textPointer.GetPositionAtOffset(offsetStart); if (pointer == null) return document.ContentEnd; return pointer; }
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; }
public Word(TextPointer wordStart, TextPointer wordEnd) { _wordStart = wordStart.GetPositionAtOffset(0, LogicalDirection.Forward); _wordEnd = wordEnd.GetPositionAtOffset(0, LogicalDirection.Backward); }
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(); } }
// 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; }
/*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; }
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); }
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; }
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); } }
/// <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); } }
// 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; }
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); }
/// <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; }
// 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; }