void UpdateTextMarkerSearch() { if (!IsSearchControlVisible) return; if (SearchString.Length == 0) { var oldColl = findResultCollection; findResultCollection = NormalizedSnapshotSpanCollection.Empty; if (oldColl != null && oldColl.Count != 0) RefreshAllTags(); SetFoundResult(true); return; } var snapshot = wpfTextView.TextSnapshot; var searchRange = new SnapshotSpan(snapshot, 0, snapshot.Length); var options = GetFindOptions(searchKind, true); int count = 0; try { var list = new List<SnapshotSpan>(); foreach (var res in textSearchService2.FindAll(searchRange, SearchString, options)) { if (res.Length != 0) list.Add(res); count++; if (count == MAX_SEARCH_RESULTS) break; } findResultCollection = new NormalizedSnapshotSpanCollection(list); } catch (ArgumentException) when ((options & FindOptions.UseRegularExpressions) != 0) { // Invalid regex string findResultCollection = NormalizedSnapshotSpanCollection.Empty; count = 0; } RefreshAllTags(); SetFoundResult(count != 0); }
public bool Find() { if (SearchTerm == null) { throw new InvalidOperationException(); } if (SearchTerm.Length == 0) { throw new InvalidOperationException(); } SnapshotPoint startingPosition; if (CurrentResult != null) { if ((SearchOptions & FindOptions.SearchReverse) != 0) { if (CurrentResult.Value.End.Position > 0) { startingPosition = CurrentResult.Value.End - 1; } else if ((SearchOptions & FindOptions.Wrap) != 0) { startingPosition = new SnapshotPoint(CurrentResult.Value.Snapshot, CurrentResult.Value.Snapshot.Length); } else { return(FindFailed()); } } else { if (CurrentResult.Value.Start.Position != CurrentResult.Value.Snapshot.Length) { startingPosition = CurrentResult.Value.Start + 1; } else if ((SearchOptions & FindOptions.Wrap) != 0) { startingPosition = new SnapshotPoint(CurrentResult.Value.Snapshot, 0); } else { return(FindFailed()); } } } else if (StartPoint != null) { startingPosition = StartPoint.Value; } else { startingPosition = new SnapshotPoint(buffer.CurrentSnapshot, 0); } startingPosition = startingPosition.TranslateTo(buffer.CurrentSnapshot, (SearchOptions & FindOptions.SearchReverse) != 0 ? PointTrackingMode.Negative : PointTrackingMode.Positive); var spanToUse = searchSpan?.GetSpan(buffer.CurrentSnapshot) ?? new SnapshotSpan(buffer.CurrentSnapshot, 0, buffer.CurrentSnapshot.Length); if (!IsValidStartingPosition(spanToUse, startingPosition)) { return(FindFailed()); } foreach (var result in textSearchService2.FindAll(spanToUse, startingPosition, SearchTerm, SearchOptions)) { currentResult = result; return(true); } return(FindFailed()); }
public bool Find() { if (string.IsNullOrEmpty(this.SearchTerm)) { throw new InvalidOperationException("You must set a non-empty search term before searching."); } bool forward = (this.SearchOptions & FindOptions.SearchReverse) != FindOptions.SearchReverse; bool wrap = (this.SearchOptions & FindOptions.Wrap) == FindOptions.Wrap; bool regEx = (this.SearchOptions & FindOptions.UseRegularExpressions) == FindOptions.UseRegularExpressions; ITextSnapshot searchSnapshot = _buffer.CurrentSnapshot; //There could be a version skew here if someone calls find from inside a text changed callback on the buffer. That probably wouldn't be a good //idea but we need to handle it gracefully. this.AdvanceToSnapshot(searchSnapshot); SnapshotPoint?searchStart = this.CalculateStartPoint(searchSnapshot, wrap, forward); if (searchStart.HasValue) { int index = 0; NormalizedSnapshotSpanCollection searchSpans = this.SearchSpans; if (searchSpans != null) { Debug.Assert(searchSpans.Count > 0); //Index is potentially outside the range of [0...searchSpans.Count-1] but we handle that below. if (!(TextSearchNavigator.TryGetIndexOfContainingSpan(searchSpans, searchStart.Value, out index) || forward)) { //For reversed searches, we want the index of the span before the point if we can't get a span that contains the point. --index; } } else { searchSpans = new NormalizedSnapshotSpanCollection(new SnapshotSpan(searchSnapshot, Span.FromBounds(0, searchSnapshot.Length))); } int searchIterations = searchSpans.Count; for (int i = 0; (i < searchIterations); ++i) { //index needs to be normalized to [0 ... searchSpans.Count - 1] but could be negative. index = (index + searchSpans.Count) % searchSpans.Count; SnapshotSpan searchSpan = searchSpans[index]; if ((i != 0) || (searchStart.Value < searchSpan.Start) || (searchStart.Value > searchSpan.End)) { searchStart = forward ? searchSpan.Start : searchSpan.End; } else if (wrap && (i == 0)) { //We will need to repeat the search to account for wrap being on and we are not searching everything in searchSpans[0]. //This is the same as simply doing a search for i == searchSpans.Count we we can make happen by bumping the number of iterations. ++searchIterations; } foreach (var result in _textSearchService.FindAll(searchSpan, searchStart.Value, this.SearchTerm, this.SearchOptions & ~FindOptions.Wrap)) { // As a safety measure, we don't include results of length zero in the navigator unless regular expressions are being used. // Zero width matches could be useful in RegEx when for example somebody is trying to replace the start of the line using the "^" // pattern. if (result.Length == 0 && !regEx) { continue; } else { // We accept the first match this.CurrentResult = result; return(true); } } if (forward) { ++index; } else { --index; } } } // If nothing was found, then clear the current result this.ClearCurrentResult(); return(false); }