protected virtual void OnTextChanged(object sender, TextContentChangedEventArgs e) { TextUtility.CombineChanges(e, out var start, out var oldLength, out var newLength); // check if change is still within current snapshot. the problem is that // change could have been calculated against projected buffer and then // host (HTML editor) could have dropped projections effectively // shortening buffer to nothing. var snapshot = this.TextBuffer.CurrentSnapshot; if (start > snapshot.Length || start + newLength > snapshot.Length) { start = 0; newLength = snapshot.Length; } OnTextChanged(start, oldLength, newLength); }
protected virtual void OnTextBufferChanged(object sender, TextContentChangedEventArgs e) { // In order to provide nicer experience when user presser and holds // ENTER or DELETE or just types really fast, we are going to track // regions optimistically and report changes without going through // async or idle processing. Idle/async is still going to hit later. if (e.Changes.Count > 0) { TextUtility.CombineChanges(e, out var start, out var oldLength, out var newLength); var changeStart = int.MaxValue; var changeEnd = 0; lock (this._regionsLock) { // Remove affected regions and shift the remaining ones. Outlining // regions are not sorted and can overlap. Hence linear search. for (var i = 0; i < this.CurrentRegions.Count; i++) { var region = this.CurrentRegions[i]; if (region.End <= start) { continue; } if (region.Contains(start) && region.Contains(start + oldLength)) { region.Expand(0, newLength - oldLength); } else if (region.Start >= start + oldLength) { region.Shift(newLength - oldLength); } else { this.CurrentRegions.RemoveAt(i); i--; } changeStart = Math.Min(changeStart, region.Start); changeEnd = Math.Max(changeEnd, region.End); } if (changeStart < int.MaxValue) { this.CurrentRegions.TextBufferVersion = this.TextBuffer.CurrentSnapshot.Version.VersionNumber; } } if (changeStart < int.MaxValue) { if (this.RegionsChanged != null) { this.RegionsChanged(this, new OutlineRegionsChangedEventArgs(this.CurrentRegions, TextRange.FromBounds(changeStart, changeEnd))); } } } }