/// <summary> /// Removes the <see cref="Word"/>s in a given <see cref="TextRange"/> from variables still holding them. /// </summary> /// <param name="deletedRange"> /// A <see cref="TextRange"/> containing the text which was deleted. /// </param> private static void RemoveDeletedTextRange(TextRange deletedRange) { foreach ( var deletedWord in RecognitionEngine.AllWordsInCode.Where( word => deletedRange.Contains(word.StartPosition) || deletedRange.Contains(word.EndPosition)) .ToList()) { RecognitionEngine.AllWordsInCode.Remove(deletedWord); } }
private void SelectRange(TextPointer start, TextPointer end) { ClearSelection(); TextRange range = new TextRange(start, end); //ChatMessageCallout callout = this.FindParent<ChatMessageCallout>(); //Brush background = Application.Current.TryFindResource( "ForegroundBrush" ) as SolidColorBrush; //Brush foreground = Application.Current.TryFindResource( "ChatMessageCalloutNormalBackgroundBrush" ) as SolidColorBrush; //if( callout != null ) //{ // background = Foreground; // foreground = callout.Background; //} Brush background = FindBackground(); Brush foreground = FindForeground(); range.ApplyPropertyValue(TextElement.ForegroundProperty, background); range.ApplyPropertyValue(TextElement.BackgroundProperty, foreground); ContextMenu contextMenu = new ContextMenu(); contextMenu.Items.Add(new MenuItem { Header = "Copy", Command = ApplicationCommands.Copy }); ContextMenu = contextMenu; _selectedRange = range; foreach (Inline inline in Inlines) { if (inline is InlineUIContainer) { InlineUIContainer container = inline as InlineUIContainer; container.BaselineAlignment = BaselineAlignment.TextBottom; if (_selectedRange.Contains(container.ContentStart) && _selectedRange.Contains(container.ContentEnd)) { if (container.Child is Grid) { (container.Child as Grid).Background = foreground; TextElement.SetForeground(container.Child, background); } } } } if (string.IsNullOrEmpty(_selectedRange.Text)) { ClearContextMenu(); } }
private void OnCopy(object sender, ExecutedRoutedEventArgs e) { StringBuilder sb = new StringBuilder(); foreach (Inline inline in this.Inlines) { if (inline is Run) { Run run = inline as Run; if (run.Background != null) { //if( run.TextDecorations == System.Windows.TextDecorations.Strikethrough ) //{ // sb.AppendFormat( "-{0}-", run.Text ); //} //else if( run.TextDecorations == System.Windows.TextDecorations.Underline ) //{ // sb.AppendFormat( "_{0}_", run.Text ); //} //else if( run.FontWeight == FontWeights.Bold ) //{ // sb.AppendFormat( "*{0}*", run.Text ); //} //else if( run.FontStyle == FontStyles.Italic ) //{ // sb.AppendFormat( "/{0}/", run.Text ); //} //else { sb.Append(run.Text); } } } else if (inline is InlineUIContainer) { InlineUIContainer container = inline as InlineUIContainer; container.BaselineAlignment = BaselineAlignment.TextBottom; if (_selectedRange.Contains(container.ContentStart) && _selectedRange.Contains(container.ContentEnd)) { if (container.Child is Grid) { Grid image = container.Child as Grid; sb.Append(image.ToolTip); } } } } Clipboard.SetText(sb.ToString()); }
public override bool CzyPasuje(INotatka notatka) { string tresc = new TextRange(notatka.Tekst.ContentStart, notatka.Tekst.ContentEnd).Text; if (string.IsNullOrEmpty(tresc)) { return(false); } string[] tab = SlowaKluczowe.Split(' '); tresc = tresc.ToLower(); int i; for (i = 0; i < tab.Length; i++) { if (tresc.Contains(tab[i])) { break; } } if (i == tab.Length) { return(false); } return(filtr.CzyPasuje(notatka)); }
/// <summary> /// Finds deepest node that fully encloses given range /// </summary> public virtual IAstNode NodeFromRange(ITextRange range) { IAstNode node = null; if (TextRange.Contains(this, range)) { node = this; for (int i = 0; i < this.Children.Count; i++) { var child = Children[i]; if (range.End < child.Start) { break; } if (child.Contains(range.Start) && child.Contains(range.End)) { node = (child.Children.Count > 0) ? child.NodeFromRange(range) : child; break; } } } return(node); }
/// <summary> /// Finds deepest element node that fully encloses given range /// </summary> public ElementNode ElementFromRange(ITextRange range) { TreeNode item = null; if (TextRange.Contains(this, range)) { item = this; for (int i = 0; i < this.Children.Count; i++) { var child = Children[i]; if (range.End < child.Start) { break; } if (child.Contains(range.Start) && child.Contains(range.End)) { item = (child.Children.Count > 0) ? child.ElementFromRange(range) : child; break; } } } return(item as ElementNode); }
/// <summary> /// Finds deepest element node which inner range fully encloses given positions /// </summary> /// <param name="range">Range to analyze</param> /// <param name="inclusiveEnd">If true, element and range may have same end points</param> public ElementNode ElementEnclosingRange(ITextRange range, bool inclusiveEnd) { ElementNode item = null; if (!this.IsShorthand() && TextRange.Contains(this.InnerRange, range, inclusiveEnd)) { item = this; foreach (var child in Children) { if (range.End < child.Start) { break; } var element = child.ElementEnclosingRange(range, inclusiveEnd); if (element != null) { item = element; break; } } } return(item); }
public override ISpecificCodeCompletionContext GetCompletionContext(CodeCompletionContext context) { var unterminatedContext = new NTriplesReparsedCompletionContext(context.File, context.SelectedTreeRange, "aaa"); unterminatedContext.Init(); IReference referenceToComplete = unterminatedContext.Reference; ITreeNode elementToComplete = unterminatedContext.TreeNode; if (elementToComplete == null) { return(null); } TreeTextRange referenceRange = referenceToComplete != null ? referenceToComplete.GetTreeTextRange() : GetElementRange(elementToComplete); TextRange referenceDocumentRange = unterminatedContext.ToDocumentRange(referenceRange); if (!referenceDocumentRange.IsValid) { return(null); } if (!referenceDocumentRange.Contains(context.CaretDocumentRange.TextRange)) { return(null); } TextLookupRanges ranges = GetTextLookupRanges(context, referenceDocumentRange); return(new NTriplesCodeCompletionContext(context, ranges, unterminatedContext)); }
/// <summary> /// Examines the AST data to determine the context type and insert the containing function declaration. /// </summary> /// <param name="context">The <see cref="SimpleContext"/> to update.</param> private static void UpdateFromAst(SimpleContext context) { // Get the snapshot offset TextSnapshotOffset snapshotOffset = context.SnapshotOffset; // Get the document ICodeDocument document = snapshotOffset.Snapshot.Document as ICodeDocument; if (document == null) { return; } ILLParseData parseData = document.ParseData as ILLParseData; if (parseData != null) { CompilationUnit compilationUnit = parseData.Ast as CompilationUnit; if ((compilationUnit != null) && (compilationUnit.HasMembers)) { // Translate the snapshot offset to the AST's snapshot if (parseData.Snapshot != null) { snapshotOffset = snapshotOffset.TranslateTo(parseData.Snapshot, TextOffsetTrackingMode.Negative); } // Loop through AST nodes foreach (FunctionDeclaration functionAstNode in compilationUnit.Members) { // If the child node is a function declaration with valid offsets... if ((functionAstNode.StartOffset.HasValue) && (functionAstNode.EndOffset.HasValue)) { // If the function's text range contains the offset... TextRange functionTextRange = new TextRange(functionAstNode.StartOffset.Value, functionAstNode.EndOffset.Value); if (functionTextRange.Contains(snapshotOffset.Offset)) { // Initially assume we are in a header context.Type = SimpleContextType.FunctionDeclarationHeader; context.ContainingFunctionDeclaration = functionAstNode; // If the function has a body with a range... if ((functionAstNode.Body != null) && (functionAstNode.Body.StartOffset.HasValue) && (functionAstNode.Body.EndOffset.HasValue)) { // If the block's text range contains the offset... TextRange blockTextRange = new TextRange(functionAstNode.Body.StartOffset.Value + 1, functionAstNode.Body.EndOffset.Value - 1); if (blockTextRange.Contains(snapshotOffset.Offset)) { // Mark that we are in a block instead context.Type = SimpleContextType.FunctionDeclarationBlock; } } break; } } } } } }
public bool Contains(int position) { if (!this.IsWellFormed && position == _end) { return(true); } return(TextRange.Contains(this, position)); }
// </Snippet_TextRange_Text> // <Snippet_TextRange_StartEnd> // This method returns true if two specified selections overlap, including when the // end of one selection serves as the beginning of the other. bool DoSelectionsOverlap(TextRange selection1, TextRange selection2) { // Is either end of selection2 contained by selection1? if (selection1.Contains(selection2.Start) || selection1.Contains(selection2.End)) { // If so, the selections overlap. return true; } // If not, selection2 may still entirely contain selection1. // Is either end of selection1 contained by seleciotn2? else if (selection2.Contains(selection1.Start) || selection2.Contains(selection1.End)) { // If so, the selections overlap. return true; } // If neither selection contains the begging or end of the other selection, //the selections do not overlap. else return false; }
[TestCase(5, 6, false)] // after last line public void TestContains(int line, int column, bool expected) { var location1 = new TextLocation(2, 4); var location2 = new TextLocation(4, 6); var selection1 = new TextRange(location1, location2); var selection2 = new TextRange(location2, location1); var testLocation = new TextLocation(line, column); if (expected) { Assert.That(selection1.Contains(testLocation), Is.True); Assert.That(selection2.Contains(testLocation), Is.True); } else { Assert.That(selection1.Contains(testLocation), Is.False); Assert.That(selection2.Contains(testLocation), Is.False); } }
private void button1_Click(object sender, RoutedEventArgs e) { for (int i = 0; i < Google.API.Translate.Language.TranslatableCollection.Count(); i++) { string richText = new TextRange(richTextBox1.Document.ContentStart, richTextBox1.Document.ContentEnd).Text; richText.Contains(Google.API.Translate.Language.TranslatableCollection.ElementAt(i).ToString()); Translator translator = new Translator(); translator.translate(richText); } }
private string GetText() { var document = DocumentText.Document; var text = new TextRange(document.ContentStart, document.ContentEnd).Text; if (text.Contains("_")) { text = TextConverter.ConvertTextToDbo(text); } return(text); }
public void TextRange_ContainsTest() { TextRange r = TextRange.FromBounds(1, 3); TextRange.Contains(r, Int32.MinValue).Should().BeFalse(); TextRange.Contains(r, 0).Should().BeFalse(); TextRange.Contains(r, 1).Should().BeTrue(); TextRange.Contains(r, 2).Should().BeTrue(); TextRange.Contains(r, 3).Should().BeFalse(); TextRange.Contains(r, Int32.MaxValue).Should().BeFalse(); }
public void TextRange_ContainsTest1() { TextRange r = TextRange.FromBounds(1, 5); TextRange.Contains(r, TextRange.FromBounds(Int32.MinValue / 2, 0)).Should().BeFalse(); TextRange.Contains(r, TextRange.FromBounds(0, 1)).Should().BeFalse(); TextRange.Contains(r, TextRange.FromBounds(5, 6)).Should().BeFalse(); TextRange.Contains(r, TextRange.FromBounds(5, Int32.MaxValue / 2)).Should().BeFalse(); TextRange.Contains(r, TextRange.FromBounds(1, 2)).Should().BeTrue(); TextRange.Contains(r, TextRange.FromBounds(3, 4)).Should().BeTrue(); TextRange.Contains(r, TextRange.FromBounds(1, 5)).Should().BeFalse(); }
public override bool CzyPasuje(INotatka notatka) { string tresc = new TextRange(notatka.Tekst.ContentStart, notatka.Tekst.ContentEnd).Text; if (string.IsNullOrEmpty(tresc)) { return(false); } string[] tab = SlowaKluczowe.Split(' '); tresc = tresc.ToLower(); foreach (string s in tab) { if (!tresc.Contains(s)) { return(false); } } return(filtr.CzyPasuje(notatka)); }
private static bool IsADestructiveChangeForSeparator( ISensitiveFragmentSeparatorsInfo separatorInfo, IEnumerable <IArtifact> itemsInRange, int start, int oldLength, int newLength, ITextProvider oldText, ITextProvider newText ) { if (separatorInfo == null || (separatorInfo.LeftSeparator.Length == 0 && separatorInfo.RightSeparator.Length == 0)) { return(false); } // Find out if one of the existing fragments contains position // and if change damages fragment start or end separators string leftSeparator = separatorInfo.LeftSeparator; string rightSeparator = separatorInfo.RightSeparator; var firstTwoItems = itemsInRange.Take(2).ToList(); var item = firstTwoItems.FirstOrDefault(); // If no items are affected, change is unsafe only if new region contains left side separators. if (item == null) { // Simple optimization for whitespace insertion if (oldLength == 0 && string.IsNullOrWhiteSpace(newText.GetText(start, newLength))) { return(false); } // Take into account that user could have deleted space between existing // { and % or added { to the existing % so extend search range accordingly. int fragmentStart = Math.Max(0, start - leftSeparator.Length + 1); int fragmentEnd = Math.Min(newText.Length, start + newLength + leftSeparator.Length - 1); return(newText.IndexOf(leftSeparator, fragmentStart, fragmentEnd - fragmentStart, true) >= 0); } // Is change completely inside an existing item? if (firstTwoItems.Count == 1 && (item.Contains(start) && item.Contains(start + oldLength))) { // Check that change does not affect item left separator if (TextRange.Contains(item.Start, leftSeparator.Length, start)) { return(true); } // Check that change does not affect item right separator. Note that we should not be using // TextRange.Intersect since in case oldLength is zero (like when user is typing right before %} or }}) // TextRange.Intersect will determine that zero-length range intersects with the right separator // which is incorrect. Typing at position 10 does not change separator at position 10. Similarly, // deleting text right before %} or }} does not make change destructive. var htmlToken = item as IHtmlToken; if (htmlToken == null || htmlToken.IsWellFormed) { int rightSeparatorStart = item.End - rightSeparator.Length; if (start + oldLength > rightSeparatorStart) { if (TextRange.Intersect(rightSeparatorStart, rightSeparator.Length, start, oldLength)) { return(true); } } } // Touching left separator is destructive too, like when changing {{ to {{@ // Check that change does not affect item left separator (whitespace is fine) if (item.Start + leftSeparator.Length == start) { if (oldLength == 0) { string text = newText.GetText(start, newLength); if (String.IsNullOrWhiteSpace(text)) { return(false); } } return(true); } int fragmentStart = item.Start + separatorInfo.LeftSeparator.Length; fragmentStart = Math.Max(fragmentStart, start - separatorInfo.RightSeparator.Length + 1); int changeLength = newLength - oldLength; int fragmentEnd = item.End + changeLength; fragmentEnd = Math.Min(fragmentEnd, start + newLength + separatorInfo.RightSeparator.Length - 1); if (newText.IndexOf(separatorInfo.RightSeparator, fragmentStart, fragmentEnd - fragmentStart, true) >= 0) { return(true); } return(false); } return(true); }
private void ConfirmarButton_Click(object sender, RoutedEventArgs e) { EditarButton.Visibility = Visibility.Visible; ConfirmarButton.Visibility = Visibility.Collapsed; CancelarButton.Visibility = Visibility.Collapsed; bool valido = true; EmailBox.IsReadOnly = true; Localidade.IsReadOnly = true; string novoEmail = new TextRange(EmailBox.Document.ContentStart, EmailBox.Document.ContentEnd).Text; novoEmail = novoEmail.Replace(Environment.NewLine, ""); string novaLocalidade = new TextRange(Localidade.Document.ContentStart, Localidade.Document.ContentEnd).Text; novaLocalidade = novaLocalidade.Replace(Environment.NewLine, ""); List <String> novoConteudoFicheiro = new List <String>(); if (novoEmail.Equals(currentUser.email)) { valido = false; if (novaLocalidade.Equals(currentUser.localidade) == false) { RegisterPage registerpageobject = new RegisterPage(); List <UtilizadorInfo> utilizadores = registerpageobject.readRegisto(); foreach (UtilizadorInfo u in utilizadores) { if (u.id == currentUser.id) { string conteudo = u.id + "-" + u.tipoConta + "-" + u.email + "-" + u.username + "-" + u.password + "-" + novaLocalidade + "-" + u.foto + "-{"; foreach (int i in u.favoritos) { conteudo = conteudo + i + ","; } conteudo = conteudo + "}-{"; foreach (string s in u.reservas) { conteudo = conteudo + s + ","; } conteudo = conteudo + "}-{"; foreach (int i in u.user_institutos_id) { conteudo = conteudo + i + ","; } conteudo = conteudo + "}"; novoConteudoFicheiro.Add(conteudo); } else { string conteudo = u.id + "-" + u.tipoConta + "-" + u.email + "-" + u.username + "-" + u.password + "-" + u.localidade + "-" + u.foto + "-{"; foreach (int i in u.favoritos) { conteudo = conteudo + i + ","; } conteudo = conteudo + "}-{"; foreach (string s in u.reservas) { conteudo = conteudo + s + ","; } conteudo = conteudo + "}-{"; foreach (int i in u.user_institutos_id) { conteudo = conteudo + i + ","; } conteudo = conteudo + "}"; novoConteudoFicheiro.Add(conteudo); } } registarAlteracoes(novoConteudoFicheiro); } } else { if (novoEmail.Length < 3 || novoEmail.Contains('@') == false || novoEmail.Contains('.') == false) { valido = false; MessageBox.Show("Email is invalid"); } else { RegisterPage registerpageobject = new RegisterPage(); List <UtilizadorInfo> utilizadores = registerpageobject.readRegisto(); foreach (UtilizadorInfo u in utilizadores) { if (u.email.Equals(novoEmail)) { valido = false; MessageBox.Show("Email já em uso!"); } } } } if (valido) { if (novaLocalidade.Equals(currentUser.localidade)) { RegisterPage registerpageobject = new RegisterPage(); List <UtilizadorInfo> utilizadores = registerpageobject.readRegisto(); foreach (UtilizadorInfo u in utilizadores) { if (u.id == currentUser.id) { string conteudo = u.id + "-" + u.tipoConta + "-" + novoEmail + "-" + u.username + "-" + u.password + "-" + u.localidade + "-" + u.foto + "-{"; foreach (int i in u.favoritos) { conteudo = conteudo + i + ","; } conteudo = conteudo + "}-{"; foreach (string s in u.reservas) { conteudo = conteudo + s + ","; } conteudo = conteudo + "}-{"; foreach (int i in u.user_institutos_id) { conteudo = conteudo + i + ","; } conteudo = conteudo + "}"; novoConteudoFicheiro.Add(conteudo); } else { string conteudo = u.id + "-" + u.tipoConta + "-" + u.email + "-" + u.username + "-" + u.password + "-" + u.localidade + "-" + u.foto + "-{"; foreach (int i in u.favoritos) { conteudo = conteudo + i + ","; } conteudo = conteudo + "}-{"; foreach (string s in u.reservas) { conteudo = conteudo + s + ","; } conteudo = conteudo + "}-{"; foreach (int i in u.user_institutos_id) { conteudo = conteudo + i + ","; } conteudo = conteudo + "}"; novoConteudoFicheiro.Add(conteudo); } } registarAlteracoes(novoConteudoFicheiro); } else { RegisterPage registerpageobject = new RegisterPage(); List <UtilizadorInfo> utilizadores = registerpageobject.readRegisto(); foreach (UtilizadorInfo u in utilizadores) { if (u.id == currentUser.id) { string conteudo = u.id + "-" + u.tipoConta + "-" + novoEmail + "-" + u.username + "-" + u.password + "-" + novaLocalidade + "-" + u.foto + "-{"; foreach (int i in u.favoritos) { conteudo = conteudo + i + ","; } conteudo = conteudo + "}-{"; foreach (string s in u.reservas) { conteudo = conteudo + s + ","; } conteudo = conteudo + "}-{"; foreach (int i in u.user_institutos_id) { conteudo = conteudo + i + ","; } conteudo = conteudo + "}"; novoConteudoFicheiro.Add(conteudo); } else { string conteudo = u.id + "-" + u.tipoConta + "-" + u.email + "-" + u.username + "-" + u.password + "-" + u.localidade + "-" + u.foto + "-{"; foreach (int i in u.favoritos) { conteudo = conteudo + i + ","; } conteudo = conteudo + "}-{"; foreach (string s in u.reservas) { conteudo = conteudo + s + ","; } conteudo = conteudo + "}-{"; foreach (int i in u.user_institutos_id) { conteudo = conteudo + i + ","; } conteudo = conteudo + "}"; novoConteudoFicheiro.Add(conteudo); } } registarAlteracoes(novoConteudoFicheiro); } } EmailBox.IsReadOnly = true; Localidade.IsReadOnly = true; }
private bool IsCaretPositionValid() { var text = new TextRange(richTextBox1.CaretPosition, richTextBox1.CaretPosition.DocumentEnd).Text; return(!text.Contains(">")); }
public bool Contains(int position) { return(TextRange.Contains(this, position)); }
void OnTextChanged(object sender, RoutedEventArgs e) { string richText = new TextRange((sender as RichTextBox).Document.ContentStart, (sender as RichTextBox).Document.ContentEnd).Text; if (string.IsNullOrWhiteSpace(richText) && Regex.Matches(richText, "\\n").Count <= 1 && !richText.Contains(" ")) { (sender as RichTextBox).Tag = "Show"; } else { (sender as RichTextBox).Tag = "Hidden"; } }
/// <summary> /// Updates <see cref="WordType"/>s of the <see cref="Word"/>s in <see cref="MainClass.AllWordsInCode"/> according to the given <see cref="Word"/>. /// </summary> /// <param name="thisWord"> /// The <see cref="Word"/> which possibly changes its successors. /// </param> /// <param name="programmingLanguage"> /// A <see cref="ProgrammingLanguage"/> which holds important information for the <see cref="WordType"/>s. /// </param> /// <returns> /// A <see cref="List{Word}"/> containing all <see cref="Word"/>s which <see cref="WordType"/>s were changed. /// </returns> private static List <Word> UpdateWordTypes(Word thisWord, ProgrammingLanguage programmingLanguage) { var changedWords = new List <Word>(); switch (thisWord.Type) { case WordType.LineCommentary: var tempLineEnd = thisWord.StartPosition.GetLineStartPosition(1); var lineEnd = (tempLineEnd ?? thisWord.StartPosition.DocumentEnd).GetInsertionPosition(LogicalDirection.Backward); var lineCommentaryRange = new TextRange(thisWord.EndPosition, lineEnd); var lineCommentaryWords = AllWordsInCode.Where(word => lineCommentaryRange.Contains(word.StartPosition)).ToList(); foreach (var word in lineCommentaryWords) { Word newWord; ChangeWordType(word, out newWord); changedWords.Add(newWord); } break; case WordType.BlockCommentary: var endPointer = thisWord.StartPosition.DocumentEnd; try { var endWord = AllWordsInCode.First( word => thisWord.StartPosition.CompareTo(word.StartPosition) > 0 && word.Content.EndsWith(programmingLanguage.EndTokens["BlockCommentary"])); endPointer = endWord.EndPosition; } catch (InvalidOperationException) { } var blockCommentaryRange = new TextRange(thisWord.EndPosition, endPointer); var blockCommentaryWords = AllWordsInCode.Where(word => blockCommentaryRange.Contains(word.StartPosition)).ToList(); foreach (var word in blockCommentaryWords) { Word newWord; ChangeWordType(word, out newWord); changedWords.Add(newWord); } break; case WordType.Value: var endPosition = thisWord.StartPosition.DocumentEnd; try { var lastWord = AllWordsInCode.First( word => thisWord.StartPosition.CompareTo(word.StartPosition) > 0 && word.Content.EndsWith(programmingLanguage.EndTokens["String"])); endPosition = lastWord.EndPosition; } catch (InvalidOperationException) { } var stringRange = new TextRange(thisWord.EndPosition, endPosition); var stringWords = AllWordsInCode.Where(word => stringRange.Contains(word.StartPosition)).ToList(); foreach (var word in stringWords) { Word newWord; ChangeWordType(word, out newWord); changedWords.Add(newWord); } break; } return(changedWords); }
private bool IsDestructiveChangeForSeparator(ISensitiveFragmentSeparatorsInfo separatorInfo, IReadOnlyList <T> itemsInRange, int start, int oldLength, int newLength, ITextProvider oldText, ITextProvider newText) { if (separatorInfo == null) { return(false); } if (separatorInfo.LeftSeparator.Length == 0 && separatorInfo.RightSeparator.Length == 0) { return(false); } // Find out if one of the existing fragments contains position // and if change damages fragment start or end separators string leftSeparator = separatorInfo.LeftSeparator; string rightSeparator = separatorInfo.RightSeparator; // If no items are affected, change is unsafe only if new region contains left side separators. if (itemsInRange.Count == 0) { // Simple optimization for whitespace insertion if (oldLength == 0 && String.IsNullOrWhiteSpace(newText.GetText(new TextRange(start, newLength)))) { return(false); } int fragmentStart = Math.Max(0, start - leftSeparator.Length + 1); int fragmentEnd; // Take into account that user could have deleted space between existing // <! and -- or added - to the existing <!- so extend search range accordingly. fragmentEnd = Math.Min(newText.Length, start + newLength + leftSeparator.Length - 1); int fragmentStartPosition = newText.IndexOf(leftSeparator, TextRange.FromBounds(fragmentStart, fragmentEnd), true); if (fragmentStartPosition >= 0) { // We could've found the left separator only in the newly inserted text since we extended the range we examined // by one less than the separator length. Return true, no further checks necessary. return(true); } return(false); } // Is change completely inside an existing item? if (itemsInRange.Count == 1 && (itemsInRange[0].Contains(start) && itemsInRange[0].Contains(start + oldLength))) { // Check that change does not affect item left separator if (TextRange.Contains(itemsInRange[0].Start, leftSeparator.Length, start)) { return(true); } // Check that change does not affect item right separator. Note that we should not be using // TextRange.Intersect since in case oldLength is zero (like when user is typing right before %> or ?>) // TextRange.Intersect will determine that zero-length range intersects with the right separator // which is incorrect. Typing at position 10 does not change separator at position 10. Similarly, // deleting text right before %> or ?> does not make change destructive. IHtmlToken htmlToken = itemsInRange[0] as IHtmlToken; if (htmlToken == null || htmlToken.IsWellFormed) { int rightSeparatorStart = itemsInRange[0].End - rightSeparator.Length; if (start + oldLength > rightSeparatorStart) { if (TextRange.Intersect(rightSeparatorStart, rightSeparator.Length, start, oldLength)) { return(true); } } } // Touching left separator is destructive too, like when changing <% to <%@ // Check that change does not affect item left separator (whitespace is fine) if (itemsInRange[0].Start + leftSeparator.Length == start) { if (oldLength == 0) { string text = newText.GetText(new TextRange(start, newLength)); if (String.IsNullOrWhiteSpace(text)) { return(false); } } return(true); } int fragmentStart = itemsInRange[0].Start + separatorInfo.LeftSeparator.Length; fragmentStart = Math.Max(fragmentStart, start - separatorInfo.RightSeparator.Length + 1); int changeLength = newLength - oldLength; int fragmentEnd = itemsInRange[0].End + changeLength; fragmentEnd = Math.Min(fragmentEnd, start + newLength + separatorInfo.RightSeparator.Length - 1); if (newText.IndexOf(separatorInfo.RightSeparator, TextRange.FromBounds(fragmentStart, fragmentEnd), true) >= 0) { return(true); } return(false); } return(true); }