private string FindBreak(TextPointer pointer) { Rect rectAtStart = pointer.GetCharacterRect(LogicalDirection.Forward); pointer = pointer.GetNextInsertionPosition(LogicalDirection.Forward); Rect currentRect = pointer.GetCharacterRect(LogicalDirection.Forward); while (currentRect.Bottom == rectAtStart.Bottom) { pointer = pointer.GetNextInsertionPosition(LogicalDirection.Forward); currentRect = pointer.GetCharacterRect(LogicalDirection.Forward); } string textBeforeBreak = pointer.GetTextInRun(LogicalDirection.Backward); string textAfterBreak = pointer.GetTextInRun(LogicalDirection.Forward); return textAfterBreak; }
private List <string> get_elements_in_string(TextPointer tp_start, TextPointer tp_end, Color color) { //获取选择区域内部指定颜色的所有单词和短语 List <string> dc_list = new List <string>(); TextPointer tp1 = tp_start; TextPointer tp2 = tp1.GetNextInsertionPosition(LogicalDirection.Forward); string color_mode_str = color.ToString(); string color_select_str; while (tp1 != tp_end) { if (tp2 == null) { break; } TextRange range_char = new TextRange(tp1, tp2); color_select_str = range_char.GetPropertyValue(TextElement.ForegroundProperty).ToString(); if (color_select_str == color_mode_str) { TextPointer tp_dc_start = tp1; TextPointer tp_dc_end; while (color_select_str == color_mode_str) { tp1 = tp2; tp2 = tp1.GetNextInsertionPosition(LogicalDirection.Forward); if (tp2 == null) { break; } range_char = new TextRange(tp1, tp2); color_select_str = range_char.GetPropertyValue(TextElement.ForegroundProperty).ToString(); } tp_dc_end = tp1; TextRange range_word = new TextRange(tp_dc_start, tp_dc_end); string word = range_word.Text; dc_list.Add(word); } else { tp1 = tp2; tp2 = tp1.GetNextInsertionPosition(LogicalDirection.Forward); } } return(dc_list); }
/// <summary> /// Pad the line of the text pointer to the length specified. /// </summary> /// <param name="Doc"></param> /// <param name="Pointer"></param> /// <param name="Length"></param> public static void PadLineToLength( this TextPointer Pointer, FlowDocument Doc, int Length, char PadChar = ' ') { TextPointer tp1 = Pointer.GetLineStartPosition(0); TextPointer tp2 = Pointer.GetLineStartPosition(1); if (tp2 != null) { tp2 = tp2.GetNextInsertionPosition(LogicalDirection.Backward); } else { tp2 = Doc.ContentEnd.GetNextInsertionPosition(LogicalDirection.Backward); } // current line text. TextRange r1 = new TextRange(tp1, tp2); string lineText = r1.Text; // pad length string padText = null; int padLx = Length - lineText.Length; if (padLx > 0) { padText = new StringBuilder().AppendRepeat(PadChar, padLx).ToString(); tp2.InsertTextInRun(padText); } }
internal void MoveCaretToFirstLine(Rect rect) { TextPointer tp = Document.ContentStart; TextPointer last_tp = tp; Rect r = tp.GetCharacterRect(LogicalDirection.Forward); while (tp != null && r.X < rect.X && tp.CompareTo(Document.ContentEnd) != 0) { tp = tp.GetNextInsertionPosition(LogicalDirection.Forward); if (tp == null) { break; } r = tp.GetCharacterRect(LogicalDirection.Forward); last_tp = tp; } if (last_tp != null) { CaretPosition = last_tp; } // Workaround for bug in .NET 3.0 if (!CaretPosition.IsAtLineStartPosition) { EditingCommands.MoveLeftByCharacter.Execute(null, this); EditingCommands.MoveRightByCharacter.Execute(null, this); } else if (CaretPosition.CompareTo(Document.ContentEnd) != 0) { EditingCommands.MoveRightByCharacter.Execute(null, this); EditingCommands.MoveLeftByCharacter.Execute(null, this); } }
protected void OnCopy(object o, DataObjectCopyingEventArgs e) { string clipboard = ""; for (TextPointer p = Selection.Start, next = null; p != null && p.CompareTo(Selection.End) < 0; p = next) { next = p.GetNextInsertionPosition(LogicalDirection.Forward); if (next == null) { break; } var emoji = (next.Parent as Run)?.PreviousInline as EmojiInline; if (emoji == null && next.Parent != p.Parent) { emoji = (p.Parent as Run)?.NextInline as EmojiInline; } if (emoji != null && (p.Parent as Run).PreviousInline != emoji) { clipboard += emoji?.Text; } else { clipboard += new TextRange(p, next).Text; } } Clipboard.SetText(clipboard); e.Handled = true; e.CancelCommand(); }
public static void ProcessParagraphLink(RichTextBox textBox, string text, Inline i) { foreach (string str in GetLinks(text)) { TextPointer tp = i.ContentStart; bool reposition = false; while (!tp.GetTextInRun(LogicalDirection.Forward).StartsWith(str)) { tp = tp.GetNextInsertionPosition(LogicalDirection.Forward); } TextPointer end = tp; for (int j = 0; j < str.Length; j++) { end = end.GetNextInsertionPosition(LogicalDirection.Forward); } TextRange tr = new TextRange(tp, end); if (textBox != null) { reposition = textBox.CaretPosition.CompareTo(tr.End) == 0; } tr.Text = string.Empty; TextBlock block = new TextBlock(); block.Text = str; block.ForceCursor = true; block.Cursor = System.Windows.Input.Cursors.Hand; block.TextDecorations = TextDecorations.Underline; block.Foreground = Brushes.Blue; block.PreviewMouseLeftButtonDown += new System.Windows.Input.MouseButtonEventHandler(block_PreviewMouseLeftButtonDown); InlineUIContainer iui = new InlineUIContainer(block, tp); } }
/// <summary> /// This function select a part of the text based on it's color. it is used for multi-line comments and strings /// </summary> public TextPointer getColorPoint(TextPointer current, LogicalDirection direction, TextPointer enterdPosition, Brush brush) { TextPointer nextPosition = current; TextPointer StartingPosition = current; bool isGreen = true; TextRange text = new TextRange(current, nextPosition); while (isGreen) { nextPosition = current.GetNextInsertionPosition(direction); if (nextPosition == null) { break; } text = new TextRange(current, nextPosition); if (text.GetPropertyValue(TextElement.ForegroundProperty) != brush) { isGreen = false; } else { current = nextPosition; } } return(current); }
} // End GetXaml method. // </Snippet_TextPointer_GetNextContextPosition> // <Snippet_TextPointer_GetNextInsertionPosition> // This method returns the number of pagragraphs between two // specified TextPointers. int GetParagraphCount(TextPointer start, TextPointer end) { int paragraphCount = 0; while (start != null && start.CompareTo(end) < 0) { Paragraph paragraph = start.Paragraph; if (paragraph != null) { paragraphCount++; // Advance start to the end of the current paragraph. start = paragraph.ContentEnd; } // Use the GetNextInsertionPosition method to skip over any interceding // content element tags. start = start.GetNextInsertionPosition(LogicalDirection.Forward); } // End while. return paragraphCount; } // End GetParagraphCount.
public TextPointer getCurrentChar(TextPointer current, LogicalDirection direction) { // in tabe ye textPointer migire va az unja ta berese be ye delimeter dar jahati behesh migim harekat mikone //va dar akhar texpointer noghte payani ro bar migardune TextPointer nextPosition = current; string test; while (1 == 1) { nextPosition = current.GetNextInsertionPosition(direction); if (nextPosition == null) { break; } test = new TextRange(current, nextPosition).Text; for (int i = 0; i < delimeters.Length; i++) { if (test == delimeters[i]) { break; } } current = nextPosition; } return(current); }
protected void OnCopy(object o, DataObjectCopyingEventArgs e) { string clipboard = ""; for (TextPointer p = Selection.Start, next = null; p != null && p.CompareTo(Selection.End) < 0; p = next) { next = p.GetNextInsertionPosition(LogicalDirection.Forward); if (next == null) { break; } //var word = new TextRange(p, next); //Console.WriteLine($"Word '{word.Text}' Inline {word.Start.Parent.GetType()}"); //Console.WriteLine($" ... p {p.Parent.GetType()}"); var t = new TextRange(p, next); clipboard += t.Start.Parent is EmojiInline ? (t.Start.Parent as EmojiInline).Text : t.Text; } Clipboard.SetText(clipboard); e.Handled = true; e.CancelCommand(); }
// По координате получает указатель в тексте. Если координаты берутся мышиные, мышь нужно брать относительно // корневого элемента управления в котором сидит FlowDocument (как пример) public static TextPointer GetPositionFromPoint(this Run run, Point searchForPoint) { // Работает тормозно. Возможно стоит пробежаться 1 раз при перерисовке flowdocument-а и в какое нибудь дерево или чето подобное запихнуть все эти рект-ы // чтобы быстро находить букву по позиции TextPointer currentTextPointer = run.ContentStart; TextPointer nextTextPointer = currentTextPointer.GetNextInsertionPosition(LogicalDirection.Forward); while (nextTextPointer != null) { Rect currentRect = currentTextPointer.GetCharacterRect(LogicalDirection.Forward); Rect nextRect = nextTextPointer.GetCharacterRect(LogicalDirection.Backward); if (searchForPoint.X >= currentRect.X && searchForPoint.X <= nextRect.X && searchForPoint.Y >= currentRect.Top && searchForPoint.Y <= nextRect.Bottom) { return(currentTextPointer); } currentTextPointer = nextTextPointer; nextTextPointer = nextTextPointer.GetNextInsertionPosition(LogicalDirection.Forward); } return(null); }
/// <summary> /// 获取第n个zhifu的结束位置 /// </summary> /// <param name="rtb"></param> /// <param name="zhifu"></param> /// <param name="n"></param> /// <returns></returns> private static TextPointer get_tp(RichTextBox rtb, string zhifu, int n) { TextPointer tpStart = rtb.Document.ContentStart; if (n == 0) { return(tpStart); } TextPointer tpEnd = rtb.Document.ContentEnd; TextPointer tp1 = tpStart; TextPointer tp2 = tp1.GetNextInsertionPosition(LogicalDirection.Forward); TextRange range_char = new TextRange(tp1, tp2); int count = 0; while (tp2 != tpEnd) { tp1 = tp2; tp2 = tp1.GetNextInsertionPosition(LogicalDirection.Forward); range_char = new TextRange(tp1, tp2); if (zhifu == "\n") { if (range_char.Text == "\n" || range_char.Text == "\r\n") { count++; } if (count == n) { break; } } else { if (range_char.Text == zhifu) { count++; } if (count == n) { break; } } } return(tp2); }
private static void RemoveHyperlink(AutoCompleteRichTextBox myRichTextBox, TextPointer caretPosition) { var backspacePosition = caretPosition.GetNextInsertionPosition(LogicalDirection.Backward); Hyperlink hyperlink; if (backspacePosition == null || !DocumentUtils.IsHyperlinkBoundaryCrossed(caretPosition, backspacePosition, out hyperlink)) { return; } // 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 = caretPosition.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 && !DocumentUtils.IsHyperlinkProperty(dp)) { inlineRange.ApplyPropertyValue(dp, value); } } // 4. Delete the (empty) hyperlink element. hyperlink.SiblingInlines.Remove(hyperlink); // 5. Update selection, since we deleted Hyperlink element and caretPosition was at that Hyperlink's end boundary. myRichTextBox.Selection.Select(newCaretPosition, newCaretPosition); }
/// <summary> /// 清除语段模式标记 /// </summary> /// <param name="rtb"></param> /// <param name="tp_biaoji_start"></param> private static void clear_yd_biaoji(RichTextBox rtb, TextPointer tp_biaoji_start) { TextPointer tp1 = tp_biaoji_start; TextPointer tp2 = tp1.GetNextInsertionPosition(LogicalDirection.Forward); Inline run = (Inline)tp2.Parent; tp2.Paragraph.Inlines.Remove(run); }
private void FixEmojis() { if (m_pending_change) { return; } /* This will prevent our operation from polluting the undo buffer, but it * will create an infinite undo stack... need to fix this. */ BeginChange(); m_pending_change = true; TextPointer cur = Document.ContentStart; while (cur.CompareTo(Document.ContentEnd) < 0) { TextPointer next = cur.GetNextInsertionPosition(LogicalDirection.Forward); if (next == null) { break; } TextRange word = new TextRange(cur, next); if (word.Text.Length > 0) { // Test this so as to preserve caret position bool caret_was_next = (0 == next.CompareTo(CaretPosition)); Inline inline; // FIXME: this is a hack, normally we should split into Runs and EmojiInlines if (word.Text == "\n") { inline = new LineBreak(); } else { inline = new EmojiInline() { Text = word.Text, FontSize = FontSize, FallbackBrush = Foreground } }; next = Replace(word, inline); if (caret_was_next) { CaretPosition = next; } } cur = next; } EndChange(); m_pending_change = false; }
protected override void OnTextChanged(TextChangedEventArgs e) { if (m_pending_change) { return; } m_pending_change = true; base.OnTextChanged(e); /* This will prevent our operation from polluting the undo buffer, but it * will create an infinite undo stack... need to fix this. */ BeginChange(); m_pending_change = true; TextPointer cur = Document.ContentStart; while (cur.CompareTo(Document.ContentEnd) < 0) { TextPointer next = cur.GetNextInsertionPosition(LogicalDirection.Forward); if (next == null) { break; } TextRange word = new TextRange(cur, next); if (EmojiData.MatchOne.IsMatch(word.Text)) { Inline inline = new EmojiInline() { Text = word.Text, FontSize = FontSize, FallbackBrush = Foreground, }; // Preserve caret position bool caret_was_next = (0 == next.CompareTo(CaretPosition)); next = Replace(word, inline); if (caret_was_next) { CaretPosition = next; } } cur = next; } EndChange(); m_pending_change = false; // FIXME: debug //Console.WriteLine(XamlWriter.Save(Document)); }
private static void GetPointer(TextPointer start, int startOffset, int endOffset, out TextPointer startPointer, out TextPointer endPointer) { int i = 0; startPointer = null; endPointer = null; //while (start.GetPointerContext(LogicalDirection.Forward) != TextPointerContext.Text) // start = start.GetNextContextPosition(LogicalDirection.Forward); while (i < startOffset && start != null) { if (start.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text) { //string textrun = start.GetTextInRun(LogicalDirection.Forward); //start = start.GetNextContextPosition(LogicalDirection.Forward); //i += start.GetTextInRun(LogicalDirection.Forward).Length; start = start.GetNextInsertionPosition(LogicalDirection.Forward); i++; } else if (start.GetPositionAtOffset(1, LogicalDirection.Forward) == null) { break; } else { start = start.GetNextInsertionPosition(LogicalDirection.Forward); i += 2; } } startPointer = start; while (i < endOffset) { if (start.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text) { i++; } else if (start.GetPositionAtOffset(1, LogicalDirection.Forward) == null) { break; } start = start.GetNextInsertionPosition(LogicalDirection.Forward); } endPointer = start; }
private static Hyperlink FindHyperlink(TextPointer textPointer, LogicalDirection logicalDirection) { TextPointer tp = textPointer.GetNextInsertionPosition(logicalDirection); if (tp != null) { return(DialogHyperlink.SelectedHyperlink(tp)); } return(null); }
public static TextPointer GetTextPointerForPosition(this RichTextBox rtb, int line, int column) { TextPointer docStartLine = rtb.Document.ContentStart.GetLineStartPosition(0); TextPointer tp = docStartLine.GetLineStartPosition(line); for (int i = 0; i <= column; i++) { tp = tp.GetNextInsertionPosition(LogicalDirection.Forward); } return(tp); }
/// <summary> /// Create a PhysicalCharInfo for the character between position and the next forward insertion position /// </summary> /// <param name="position"></param> public PhysicalCharInfo(TextPointer position) { if (position == null) { throw new ArgumentNullException("position"); } this.NearPosition = null; this.FarPosition = null; Initialize(position, position.GetNextInsertionPosition(LogicalDirection.Forward) ?? position); }
public static int GetColumnForTextPointer(this RichTextBox rtb, TextPointer tp) { TextPointer tpColumn = tp.GetInsertionPosition(LogicalDirection.Backward); int columnNr = 1; for (TextPointer linePointer = tpColumn.GetLineStartPosition(0).GetNextInsertionPosition(LogicalDirection.Forward); linePointer.CompareTo(tpColumn) < 0; linePointer = linePointer.GetNextInsertionPosition(LogicalDirection.Forward)) { columnNr++; } return(columnNr); }
private static TextPointer LetterShift_Guess(TextPointer start, int numLetters, out int numOff) { if (numLetters == 0) { numOff = 0; return(start); } TextPointer result = start.GetPositionAtOffset(numLetters); if (result == null) { numOff = 0; return(null); } if (!result.IsAtInsertionPosition) { TextPointer save; if ((save = result.GetNextInsertionPosition(LogicalDirection.Backward)) == null) { if ((save = result.GetNextInsertionPosition(LogicalDirection.Forward)) == null) { numOff = 0; return(null); } } result = save; } bool wasNegative = numLetters < 0; numOff = Math.Abs(numLetters) - start.GetLetterOffset(result); if (wasNegative) { numOff *= -1; } return(result); }
/// <summary> /// return TextPointer position before the last char of the line of the input /// TextPointer. /// </summary> /// <param name="TextPointer"></param> /// <param name="Doc"></param> /// <returns></returns> public static TextPointer GetLineEndPosition( this TextPointer TextPointer, FlowDocument Doc, RelativePosition Relative = RelativePosition.After) { TextPointer tp1 = TextPointer.GetLineStartPosition(1); if (tp1 == null) { tp1 = Doc.ContentEnd; tp1 = tp1.GetNextInsertionPosition(LogicalDirection.Backward); } else { tp1 = tp1.GetNextInsertionPosition(LogicalDirection.Backward); // position before the last char of the line. if ((tp1 != null) && (Relative == RelativePosition.Before)) { tp1 = tp1.GetNextInsertionPosition(LogicalDirection.Backward); } } return(tp1); }
/// <summary> /// 1. When wordBreakDirection = Forward, returns a position at the end of the word, /// i.e. a position with a wordBreak character (space) following it. /// 2. When wordBreakDirection = Backward, returns a position at the start of the word, /// i.e. a position with a wordBreak character (space) preceeding it. /// 3. Returns null when there is no workbreak in the requested direction. /// </summary> private static TextPointer GetPositionAtWordBoundary(TextPointer position, LogicalDirection wordBreakDirection) { if (!position.IsAtInsertionPosition) { position = position.GetInsertionPosition(wordBreakDirection); } TextPointer navigator = position; while (navigator != null && !IsPositionNextToWordBreak(navigator, wordBreakDirection)) { navigator = navigator.GetNextInsertionPosition(wordBreakDirection); } return(navigator); }
public static TextPointer GetPositionFromPoint(Run thiz, Point searchForPoint) { TextPointer ptrCurCharcter = thiz.ContentStart.GetNextInsertionPosition(LogicalDirection.Forward); TextPointer ptrNextCharcter = ptrCurCharcter.GetNextInsertionPosition(LogicalDirection.Forward); while (ptrNextCharcter != null) { Rect charcterInsertionPointRectangle = ptrCurCharcter.GetCharacterRect(LogicalDirection.Forward); Rect nextCharcterInsertionPointRectangle = ptrNextCharcter.GetCharacterRect(LogicalDirection.Backward); if (searchForPoint.X >= charcterInsertionPointRectangle.X && searchForPoint.X <= nextCharcterInsertionPointRectangle.X && searchForPoint.Y >= charcterInsertionPointRectangle.Top && searchForPoint.Y <= charcterInsertionPointRectangle.Bottom) { return(ptrCurCharcter); } ptrCurCharcter = ptrCurCharcter.GetNextInsertionPosition(LogicalDirection.Forward); ptrNextCharcter = ptrNextCharcter.GetNextInsertionPosition(LogicalDirection.Forward); } return(null); }
/// <summary> /// return a TextPointer positioned before a specified position on the line. /// If the position exceeds the end of the line, either pad the line with /// blanks or set the position to the last char on the line. /// </summary> /// <param name="Doc"></param> /// <param name="Pointer"></param> /// <param name="Position"></param> /// <param name="Pad"></param> /// <returns></returns> public static TextPointer SetPositionOnLine( this TextPointer Pointer, FlowDocument Doc, int Position, bool Pad = false) { TextPointer tp = Pointer.GetLineStartPosition(0); int pos = Position; // make sure length of the line can accomodate the position. string lineText = Pointer.GetLineText(Doc, 0, ""); if (pos > (lineText.Length - 1)) { if (Pad == false) { pos = lineText.Length - 1; } else { Pointer.PadLineToLength(Doc, pos + 1); lineText = Pointer.GetLineText(Doc); } } // position to the last char on the line. if (lineText.Length == (pos + 1)) { tp = Pointer.GetLineEndPosition(Doc); } // advance a char at a time from the start of the line. else { for (int ix = 0; ix < pos; ++ix) { var nextTp = tp.GetNextInsertionPosition(LogicalDirection.Forward); if (nextTp != null) { tp = nextTp; } else { break; } } } return(tp); }
public TextPointer GetTextPointer(int charOffset, bool reset = false) { if (reset) { ResetToStart(); } while (CurrentPosition.CompareTo(EndOfDocument) < 0) { switch (CurrentPosition.GetPointerContext(LogicalDirection.Forward)) { case TextPointerContext.ElementEnd: { DependencyObject d = this.CurrentPosition.GetAdjacentElement(LogicalDirection.Forward); if (d is Paragraph || d is LineBreak) { CurrentCharacterOffset += 2; } if (d is InlineUIContainer) { CurrentCharacterOffset += 1; } break; } case TextPointerContext.Text: { int characterInCurrentRun = CurrentCharacterOffset + CurrentPosition.GetTextRunLength(LogicalDirection.Forward); if (charOffset <= characterInCurrentRun) { int offset = charOffset - CurrentCharacterOffset; return(CurrentPosition.GetPositionAtOffset(offset, LogicalDirection.Forward)); } CurrentCharacterOffset = characterInCurrentRun; break; } } CurrentPosition = CurrentPosition.GetNextContextPosition(LogicalDirection.Forward); } if (CurrentCharacterOffset != 0 && charOffset <= CurrentCharacterOffset) { return(EndOfDocument.GetNextInsertionPosition(LogicalDirection.Backward)); } return(EndOfDocument); }
private void SaveCheckTextPointer() { CheckTextPointer = new TextPointer[lenofCheck + 1]; FlowDocument document = CheckTextBox.Document; TextPointer txNext = document.ContentStart; for (int i = 0; i <= lenofCheck; i++) { txNext = txNext.GetNextInsertionPosition(LogicalDirection.Forward); CheckTextPointer[i] = txNext; } for (int i = 0; i < lenofCheck; i++) { TextRange tr = new TextRange(CheckTextPointer[i], CheckTextPointer[i + 1]); //Console.WriteLine(tr.Text); } }
private static bool IsRichTextBoxEmpty(RichTextBox richTextBox) { // Taken from: // https://stackoverflow.com/a/5825644/10018492 // May need to be adapted a little bit, but for now, this seems to do what it's // supposed to do. if (richTextBox.Document.Blocks.Count == 0) { return(true); } TextPointer contentStart = richTextBox.Document.ContentStart; TextPointer contentEnd = richTextBox.Document.ContentEnd; TextPointer startPointer = contentStart.GetNextInsertionPosition(LogicalDirection.Forward); TextPointer endPointer = contentEnd.GetNextInsertionPosition(LogicalDirection.Backward); return(startPointer.CompareTo(endPointer) == 0); }
//returns [0]=Rect of char at end of first line, [1]=Rect of char at start of second line internal static Rect[] FindStartEndOfVisualLineRects(TextPointer start, Rect startRect) { TextPointer next = start; Rect nextRect; while ((next = next.GetNextInsertionPosition(LogicalDirection.Forward)) != null) { nextRect = next.GetCharacterRect(LogicalDirection.Forward); if (nextRect.Top != startRect.Top) { return new Rect[2] { next.GetCharacterRect(LogicalDirection.Backward), nextRect } } ; //for some reason next.GetCharacterRect(LogicalDirection.Backward) is not the same as 'prior' (prev value of 'next') } return(null); }