private void MergeTextChangeRight(TextChange oldChange, TextChange newChange, int offset, int length) 
        {
            // If the old change is an addition, find the length of the overlap 
            // and adjust the addition and new deletion counts accordingly
            int addedLengthOverlap = oldChange.AddedLength > 0 ? offset + length - oldChange.Offset : 0;

#if PROPERTY_CHANGES 
            // Check for a property change in the new change that overlaps the old change
            int propertyOverlap = newChange.Offset + newChange.PropertyCount - oldChange.Offset; 
            if (propertyOverlap > 0) 
            {
                int delta = Math.Min(propertyOverlap, addedLengthOverlap); 
                newChange.SetPropertyCount(newChange.PropertyCount - delta);
                // Don't need to adjust oldChange.PropertyCount, since oldChange is about to be removed
            }
#endif 

            // adjust removed count 
            if (addedLengthOverlap >= oldChange.AddedLength) 
            {
                // old change is entirely within new one 
                newChange.RemovedLength += (oldChange.RemovedLength - oldChange.AddedLength);
                Changes.Remove(oldChange.Offset);
            }
            else 
            {
                newChange.RemovedLength += (oldChange.RemovedLength - addedLengthOverlap); 
                newChange.AddedLength += (oldChange.AddedLength - addedLengthOverlap); 
                Changes.Remove(oldChange.Offset);
            } 
        }
 private bool MergePropertyChange(TextChange leftChange, TextChange rightChange) 
 {
     if (leftChange.Offset + leftChange.PropertyCount >= rightChange.Offset) 
     { 
         if (leftChange.Offset + leftChange.PropertyCount < rightChange.Offset + rightChange.PropertyCount)
         { 
             // right change is partially inside left, but not completely.
             int overlap = leftChange.Offset + leftChange.PropertyCount - rightChange.Offset;
             int delta = rightChange.PropertyCount - overlap;
             leftChange.SetPropertyCount(leftChange.PropertyCount + delta); 
         }
         rightChange.SetPropertyCount(0); 
         return true; 
     }
     return false; 
 }
        // returns true if the change merged into an earlier insertion 
        private bool MergeTextChangeLeft(TextChange oldChange, TextChange newChange, bool isDeletion, int length)
        { 
            // newChange is inserting or deleting text inside oldChange.
            int overlap;

#if PROPERTY_CHANGES 
            // Check for a property change in the old change that overlaps the new change
            if (oldChange.Offset + oldChange.PropertyCount >= newChange.Offset) 
            { 
                if (isDeletion)
                { 
                    overlap = oldChange.PropertyCount - (newChange.Offset - oldChange.Offset);
                    oldChange.SetPropertyCount(oldChange.PropertyCount - Math.Min(overlap, length));
                    DeleteChangeIfEmpty(oldChange);
                } 
                else
                { 
                    oldChange.SetPropertyCount(oldChange.PropertyCount + length); 
                }
            } 
#endif

            if (oldChange.Offset + oldChange.AddedLength >= newChange.Offset)
            { 
                // If any text was deleted in the new change, adjust the added count of the
                // previous change accordingly.  The removed count of the new change must be 
                // adjusted by the same amount. 
                if (isDeletion)
                { 
                    overlap = oldChange.AddedLength - (newChange.Offset - oldChange.Offset);
                    int cancelledCount = Math.Min(overlap, newChange.RemovedLength);
                    oldChange.AddedLength -= cancelledCount;
                    oldChange.RemovedLength += (length - cancelledCount); 
                }
                else 
                { 
                    oldChange.AddedLength += length;
                } 
#if PROPERTY_CHANGES
                if (newChange.PropertyCount == 0)
                {
                    // We've merged the data from the new change into an older one, so we can 
                    // delete the change from the list.
                    Changes.Remove(newChange.Offset); 
                } 
                else
                { 
                    // Can't delete the change, since there's pre-existing property change data, so
                    // just clear the data instead.
                    newChange.AddedLength = 0;
                    newChange.RemovedLength = 0; 
                }
#else 
                // We've merged the data from the new change into an older one, so we can 
                // delete the change from the list.
                Changes.Remove(newChange.Offset); 
#endif
                return true;
            }
            return false; 
        }