/// <summary>
        ///     Calculates the inverted OffsetChangeMap (used for the undo operation).
        /// </summary>
        public OffsetChangeMap Invert()
        {
            if (this == Empty)
            {
                return(this);
            }
            var newMap = new OffsetChangeMap(Count);

            for (var i = Count - 1; i >= 0; i--)
            {
                var entry = this[i];
                // swap InsertionLength and RemovalLength
                newMap.Add(new OffsetChangeMapEntry(entry.Offset, entry.InsertionLength, entry.RemovalLength));
            }
            return(newMap);
        }
示例#2
0
        /// <summary>
        ///     Replaces text.
        /// </summary>
        /// <param name="offset">The starting offset of the text to be replaced.</param>
        /// <param name="length">The length of the text to be replaced.</param>
        /// <param name="text">The new text.</param>
        /// <param name="offsetChangeMappingType">
        ///     The offsetChangeMappingType determines how offsets inside the old text are mapped to the new text.
        ///     This affects how the anchors and segments inside the replaced region behave.
        /// </param>
        public void Replace(int offset, int length, ITextSource text, OffsetChangeMappingType offsetChangeMappingType)
        {
            if (text == null)
            {
                throw new ArgumentNullException("text");
            }
            // Please see OffsetChangeMappingType XML comments for details on how these modes work.
            switch (offsetChangeMappingType)
            {
            case OffsetChangeMappingType.Normal:
                Replace(offset, length, text, null);
                break;

            case OffsetChangeMappingType.KeepAnchorBeforeInsertion:
                Replace(offset, length, text, OffsetChangeMap.FromSingleElement(
                            new OffsetChangeMapEntry(offset, length, text.TextLength, false, true)));
                break;

            case OffsetChangeMappingType.RemoveAndInsert:
                if (length == 0 || text.TextLength == 0)
                {
                    // only insertion or only removal?
                    // OffsetChangeMappingType doesn't matter, just use Normal.
                    Replace(offset, length, text, null);
                }
                else
                {
                    var map = new OffsetChangeMap(2);
                    map.Add(new OffsetChangeMapEntry(offset, length, 0));
                    map.Add(new OffsetChangeMapEntry(offset, 0, text.TextLength));
                    map.Freeze();
                    Replace(offset, length, text, map);
                }
                break;

            case OffsetChangeMappingType.CharacterReplace:
                if (length == 0 || text.TextLength == 0)
                {
                    // only insertion or only removal?
                    // OffsetChangeMappingType doesn't matter, just use Normal.
                    Replace(offset, length, text, null);
                }
                else if (text.TextLength > length)
                {
                    // look at OffsetChangeMappingType.CharacterReplace XML comments on why we need to replace
                    // the last character
                    var entry = new OffsetChangeMapEntry(offset + length - 1, 1, 1 + text.TextLength - length);
                    Replace(offset, length, text, OffsetChangeMap.FromSingleElement(entry));
                }
                else if (text.TextLength < length)
                {
                    var entry = new OffsetChangeMapEntry(offset + text.TextLength, length - text.TextLength, 0, true, false);
                    Replace(offset, length, text, OffsetChangeMap.FromSingleElement(entry));
                }
                else
                {
                    Replace(offset, length, text, OffsetChangeMap.Empty);
                }
                break;

            default:
                throw new ArgumentOutOfRangeException("offsetChangeMappingType", offsetChangeMappingType, "Invalid enum value");
            }
        }