/// <summary>
        /// This is called by AddUndo, so that primitives are always in a fully merged state as we go.
        /// </summary>
        protected void MergeMostRecentUndoPrimitive()
        {
            // no merging unless there are at least two items
            if (_primitives.Count < 2)
            {
                return;
            }

            ITextUndoPrimitive top = _primitives[_primitives.Count - 1];

            ITextUndoPrimitive victim = null;
            int victimIndex           = -1;

            for (int i = _primitives.Count - 2; i >= 0; --i)
            {
                if (top.GetType() == _primitives[i].GetType() && top.CanMerge(_primitives[i]))
                {
                    victim      = _primitives[i];
                    victimIndex = i;
                    break;
                }
            }

            if (victim != null)
            {
                ITextUndoPrimitive newPrimitive = top.Merge(victim);
                _primitives.RemoveRange(_primitives.Count - 1, 1);
                _primitives.RemoveRange(victimIndex, 1);
                _primitives.Add(newPrimitive);
            }
        }
        public bool CanMerge(ITextUndoTransaction newTransaction, ITextUndoTransaction oldTransaction)
        {
            MergeUndoActionPolicy oldPolicy = oldTransaction.MergePolicy as MergeUndoActionPolicy;
            MergeUndoActionPolicy newPolicy = newTransaction.MergePolicy as MergeUndoActionPolicy;

            if (oldPolicy != null && oldPolicy._mergeNext &&
                newPolicy != null && newPolicy._mergePrevious &&
                oldPolicy._actionName == newPolicy._actionName)
            {
                // If one of the transactions is empty, than it is safe to merge
                if (newTransaction.UndoPrimitives.Count == 0 ||
                    oldTransaction.UndoPrimitives.Count == 0)
                {
                    return(true);
                }

                // Make sure that we only merge consecutive edits
                ITextUndoPrimitive newPrimitive = newTransaction.UndoPrimitives[0];
                ITextUndoPrimitive oldPrimitive = oldTransaction.UndoPrimitives[oldTransaction.UndoPrimitives.Count - 1];

                return(newPrimitive.CanMerge(oldPrimitive));
            }

            return(false);
        }
        public bool CanMerge(ITextUndoTransaction newTransaction, ITextUndoTransaction oldTransaction)
        {
            // Validate
            if (newTransaction == null)
            {
                throw new ArgumentNullException(nameof(newTransaction));
            }

            if (oldTransaction == null)
            {
                throw new ArgumentNullException(nameof(oldTransaction));
            }

            TextTransactionMergePolicy oldPolicy = oldTransaction.MergePolicy as TextTransactionMergePolicy;
            TextTransactionMergePolicy newPolicy = newTransaction.MergePolicy as TextTransactionMergePolicy;

            if (oldPolicy == null || newPolicy == null)
            {
                throw new InvalidOperationException("The MergePolicy for both transactions should be a TextTransactionMergePolicy.");
            }

            // Make sure the merge policy directions permit merging these two transactions.
            if ((oldPolicy._allowableMergeDirections & TextTransactionMergeDirections.Forward) == 0 ||
                (newPolicy._allowableMergeDirections & TextTransactionMergeDirections.Backward) == 0)
            {
                return(false);
            }

            // Only merge text transactions that have the same description
            if (!string.Equals(newTransaction.Description, oldTransaction.Description, StringComparison.Ordinal))
            {
                return(false);
            }

            // If one of the transactions is empty, than it is safe to merge
            if ((newTransaction.UndoPrimitives.Count == 0) || (oldTransaction.UndoPrimitives.Count == 0))
            {
                return(true);
            }

            // Make sure that we only merge consecutive edits
            ITextUndoPrimitive newerBeforeTextChangePrimitive = newTransaction.UndoPrimitives[0];
            ITextUndoPrimitive olderAfterTextChangePrimitive  = oldTransaction.UndoPrimitives[oldTransaction.UndoPrimitives.Count - 1];

            return(newerBeforeTextChangePrimitive.CanMerge(olderAfterTextChangePrimitive));
        }