public void Update(ITextSourceVersion newVersion)
            {
                // Apply document changes to all highlighting sections:
                foreach (TextChangeEventArgs change in OldVersion.GetChangesTo(newVersion))
                {
                    foreach (HighlightedSection section in HighlightedLine.Sections)
                    {
                        int endOffset = section.Offset + section.Length;
                        section.Offset = change.GetNewOffset(section.Offset);
                        endOffset      = change.GetNewOffset(endOffset);
                        section.Length = endOffset - section.Offset;
                    }
                }
                // The resulting sections might have become invalid:
                // - zero-length if section was deleted,
                // - a section might have moved outside the range of this document line (newline inserted in document = line split up)
                // So we will remove all highlighting sections which have become invalid.
                int lineStart = HighlightedLine.DocumentLine.Offset;
                int lineEnd   = lineStart + HighlightedLine.DocumentLine.Length;

                for (int i = 0; i < HighlightedLine.Sections.Count; i++)
                {
                    HighlightedSection section = HighlightedLine.Sections[i];
                    if (section.Offset < lineStart || section.Offset + section.Length > lineEnd || section.Length <= 0)
                    {
                        HighlightedLine.Sections.RemoveAt(i--);
                    }
                }

                this.OldVersion = newVersion;
                this.IsValid    = false;
            }
 public void Apply(IDocument document)
 {
     using (document.OpenUndoGroup()) {
         var changes = oldVersion.GetChangesTo(newVersion);
         foreach (var change in changes)
         {
             document.Replace(change.Offset, change.RemovalLength, change.InsertedText);
         }
     }
 }
예제 #3
0
        internal List <UnchangedSegment> GetReuseMapTo(ITextSourceVersion newVersion)
        {
            ITextSourceVersion oldVersion = this.Version;

            if (oldVersion == null || newVersion == null)
            {
                return(null);
            }
            if (!oldVersion.BelongsToSameDocumentAs(newVersion))
            {
                return(null);
            }
            List <UnchangedSegment> reuseMap = new List <UnchangedSegment>();

            reuseMap.Add(new UnchangedSegment(0, 0, this.TextLength));
            foreach (var change in oldVersion.GetChangesTo(newVersion))
            {
                bool needsSegmentRemoval = false;
                for (int i = 0; i < reuseMap.Count; i++)
                {
                    UnchangedSegment segment = reuseMap[i];
                    if (segment.NewOffset + segment.Length <= change.Offset)
                    {
                        // change is completely after this segment
                        continue;
                    }
                    if (change.Offset + change.RemovalLength <= segment.NewOffset)
                    {
                        // change is completely before this segment
                        segment.NewOffset += change.InsertionLength - change.RemovalLength;
                        reuseMap[i]        = segment;
                        continue;
                    }
                    // Change is overlapping segment.
                    // Split segment into two parts: the part before change, and the part after change.
                    var segmentBefore = new UnchangedSegment(segment.OldOffset, segment.NewOffset, change.Offset - segment.NewOffset);
                    Debug.Assert(segmentBefore.Length < segment.Length);

                    int lengthAtEnd  = segment.NewOffset + segment.Length - (change.Offset + change.RemovalLength);
                    var segmentAfter = new UnchangedSegment(
                        segment.OldOffset + segment.Length - lengthAtEnd,
                        change.Offset + change.InsertionLength,
                        lengthAtEnd);
                    Debug.Assert(segmentAfter.Length < segment.Length);
                    Debug.Assert(segmentBefore.Length + segmentAfter.Length <= segment.Length);
                    Debug.Assert(segmentBefore.NewOffset + segmentBefore.Length <= segmentAfter.NewOffset);
                    Debug.Assert(segmentBefore.OldOffset + segmentBefore.Length <= segmentAfter.OldOffset);
                    if (segmentBefore.Length > 0 && segmentAfter.Length > 0)
                    {
                        reuseMap[i] = segmentBefore;
                        reuseMap.Insert(++i, segmentAfter);
                    }
                    else if (segmentBefore.Length > 0)
                    {
                        reuseMap[i] = segmentBefore;
                    }
                    else
                    {
                        reuseMap[i] = segmentAfter;
                        if (segmentAfter.Length <= 0)
                        {
                            needsSegmentRemoval = true;
                        }
                    }
                }
                if (needsSegmentRemoval)
                {
                    reuseMap.RemoveAll(s => s.Length <= 0);
                }
            }
            return(reuseMap);
        }