in src/Editor/Text/Impl/TextModel/Projection/ProjectionBuffer.cs [1498:1595]
private StringRebuilder InsertionLiesInSpan(ITextSnapshot afterSourceSnapshot,
int projectedPosition,
int spanPosition,
SnapshotSpan rawSpan,
Span deletionSpan,
int sourcePosition,
SpanTrackingMode mode,
ITextChange incomingChange,
HashSet<SnapshotPoint> urPoints,
SortedDictionary<int, SpanAdjustment> spanAdjustments,
int accumulatedDelta)
{
int renormalizedSourcePosition = sourcePosition + accumulatedDelta;
if (mode == SpanTrackingMode.Custom)
{
return InsertionLiesInCustomSpan(afterSourceSnapshot, spanPosition, incomingChange, urPoints, accumulatedDelta);
}
bool contains = rawSpan.Contains(sourcePosition);
if (mode == SpanTrackingMode.EdgeInclusive)
{
if ((this.bufferOptions & ProjectionBufferOptions.PermissiveEdgeInclusiveSourceSpans) != 0)
{
return InsertionLiesInPermissiveInclusiveSpan
(afterSourceSnapshot, rawSpan, deletionSpan, sourcePosition, renormalizedSourcePosition, incomingChange, urPoints);
}
else
{
return contains || sourcePosition == rawSpan.End ? TextChange.NewStringRebuilder(incomingChange) : StringRebuilder.Empty;
}
}
else
{
if (!this.editInProgress)
{
// Edit originated in the source buffer; we don't do any implicit growing
// of spans
bool included;
if (mode == SpanTrackingMode.EdgeNegative)
{
included = contains;
}
else if (mode == SpanTrackingMode.EdgePositive)
{
included = (sourcePosition != rawSpan.Start) && (contains || sourcePosition == rawSpan.End);
}
else
{
included = contains && sourcePosition != rawSpan.Start;
}
return included ? TextChange.NewStringRebuilder(incomingChange) : StringRebuilder.Empty;
}
else
{
if (sourcePosition == rawSpan.Start && (mode != SpanTrackingMode.EdgeNegative))
{
SnapshotPoint? urPoint = MappingHelper.MapDownToFirstMatchNoTrack(new SnapshotPoint(afterSourceSnapshot, renormalizedSourcePosition),
(buffer) => (buffer is TextBuffer),
PositionAffinity.Successor);
Debug.Assert(urPoint.HasValue);
if (urPoints.Add(urPoint.Value))
{
if (BufferGroup.Tracing)
{
Debug.WriteLine("UR-Point [exclusive:start]" + urPoint.Value.ToString());
}
// Insertion at exclusive left edge of source span: we need to grow the source span on the left
SpanAdjustment adjust = GetAdjustment(spanAdjustments, spanPosition);
// Create the text change that will be induced by the span adjustment
Debug.Assert(adjust.LeadingChange == null);
adjust.LeadingChange = TextChange.Create(projectedPosition, StringRebuilder.Empty, TextChange.NewStringRebuilder(incomingChange), this.currentProjectionSnapshot);
}
return StringRebuilder.Empty; // this insertion either already happened or happens on a subsequent transaction, not this one
}
else if (sourcePosition == rawSpan.End && (mode != SpanTrackingMode.EdgePositive))
{
SnapshotPoint? urPoint = MappingHelper.MapDownToFirstMatchNoTrack(new SnapshotPoint(afterSourceSnapshot, renormalizedSourcePosition),
(buffer) => (buffer is TextBuffer),
PositionAffinity.Predecessor);
Debug.Assert(urPoint.HasValue);
if (urPoints.Add(urPoint.Value))
{
if (BufferGroup.Tracing)
{
Debug.WriteLine("UR-Point [exclusive:end]" + urPoint.Value.ToString());
}
// Insertion at exclusive right edge of source span: we need to grow the source span on the right
SpanAdjustment adjust = GetAdjustment(spanAdjustments, spanPosition);
// Create the text change that will be induced by the span adjustment
Debug.Assert(adjust.TrailingChange == null);
adjust.TrailingChange = TextChange.Create(projectedPosition, StringRebuilder.Empty, TextChange.NewStringRebuilder(incomingChange), this.currentProjectionSnapshot);
}
return StringRebuilder.Empty; // this insertion either already happened or happens on a subsequent transaction, not this one
}
return (contains || (mode == SpanTrackingMode.EdgePositive && sourcePosition == rawSpan.End)) ? TextChange.NewStringRebuilder(incomingChange) : StringRebuilder.Empty;
}
}
}