diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/OffsetChangeMap.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/OffsetChangeMap.cs index 692b15e7b4..8612957a5b 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/OffsetChangeMap.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/OffsetChangeMap.cs @@ -108,7 +108,7 @@ namespace ICSharpCode.AvalonEdit.Document /// /// Gets the new offset where the specified offset moves after this document change. /// - public int GetNewOffset(int offset, AnchorMovementType movementType) + public int GetNewOffset(int offset, AnchorMovementType movementType = AnchorMovementType.Default) { IList items = this.Items; int count = items.Count; diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/RichText.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/RichText.cs index 46fd4c9902..597bfe5015 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/RichText.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/RichText.cs @@ -3,10 +3,12 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Windows.Documents; +using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Utils; namespace ICSharpCode.AvalonEdit.Highlighting @@ -16,6 +18,11 @@ namespace ICSharpCode.AvalonEdit.Highlighting /// public class RichText { + /// + /// The empty string without any formatting information. + /// + public static readonly RichText Empty = new RichText(string.Empty); + readonly string text; internal readonly int[] stateChangeOffsets; internal readonly HighlightingColor[] stateChanges; @@ -53,6 +60,8 @@ namespace ICSharpCode.AvalonEdit.Highlighting internal RichText(string text, int[] offsets, HighlightingColor[] states) { this.text = text; + Debug.Assert(offsets[0] == 0); + Debug.Assert(offsets.Last() <= text.Length); this.stateChangeOffsets = offsets; this.stateChanges = states; } @@ -191,9 +200,15 @@ namespace ICSharpCode.AvalonEdit.Highlighting /// public RichText Substring(int offset, int length) { -// if (offset == 0 && length == this.Length) -// return this; - throw new NotImplementedException(); + if (offset == 0 && length == this.Length) + return this; + string newText = text.Substring(offset, length); + RichTextModel model = ToRichTextModel(); + OffsetChangeMap map = new OffsetChangeMap(2); + map.Add(new OffsetChangeMapEntry(offset + length, text.Length - offset - length, 0)); + map.Add(new OffsetChangeMapEntry(0, offset, 0)); + model.UpdateOffsets(map); + return new RichText(newText, model); } /// @@ -201,7 +216,18 @@ namespace ICSharpCode.AvalonEdit.Highlighting /// public static RichText Concat(params RichText[] texts) { - throw new NotImplementedException(); + if (texts == null || texts.Length == 0) + return Empty; + else if (texts.Length == 1) + return texts[0]; + string newText = string.Concat(texts.Select(txt => txt.text)); + RichTextModel model = texts[0].ToRichTextModel(); + int offset = texts[0].Length; + for (int i = 1; i < texts.Length; i++) { + model.Append(offset, texts[i].stateChangeOffsets, texts[i].stateChanges); + offset += texts[i].Length; + } + return new RichText(newText, model); } /// diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/RichTextModel.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/RichTextModel.cs index ca1f588612..7a5f604a27 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/RichTextModel.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Highlighting/RichTextModel.cs @@ -4,6 +4,8 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; using System.Windows; using System.Windows.Media; using ICSharpCode.NRefactory.Editor; @@ -72,6 +74,7 @@ namespace ICSharpCode.AvalonEdit.Highlighting /// internal RichTextModel(int[] stateChangeOffsets, HighlightingColor[] stateChanges) { + Debug.Assert(stateChangeOffsets[0] == 0); this.stateChangeOffsets.AddRange(stateChangeOffsets); this.stateChanges.AddRange(stateChanges); } @@ -85,9 +88,18 @@ namespace ICSharpCode.AvalonEdit.Highlighting { if (e == null) throw new ArgumentNullException("e"); - for (int i = 0; i < stateChangeOffsets.Count; i++) { - stateChangeOffsets[i] = e.GetNewOffset(stateChangeOffsets[i]); - } + UpdateOffsets(e.GetNewOffset); + } + + /// + /// Updates the start and end offsets of all segments stored in this collection. + /// + /// OffsetChangeMap instance describing the change to the document. + public void UpdateOffsets(OffsetChangeMap change) + { + if (change == null) + throw new ArgumentNullException("change"); + UpdateOffsets(change.GetNewOffset); } /// @@ -96,12 +108,52 @@ namespace ICSharpCode.AvalonEdit.Highlighting /// OffsetChangeMapEntry instance describing the change to the document. public void UpdateOffsets(OffsetChangeMapEntry change) { - for (int i = 0; i < stateChangeOffsets.Count; i++) { - stateChangeOffsets[i] = change.GetNewOffset(stateChangeOffsets[i]); + UpdateOffsets(change.GetNewOffset); + } + + void UpdateOffsets(Func updateOffset) + { + int readPos = 1; + int writePos = 1; + while (readPos < stateChangeOffsets.Count) { + Debug.Assert(writePos <= readPos); + int newOffset = updateOffset(stateChangeOffsets[readPos], AnchorMovementType.Default); + if (newOffset == stateChangeOffsets[writePos - 1]) { + // offset moved to same position as previous offset + // -> previous segment has length 0 and gets overwritten with this segment + stateChanges[writePos - 1] = stateChanges[readPos]; + } else { + stateChangeOffsets[writePos] = newOffset; + stateChanges[writePos] = stateChanges[readPos]; + writePos++; + } + readPos++; } + // Delete all entries that were not written to + stateChangeOffsets.RemoveRange(writePos, stateChangeOffsets.Count - writePos); + stateChanges.RemoveRange(writePos, stateChanges.Count - writePos); } #endregion + /// + /// Appends another RichTextModel after this one. + /// + internal void Append(int offset, int[] newOffsets, HighlightingColor[] newColors) + { + Debug.Assert(newOffsets.Length == newColors.Length); + Debug.Assert(newOffsets[0] == 0); + // remove everything before offset: + while (stateChangeOffsets.Count > 0 && stateChangeOffsets.Last() <= offset) { + stateChangeOffsets.RemoveAt(stateChangeOffsets.Count - 1); + stateChanges.RemoveAt(stateChanges.Count - 1); + } + // Append the new segments + for (int i = 0; i < newOffsets.Length; i++) { + stateChangeOffsets.Add(offset + newOffsets[i]); + stateChanges.Add(newColors[i]); + } + } + /// /// Gets a copy of the HighlightingColor for the specified offset. /// diff --git a/src/Main/Base/Project/Src/Gui/Pads/CompilerMessageView/CompilerMessageView.cs b/src/Main/Base/Project/Src/Gui/Pads/CompilerMessageView/CompilerMessageView.cs index 1591db7faf..e9edf212db 100644 --- a/src/Main/Base/Project/Src/Gui/Pads/CompilerMessageView/CompilerMessageView.cs +++ b/src/Main/Base/Project/Src/Gui/Pads/CompilerMessageView/CompilerMessageView.cs @@ -50,7 +50,9 @@ namespace ICSharpCode.SharpDevelop.Gui return this.SelectedMessageViewCategory; } set { - throw new NotImplementedException(); + int index = messageCategories.IndexOf(value as MessageViewCategory); + if (index >= 0) + SelectedCategoryIndex = index; } }