// We always favor the last buffer of our language type. This handles cases where we're on a boundary between a prompt and a language // buffer - we favor the language buffer because the prompts cannot be edited. In the case of two language buffers this also works because // our spans are laid out like: // <lang span 1 including newline> // <prompt span><lang span 2> // // In the case where the prompts are in the margin we have an insertion conflict between the two language spans. But because // lang span 1 includes the new line in order to be oun the boundary we need to be on lang span 2's line. // // This works the same way w/ our input buffer where the input buffer present instead of <lang span 2>. void IProjectionEditResolver.FillInInsertionSizes(SnapshotPoint projectionInsertionPoint, ReadOnlyCollection <SnapshotPoint> sourceInsertionPoints, string insertionText, IList <int> insertionSizes) { int index = _window.UIThread(uiOnly => IndexOfEditableBuffer(sourceInsertionPoints, uiOnly)); if (index != -1) { insertionSizes[index] = insertionText.Length; } }
/// <summary> /// Flushes the buffer, should always be called from the UI thread. /// </summary> public void Flush() { Entry firstEntryToFlush = null; int flushLength = 0; lock (_mutex) { // if we're rapidly outputting grow the threshold long curTime = s_stopwatch.ElapsedMilliseconds; if (curTime - _lastFlushTimeMilliseconds < 1000) { if (_flushThreshold < 1024 * 1024) { _flushThreshold *= 2; } } _lastFlushTimeMilliseconds = s_stopwatch.ElapsedMilliseconds; if (_unflushedLength > 0) { // normalize line breaks - the editor isn't happy about projections that cut "\r\n" line break in half: if (_lastEntry.Text[_lastEntry.Text.Length - 1] == '\r') { AddEntry("\n"); } firstEntryToFlush = _firstEntry; flushLength = _unflushedLength; _firstEntry = _lastEntry = null; _unflushedLength = 0; } _timer.IsEnabled = false; } if (firstEntryToFlush != null) { _window.UIThread(() => _window.AppendOutput(GetEntries(firstEntryToFlush), flushLength)); } }