public static bool Intersects(TextSpan span1, TextSpan span2) { return(TextSpanHelper.StartsBeforeEndOf(span1, span2) && TextSpanHelper.EndsAfterStartOf(span1, span2)); }
const int ChunkThreshold = 1000; // don't combine chunks separate by more than 1000 characters. ArrayList MergeEdits(ArrayList edits) { StringBuilder buffer = new StringBuilder(); EditSpan combined = null; ArrayList merged = new ArrayList(); ArrayList markers = GetTextMarkers(); int markerPos = 0; TextSpan marker = (markers.Count > 0) ? (TextSpan)markers[0] : new TextSpan(); foreach (EditSpan editSpan in edits) { TextSpan span = editSpan.Span; string text = editSpan.Text; if (markerPos < markers.Count && (TextSpanHelper.StartsAfterStartOf(span, marker) || TextSpanHelper.EndsAfterStartOf(span, marker))) { AddCombinedEdit(combined, buffer, merged); if (TextSpanHelper.Intersects(span, marker)) { combined = null; // Have to apply this as a distinct edit operation. merged.Add(editSpan); } else { combined = editSpan; buffer.Append(text); } while (++markerPos < markers.Count) { marker = (TextSpan)markers[markerPos]; if (!TextSpanHelper.StartsAfterStartOf(span, marker) && !TextSpanHelper.EndsAfterStartOf(span, marker)) { break; } } } else if (combined == null) { combined = editSpan; buffer.Append(text); } else { // A little sanity check here, if there are too many characters in between the two // edits, then keep them separate. TextSpan s = combined.Span; string between = this.source.GetText(s.iEndLine, s.iEndIndex, span.iStartLine, span.iStartIndex); if (between.Length > ChunkThreshold) { AddCombinedEdit(combined, buffer, merged); combined = editSpan; buffer.Append(text); } else { // merge edit spans by adding the text in-between the current and previous spans. buffer.Append(between); buffer.Append(text); // and add the new text. s.iEndIndex = span.iEndIndex; s.iEndLine = span.iEndLine; combined.Span = s; } } } AddCombinedEdit(combined, buffer, merged); return(merged); }