// Helper for GetPositionAtWordBoundary. // Returns true when passed TextPointer is next to a wordBreak in requested direction. private static bool IsPositionNextToWordBreak(TextPointer position, LogicalDirection wordBreakDirection) { bool isAtWordBoundary = false; // Skip over any formatting. if (position.GetPointerContext(wordBreakDirection) != TextPointerContext.Text) { position = position.GetInsertionPosition(wordBreakDirection); } if (position.GetPointerContext(wordBreakDirection) == TextPointerContext.Text) { LogicalDirection oppositeDirection = (wordBreakDirection == LogicalDirection.Forward) ? LogicalDirection.Backward : LogicalDirection.Forward; char[] runBuffer = new char[1]; char[] oppositeRunBuffer = new char[1]; position.GetTextInRun(wordBreakDirection, runBuffer, /*startIndex*/0, /*count*/1); position.GetTextInRun(oppositeDirection, oppositeRunBuffer, /*startIndex*/0, /*count*/1); if (runBuffer[0] == ' ' && !(oppositeRunBuffer[0] == ' ')) { isAtWordBoundary = true; } } else { // If we're not adjacent to text then we always want to consider this position a "word break". // In practice, we're most likely next to an embedded object or a block boundary. isAtWordBoundary = true; } return isAtWordBoundary; }
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; }
/// <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; }
/// <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); } }
private TextPointer FindNextString(TextPointer tp) { char[] buffer = new char[1]; tp.GetTextInRun(LogicalDirection.Forward, buffer, 0, 1); return tp; }
private string GetAllTextFromPointer(TextPointer pointer, out TextPointer pointerOut) { string allText = null; pointerOut = null; while (pointer != null) { if (pointer.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text) { allText = pointer.GetTextInRun(LogicalDirection.Forward); pointerOut = pointer; } pointer = pointer.GetNextContextPosition(LogicalDirection.Forward); } return allText; }
/// <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; }
/// <summary> /// Writes the container into the specified XmlWriter. /// </summary> private void WriteContainer(TextPointer start, TextPointer end, XmlWriter writer) { TextElement textElement; System.Diagnostics.Debug.Assert(start != null); System.Diagnostics.Debug.Assert(end != null); System.Diagnostics.Debug.Assert(writer != null); _writer = writer; WriteWordXmlHead(); _cursor = start; while (_cursor.CompareTo(end) < 0) { switch (_cursor.GetPointerContext(_dir)) { case TextPointerContext.None: System.Diagnostics.Debug.Assert(false, "Next symbol should never be None if cursor < End."); break; case TextPointerContext.Text: RequireOpenRange(); _writer.WriteStartElement(WordXmlSerializer.WordTextTag); _writer.WriteString(_cursor.GetTextInRun(_dir)); _writer.WriteEndElement(); break; case TextPointerContext.EmbeddedElement: DependencyObject obj = _cursor.GetAdjacentElement(LogicalDirection.Forward); if (obj is LineBreak) { RequireOpenRange(); _writer.WriteStartElement(WordXmlSerializer.WordBreakTag); _writer.WriteEndElement(); } // TODO: try to convert some known embedded objects. break; case TextPointerContext.ElementStart: TextPointer position; position = _cursor; position = position.GetNextContextPosition(LogicalDirection.Forward); textElement = position.Parent as TextElement; if (textElement is Paragraph) { RequireClosedRange(); RequireOpenParagraph(); } else if (textElement is Inline) { RequireClosedRange(); RequireOpenParagraph(); RequireOpenRange(); } break; case TextPointerContext.ElementEnd: textElement = _cursor.Parent as TextElement; if (textElement is Inline) { RequireClosedRange(); } else if (textElement is Paragraph) { RequireClosedParagraph(); } break; } _cursor = _cursor.GetNextContextPosition(_dir); } RequireClosedRange(); WriteWordXmlTail(); }
private void ChangeFontSize(TextPointer currentPoint, double size, TextPointer endingPoint, bool increase) { // currentPoint can split text, but size is the text's size based on the enclosing tag // find the next position TextPointer next = currentPoint.GetNextContextPosition(LogicalDirection.Forward); //TextPointerContext nextCtx = currentPoint.GetPointerContext(LogicalDirection.Forward); int currentOffset = next.GetOffsetToPosition(endingPoint); TextPointer endOfApply = (currentOffset <= 0) ? endingPoint : next; // apply the style for this portion TextRange range = new TextRange(currentPoint, endOfApply); try { string text = currentPoint.GetTextInRun(LogicalDirection.Forward); double newSize = increase ? GetNextFontSize(size) : GetPreviousFontSize(size); range.ApplyPropertyValue(TextElement.FontSizeProperty, newSize); } catch (Exception) { // ignore return; } if (currentOffset <= 0) return; // done // what's next? object element = endOfApply.GetAdjacentElement(LogicalDirection.Forward); TextPointerContext ctx = endOfApply.GetPointerContext(LogicalDirection.Forward); if (element is UIElement) { UIElement uiElement = element as UIElement; } else if (element is TextElement) { TextElement textElement = element as TextElement; size = textElement.FontSize; ChangeFontSize(endOfApply, size, endingPoint, increase); } else { ChangeFontSize(endOfApply, size, endingPoint, increase); } return; // don't know what to do = done }
/// <summary> /// Get the characters before the TextPointer, going backwards to the first space /// </summary> /// <param name="txtPtr">TextPointer</param> /// <returns>string</returns> private string GetLastWordAtPointer(TextPointer txtPtr) { string textRunBack = txtPtr.GetTextInRun(LogicalDirection.Backward); //text from TextPointer backwards //get the last word in the text run string text = textRunBack.TrimEnd(); if (text.Contains(' ')) { text = text.Substring(text.LastIndexOf(' ') + 1); } //if a variable then it is case sensitive if ((text.Length > 0) && (text.First() == '$')) { return text; } return text.ToUpper(); }
private bool AtSpace(TextPointer txtPtr) { string textRunBack = txtPtr.GetTextInRun(LogicalDirection.Backward); return ((textRunBack.Length > 0) && (textRunBack.Last() == ' ')); }
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 static string GetWordCharactersBefore(TextPointer textPointer) { var backwards = textPointer.GetTextInRun(LogicalDirection.Backward); var wordCharactersBeforePointer = new string( backwards.Reverse() .TakeWhile(c => !char.IsSeparator(c) && !char.IsPunctuation(c)) .Reverse() .ToArray()); return wordCharactersBeforePointer; }
private static string GetWordCharactersAfter(TextPointer textPointer) { var fowards = textPointer.GetTextInRun(LogicalDirection.Forward); var wordCharactersAfterPointer = new string(fowards.TakeWhile(c => !char.IsSeparator(c) && !char.IsPunctuation(c)).ToArray()); return wordCharactersAfterPointer; }
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); } }
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; }