public bool InsertTextAsBox()

in src/Editor/Text/Impl/EditorOperations/EditorOperations.cs [3624:3798]


        public bool InsertTextAsBox(string text, out VirtualSnapshotPoint boxStart, out VirtualSnapshotPoint boxEnd, string undoText)
        {
            if (text == null)
                throw new ArgumentNullException(nameof(text));

            boxStart = boxEnd = _textView.Caret.Position.VirtualBufferPosition;

            // You can't use out parameters in a lambda or delegate, so just make a copy of
            // boxStart/boxEnd
            VirtualSnapshotPoint newStart, newEnd;
            newStart = newEnd = boxStart;

            if (text.Length == 0)
                return this.InsertText(text);

            Func<bool> action = () =>
            {
                // Separate edit transaction for the delete
                if (!DeleteHelper(_textView.Selection.SelectedSpans))
                    return false;

                // Put the selection in box mode for this operation
                _textView.Selection.Mode = TextSelectionMode.Box;

                _textView.Caret.MoveTo(_textView.Selection.Start);

                // Remember the starting position
                VirtualSnapshotPoint oldCaretPos = _textView.Caret.Position.VirtualBufferPosition;
                double startX = _textView.Caret.Left;

                // Estimate the number of spaces to the caret, to be used
                // for any amount of text that goes past the end of the buffer
                int spacesToCaret = _editorPrimitives.View.GetTextPoint(oldCaretPos.Position).DisplayColumn + oldCaretPos.VirtualSpaces;

                ITrackingPoint endPoint = null;
                int? firstLineInsertedVirtualSpaces = null;

                using (ITextEdit textEdit = _editorPrimitives.Buffer.AdvancedTextBuffer.CreateEdit())
                {
                    VirtualSnapshotPoint currentCaret = oldCaretPos;
                    ITextViewLine currentLine = _textView.GetTextViewLineContainingBufferPosition(currentCaret.Position);

                    bool pastEndOfBuffer = false;

                    // Read a line at a time from the given text, inserting each line of text
                    // into the buffer at a successive line below the line the caret is on.
                    // For any text left over at the end of the buffer, insert endlines as
                    // well (to create new lines at the end of the file), with virtual space
                    // for padding.
                    using (StringReader reader = new StringReader(text))
                    {
                        for (string lineText = reader.ReadLine(); lineText != null;)
                        {
                            if (lineText.Length > 0)
                            {
                                // Remember the endPoint, for determining the boxEnd argument
                                endPoint = _textView.TextSnapshot.CreateTrackingPoint(currentCaret.Position, PointTrackingMode.Positive);

                                int whitespaceLength = 0;

                                // Add on any virtual space needed
                                if (currentCaret.IsInVirtualSpace)
                                {
                                    string whitespace = GetWhitespaceForVirtualSpace(currentCaret);
                                    lineText = whitespace + lineText;
                                    whitespaceLength = whitespace.Length;
                                }

                                // Update information about the first inserted line
                                if (!firstLineInsertedVirtualSpaces.HasValue)
                                {
                                    firstLineInsertedVirtualSpaces = whitespaceLength;
                                    oldCaretPos = currentCaret;
                                }

                                // Insert the text as part of this edit transaction
                                if (!textEdit.Insert(currentCaret.Position, lineText))
                                    return false;
                            }

                            // We've already read past the end of the buffer, so we're done
                            if (pastEndOfBuffer)
                                break;

                            // If this is the last line in the file, collect the rest
                            // of the text to insert.
                            if (currentLine.LineBreakLength == 0)
                            {
                                string whitespace = GetWhitespaceForDisplayColumn(spacesToCaret);
                                string newline = _editorOptions.GetNewLineCharacter();

                                string extraLine = null;
                                lineText = string.Empty;
                                string blankLines = string.Empty;
                                while ((extraLine = reader.ReadLine()) != null)
                                {
                                    // Either add the line (if there is any text), or
                                    // just add the newline
                                    if (extraLine.Length > 0)
                                    {
                                        lineText += blankLines + // Any blank lines
                                                    newline + // a line break, to get a new line
                                                    whitespace + // realized virtual space
                                                    extraLine; // the line text itself

                                        blankLines = string.Empty;
                                    }
                                    else
                                    {
                                        blankLines += newline;
                                    }
                                }

                                pastEndOfBuffer = true;

                                currentCaret = new VirtualSnapshotPoint(currentLine.EndIncludingLineBreak);
                                // Current line hasn't changed, so we don't need to set it again
                            }
                            else // Otherwise, try and read the next line
                            {
                                lineText = reader.ReadLine();

                                if (lineText != null)
                                {
                                    currentLine = _textView.GetTextViewLineContainingBufferPosition(currentLine.EndIncludingLineBreak);
                                    currentCaret = currentLine.GetInsertionBufferPositionFromXCoordinate(startX);
                                }
                            }
                        }
                    }

                    // If we didn't actually insert any text, then cancel the edit and return false
                    if (endPoint == null)
                    {
                        textEdit.Cancel();
                        return false;
                    }

                    textEdit.Apply();

                    if (textEdit.Canceled)
                        return false;
                }

                // Now, figure out the start and end positions
                // and update the caret and selection.
                _textView.Selection.Clear();

                // Move the caret back to the starting point, which is now
                // no longer in virtual space.
                int virtualSpaces = firstLineInsertedVirtualSpaces.HasValue ? firstLineInsertedVirtualSpaces.Value : 0;

                _textView.Caret.MoveTo(new SnapshotPoint(_textView.TextSnapshot,
                                                         oldCaretPos.Position.Position + virtualSpaces));

                newStart = _textView.Caret.Position.VirtualBufferPosition;

                // endPoint was a forward-tracking point at the beginning of the last insertion,
                // so it should be positioned at the very end of the inserted text in the new
                // snapshot.
                newEnd = new VirtualSnapshotPoint(endPoint.GetPoint(_textView.TextSnapshot));

                return true;
            };

            bool succeeded = ExecuteAction(undoText, action);

            if (succeeded)
            {
                boxStart = newStart;
                boxEnd = newEnd;
            }

            return succeeded;
        }