in Nodejs/Product/Nodejs/Jade/Text/TextRangeCollection.cs [694:792]
public virtual ICollection<T> ReflectTextChange(int start, int oldLength, int newLength, bool startInclusive)
{
var indexStart = GetItemContaining(start);
var indexEnd = GetItemContaining(start + oldLength);
ICollection<T> removed = _emptyList;
// Make sure that end of the deleted range is not simply touching start
// of an existing range since deleting span that is touching an existing
// range does not invalidate the existing range: |__r1__|deleted|__r2__|
if (indexEnd > indexStart && indexStart >= 0)
{
if (this[indexEnd].Start == start + oldLength)
{
indexEnd--;
}
}
if (indexStart != indexEnd || (indexStart < 0 && indexEnd < 0))
{
removed = RemoveInRange(new TextRange(start, oldLength));
}
if (this.Count > 0)
{
var offset = newLength - oldLength;
if (removed != _emptyList && removed.Count > 0)
{
indexStart = GetItemContaining(start);
}
if (indexStart >= 0)
{
// If range length is 0 it still contains the position.
// Don't try and shrink zero length ranges and instead
// shift them.
var range = this[indexStart];
if (range.Length == 0 && offset < 0)
{
range.Shift(offset);
}
else if (!startInclusive && oldLength == 0 && start == range.Start)
{
// range.Contains(start) is true but we don't want to expand
// the range if change is actually an insert right before
// the existing range like in {some text inserted}|__r1__|
range.Shift(offset);
}
else
{
// In Razor ranges may have end-inclusive set which
// may cause us to try and shrink zero-length ranges.
if (range.Length > 0 || offset > 0)
{
// In the case when range is end-inclusive as in Razor,
// and change is right at the end of the range, we may end up
// trying to shrink range that is really must be deleted.
// If offset is bigger than the range length, delete it instead.
if ((range is IExpandableTextRange) && (range.Length + offset >= 0))
{
var expandable = range as IExpandableTextRange;
expandable.Expand(0, offset);
}
else if (range is ICompositeTextRange)
{
var composite = range as ICompositeTextRange;
composite.ShiftStartingFrom(start, offset);
}
else
{
RemoveAt(indexStart);
indexStart--;
if (removed == _emptyList)
{
removed = new List<T>();
}
removed.Add(range);
}
}
}
for (var i = indexStart + 1; i < this.Count; i++)
{
this[i].Shift(offset);
}
}
else
{
ShiftStartingFrom(start, offset);
}
}
return removed;
}