From 429f0229b59eacdfa8b482536568c59f9a5f7875 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 14 Aug 2011 16:49:43 +0200 Subject: [PATCH] fix some bugs in ChangeMarkerMargin --- .../Src/ChangeMarkerMargin.cs | 34 ++++++---------- .../Src/DefaultChangeWatcher.cs | 40 ++++++++++++------- .../AvalonEdit.AddIn/Src/LineChangeInfo.cs | 34 +++------------- .../Utils/CompressingTreeList.cs | 29 ++++++++++++++ 4 files changed, 74 insertions(+), 63 deletions(-) diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ChangeMarkerMargin.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ChangeMarkerMargin.cs index 7f2730df6a..55053aebd8 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ChangeMarkerMargin.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ChangeMarkerMargin.cs @@ -158,6 +158,17 @@ namespace ICSharpCode.AvalonEdit.AddIn } if (oldText != null) { + // TODO : deletions on line 0 cannot be displayed. + + LineChangeInfo currLineInfo = changeWatcher.GetChange(startLine); + + if (currLineInfo.Change == ChangeType.Deleted) { + var docLine = editor.Document.GetLineByNumber(startLine); + if (docLine.DelimiterLength == 0) + oldText = DocumentUtilitites.GetLineTerminator(changeWatcher.CurrentDocument, startLine); + oldText = editor.Document.GetText(docLine.Offset, docLine.TotalLength) + oldText; + } + DiffControl differ = new DiffControl(); differ.editor.SyntaxHighlighting = editor.SyntaxHighlighting; differ.editor.HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden; @@ -165,16 +176,6 @@ namespace ICSharpCode.AvalonEdit.AddIn differ.editor.Document.Text = oldText; differ.Background = Brushes.White; - // TODO : deletions on line 0 cannot be displayed. - - LineChangeInfo prevLineInfo = changeWatcher.GetChange(startLine - 1); - LineChangeInfo lineInfo = changeWatcher.GetChange(startLine); - - if (prevLineInfo.Change == ChangeType.Deleted) { - var docLine = editor.Document.GetLineByNumber(startLine - 1); - differ.editor.Document.Insert(0, editor.Document.GetText(docLine.Offset, docLine.TotalLength)); - } - if (oldText == string.Empty) { differ.editor.Visibility = Visibility.Collapsed; differ.copyButton.Visibility = Visibility.Collapsed; @@ -184,22 +185,13 @@ namespace ICSharpCode.AvalonEdit.AddIn var mainHighlighter = new DocumentHighlighter(baseDocument, differ.editor.SyntaxHighlighting.MainRuleSet); var popupHighlighter = differ.editor.TextArea.GetService(typeof(IHighlighter)) as DocumentHighlighter; - if (prevLineInfo.Change == ChangeType.Deleted) - popupHighlighter.InitialSpanStack = mainHighlighter.GetSpanStack(prevLineInfo.OldStartLineNumber); - else - popupHighlighter.InitialSpanStack = mainHighlighter.GetSpanStack(lineInfo.OldStartLineNumber); + popupHighlighter.InitialSpanStack = mainHighlighter.GetSpanStack(currLineInfo.OldStartLineNumber); } } differ.revertButton.Click += delegate { if (hasNewVersion) { - int delimiter = 0; - DocumentLine l = Document.GetLineByOffset(offset + length); - if (added) - delimiter = l.DelimiterLength; - if (length == 0) - oldText += DocumentUtilitites.GetLineTerminator(new AvalonEditDocumentAdapter(Document, null), l.LineNumber); - Document.Replace(offset, length + delimiter, oldText); + Document.Replace(offset, length, oldText); tooltip.IsOpen = false; } }; diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/DefaultChangeWatcher.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/DefaultChangeWatcher.cs index b46890e08d..1fcc51c072 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/DefaultChangeWatcher.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/DefaultChangeWatcher.cs @@ -81,7 +81,7 @@ namespace ICSharpCode.AvalonEdit.AddIn if (update) changeList.Transform(TransformLineChangeInfo); else - changeList.InsertRange(0, document.TotalNumberOfLines + 1, LineChangeInfo.Empty); + changeList.InsertRange(0, document.TotalNumberOfLines + 1, LineChangeInfo.EMPTY); } else { changeList.Clear(); @@ -92,25 +92,23 @@ namespace ICSharpCode.AvalonEdit.AddIn new DocumentSequence(document, hashes) ); - changeList.Add(LineChangeInfo.Empty); + changeList.Add(LineChangeInfo.EMPTY); int lastEndLine = 0; foreach (Edit edit in diff.GetEdits()) { int beginLine = edit.BeginB; int endLine = edit.EndB; - changeList.InsertRange(changeList.Count, beginLine - lastEndLine, LineChangeInfo.Empty); + changeList.InsertRange(changeList.Count, beginLine - lastEndLine, LineChangeInfo.EMPTY); - LineChangeInfo change = new LineChangeInfo(edit.EditType, edit.BeginA, edit.BeginB, edit.EndA, edit.EndB); if (endLine == beginLine) - changeList[changeList.Count - 1] = change; + changeList[changeList.Count - 1] = new LineChangeInfo(edit.EditType, edit.BeginA, edit.EndA); else - changeList.InsertRange(changeList.Count, endLine - beginLine, change); - + changeList.InsertRange(changeList.Count, endLine - beginLine, new LineChangeInfo(edit.EditType, edit.BeginA, edit.EndA)); lastEndLine = endLine; } - changeList.InsertRange(changeList.Count, textDocument.LineCount - lastEndLine, LineChangeInfo.Empty); + changeList.InsertRange(changeList.Count, textDocument.LineCount - lastEndLine, LineChangeInfo.EMPTY); } OnChangeOccurred(EventArgs.Empty); @@ -158,7 +156,7 @@ namespace ICSharpCode.AvalonEdit.AddIn void ILineTracker.LineInserted(DocumentLine insertionPos, DocumentLine newLine) { int index = insertionPos.LineNumber; - var newLineInfo = new LineChangeInfo(ChangeType.Unsaved, index, index, newLine.LineNumber, newLine.LineNumber); + var newLineInfo = new LineChangeInfo(ChangeType.Unsaved, index, index); changeList[index] = newLineInfo; changeList.Insert(index + 1, newLineInfo); @@ -167,7 +165,7 @@ namespace ICSharpCode.AvalonEdit.AddIn void ILineTracker.RebuildDocument() { changeList.Clear(); - changeList.InsertRange(0, document.TotalNumberOfLines + 1, new LineChangeInfo(ChangeType.Unsaved, 1, 1, baseDocument.TotalNumberOfLines, document.TotalNumberOfLines)); + changeList.InsertRange(0, document.TotalNumberOfLines + 1, new LineChangeInfo(ChangeType.Unsaved, 1, baseDocument.TotalNumberOfLines)); } bool disposed = false; @@ -188,7 +186,7 @@ namespace ICSharpCode.AvalonEdit.AddIn added = info.Change == ChangeType.Added; if (info.Change != ChangeType.None && info.Change != ChangeType.Unsaved) { - newStartLine = info.NewStartLineNumber + 1; + newStartLine = CalculateNewStartLineNumber(lineNumber); if (info.Change == ChangeType.Added) return ""; @@ -196,23 +194,37 @@ namespace ICSharpCode.AvalonEdit.AddIn var startDocumentLine = baseDocument.GetLine(info.OldStartLineNumber + 1); var endLine = baseDocument.GetLine(info.OldEndLineNumber); - return baseDocument.GetText(startDocumentLine.Offset, endLine.EndOffset - startDocumentLine.Offset); + return TextUtilities.NormalizeNewLines(baseDocument.GetText(startDocumentLine.Offset, endLine.EndOffset - startDocumentLine.Offset), DocumentUtilitites.GetLineTerminator(document, newStartLine)); } newStartLine = 0; return null; } + int CalculateNewStartLineNumber(int lineNumber) + { + return changeList.GetStartOfRun(lineNumber); + } + + int CalculateNewEndLineNumber(int lineNumber) + { + return changeList.GetEndOfRun(lineNumber) - 1; + } + public bool GetNewVersionFromLine(int lineNumber, out int offset, out int length) { LineChangeInfo info = changeList[lineNumber]; if (info.Change != ChangeType.None && info.Change != ChangeType.Unsaved) { - var startLine = document.GetLine(info.NewStartLineNumber + 1); - var endLine = document.GetLine(info.NewEndLineNumber); + var startLine = document.GetLine(CalculateNewStartLineNumber(lineNumber)); + var endLine = document.GetLine(CalculateNewEndLineNumber(lineNumber)); offset = startLine.Offset; length = endLine.EndOffset - startLine.Offset; + + if (info.Change == ChangeType.Added) + length += endLine.DelimiterLength; + return true; } diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/LineChangeInfo.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/LineChangeInfo.cs index 99551b6755..42e7d21ea0 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/LineChangeInfo.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/LineChangeInfo.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using ICSharpCode.AvalonEdit.Utils; using ICSharpCode.SharpDevelop.Editor; namespace ICSharpCode.AvalonEdit.AddIn @@ -34,7 +35,7 @@ namespace ICSharpCode.AvalonEdit.AddIn public struct LineChangeInfo : IEquatable { - public static readonly LineChangeInfo Empty = new LineChangeInfo(ChangeType.None, -1, -1, -1, -1); + public static readonly LineChangeInfo EMPTY = new LineChangeInfo(ChangeType.None, -1, -1); ChangeType change; @@ -47,37 +48,19 @@ namespace ICSharpCode.AvalonEdit.AddIn public int OldStartLineNumber { get { return oldStartLineNumber; } - set { oldStartLineNumber = value; } - } - - int newStartLineNumber; - - public int NewStartLineNumber { - get { return newStartLineNumber; } - set { newStartLineNumber = value; } } int oldEndLineNumber; public int OldEndLineNumber { get { return oldEndLineNumber; } - set { oldEndLineNumber = value; } } - int newEndLineNumber; - - public int NewEndLineNumber { - get { return newEndLineNumber; } - set { newEndLineNumber = value; } - } - - public LineChangeInfo(ChangeType change, int oldStartLineNumber, int newStartLineNumber, int oldEndLineNumber, int newEndLineNumber) + public LineChangeInfo(ChangeType change, int oldStartLineNumber, int oldEndLineNumber) { this.change = change; this.oldStartLineNumber = oldStartLineNumber; - this.newStartLineNumber = newStartLineNumber; this.oldEndLineNumber = oldEndLineNumber; - this.newEndLineNumber = newEndLineNumber; } #region Equals and GetHashCode implementation @@ -88,11 +71,7 @@ namespace ICSharpCode.AvalonEdit.AddIn public bool Equals(LineChangeInfo other) { - return this.change == other.change && - this.oldEndLineNumber == other.oldEndLineNumber && - this.newStartLineNumber == other.newStartLineNumber && - this.oldStartLineNumber == other.oldStartLineNumber && - this.newEndLineNumber == other.newEndLineNumber; + return this.change == other.change && this.oldStartLineNumber == other.oldStartLineNumber && this.oldEndLineNumber == other.oldEndLineNumber; } public override int GetHashCode() @@ -101,9 +80,7 @@ namespace ICSharpCode.AvalonEdit.AddIn unchecked { hashCode += 1000000007 * change.GetHashCode(); hashCode += 1000000009 * oldStartLineNumber.GetHashCode(); - hashCode += 1000000021 * newStartLineNumber.GetHashCode(); - hashCode += 1000000033 * oldEndLineNumber.GetHashCode(); - hashCode += 1000000087 * newEndLineNumber.GetHashCode(); + hashCode += 1000000021 * oldEndLineNumber.GetHashCode(); } return hashCode; } @@ -118,5 +95,6 @@ namespace ICSharpCode.AvalonEdit.AddIn return !(lhs == rhs); } #endregion + } } diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Utils/CompressingTreeList.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Utils/CompressingTreeList.cs index db23c5bb2c..fb984c13ad 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Utils/CompressingTreeList.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Utils/CompressingTreeList.cs @@ -343,9 +343,38 @@ namespace ICSharpCode.AvalonEdit.Utils return -1; } + /// + /// Gets the the first index so that all values from the result index to + /// are equal. + /// + public int GetStartOfRun(int index) + { + if (index < 0 || index >= this.Count) + throw new ArgumentOutOfRangeException("index", index, "Value must be between 0 and " + (this.Count - 1)); + int indexInRun = index; + GetNode(ref indexInRun); + return index - indexInRun; + } + + /// + /// Gets the first index after so that the value at the result index is not + /// equal to the value at . + /// That is, this method returns the exclusive end index of the run of equal values. + /// + public int GetEndOfRun(int index) + { + if (index < 0 || index >= this.Count) + throw new ArgumentOutOfRangeException("index", index, "Value must be between 0 and " + (this.Count - 1)); + int indexInRun = index; + int runLength = GetNode(ref indexInRun).count; + return index - indexInRun + runLength; + } + /// /// Gets the number of elements after that have the same value as each other. /// + [Obsolete("This method may be confusing as it returns only the remaining run length after index. " + + "Use GetStartOfRun/GetEndOfRun instead.")] public int GetRunLength(int index) { if (index < 0 || index >= this.Count)