public void TestUndoCommand()
        {
            // Arrange
            var project = new Project();
            var context = new BlockCommandContext(project);
            ProjectBlockCollection blocks = project.Blocks;
            Block block = blocks[0];
            using (block.AcquireBlockLock(RequestLock.Write))
            {
                block.SetText("abcd");
            }
            int blockVersion = block.Version;
            BlockKey blockKey = block.BlockKey;

            var command = new InsertTextCommand(new BlockPosition(blockKey, 2), "YES");
            project.Commands.Do(command, context);

            // Act
            project.Commands.Undo(context);

            // Assert
            Assert.AreEqual(1, blocks.Count);
            Assert.AreEqual(
                new BlockPosition(blocks[0], 2), project.Commands.LastPosition);

            const int index = 0;
            Assert.AreEqual("abcd", blocks[index].Text);
            Assert.AreEqual(blockVersion + 2, blocks[index].Version);
        }
        public ReplaceTextCommand(
			BlockPosition position,
			int length,
			string text)
            : base(position, true)
        {
            // Save the text for the changes.
            Length = length;
            Text = text;

            // Create the commands in this command.
            var deleteCommand = new DeleteTextCommand(
                position, (int) position.TextIndex + Length);
            var insertCommand = new InsertTextCommand(position, Text);

            Commands.Add(deleteCommand);
            Commands.Add(insertCommand);
        }
        public override LineBufferOperationResults InsertText(
			int lineIndex,
			int characterIndex,
			string text)
        {
            using (project.Blocks.AcquireLock(RequestLock.Write))
            {
                Block block = project.Blocks[lineIndex];
                var position = new BlockPosition(block.BlockKey, characterIndex);
                var command = new InsertTextCommand(position, text);
                var context = new BlockCommandContext(project);
                project.Commands.Do(command, context);

                return GetOperationResults();
            }
        }
        public void Do(BlockCommandContext context)
        {
            // We have to clear the undo buffer every time because we'll be creating
            // new blocks.
            addedBlocks.Clear();

            // Start by breaking apart the lines on the newline.
            string[] lines = Text.Split('\n');

            // Make changes to the first line by creating a command, adding it to the
            // list of commands we need an inverse for, and then performing it.
            Block block = context.Blocks[BlockPosition.BlockKey];
            string remainingText = block.Text.Substring((int) BlockPosition.TextIndex);
            deleteFirstCommand = new DeleteTextCommand(BlockPosition, block.Text.Length);
            insertFirstCommand = new InsertTextCommand(BlockPosition, lines[0]);

            deleteFirstCommand.Do(context);
            insertFirstCommand.Do(context);

            // Update the final lines text with the remains of the first line.
            int lastLineLength = lines[lines.Length - 1].Length;
            lines[lines.Length - 1] += remainingText;

            // For the remaining lines, we need to insert each one in turn.
            if (UpdateTextPosition.HasFlag(DoTypes.Do))
            {
                context.Position = BlockPosition.Empty;
            }

            if (lines.Length > 1)
            {
                // Go through all the lines in reverse order to insert them.
                int firstBlockIndex = context.Blocks.IndexOf(block);

                for (int i = lines.Length - 1;
                    i > 0;
                    i--)
                {
                    // Insert the line and set its text value.
                    var newBlock = new Block(context.Blocks);

                    addedBlocks.Add(newBlock);

                    using (newBlock.AcquireBlockLock(RequestLock.Write))
                    {
                        newBlock.SetText(lines[i]);
                    }

                    context.Blocks.Insert(firstBlockIndex + 1, newBlock);

                    // Update the last position as we go.
                    if (context.Position == BlockPosition.Empty)
                    {
                        if (UpdateTextPosition.HasFlag(DoTypes.Do))
                        {
                            context.Position = new BlockPosition(
                                newBlock.BlockKey, (CharacterPosition) lastLineLength);
                        }
                    }
                }
            }
        }