diff --git a/AvalonEdit/ICSharpCode.AvalonEdit.Tests/Document/CollapsingTests.cs b/AvalonEdit/ICSharpCode.AvalonEdit.Tests/Document/CollapsingTests.cs
index c8ae9d1d4..ddb2535e9 100644
--- a/AvalonEdit/ICSharpCode.AvalonEdit.Tests/Document/CollapsingTests.cs
+++ b/AvalonEdit/ICSharpCode.AvalonEdit.Tests/Document/CollapsingTests.cs
@@ -143,7 +143,8 @@ namespace ICSharpCode.AvalonEdit.Document
CheckHeights();
Assert.AreSame(null, sec1.Start);
Assert.AreSame(null, sec1.End);
- Assert.IsTrue(sec1.IsCollapsed);
+ // section gets uncollapsed when it is removed
+ Assert.IsFalse(sec1.IsCollapsed);
}
void CheckHeights()
diff --git a/AvalonEdit/ICSharpCode.AvalonEdit.Tests/ICSharpCode.AvalonEdit.Tests.csproj b/AvalonEdit/ICSharpCode.AvalonEdit.Tests/ICSharpCode.AvalonEdit.Tests.csproj
index ea99e5af4..0b0d6958e 100644
--- a/AvalonEdit/ICSharpCode.AvalonEdit.Tests/ICSharpCode.AvalonEdit.Tests.csproj
+++ b/AvalonEdit/ICSharpCode.AvalonEdit.Tests/ICSharpCode.AvalonEdit.Tests.csproj
@@ -85,6 +85,7 @@
+
@@ -104,4 +105,7 @@
ICSharpCode.AvalonEdit
+
+
+
\ No newline at end of file
diff --git a/AvalonEdit/ICSharpCode.AvalonEdit.Tests/Search/FindTests.cs b/AvalonEdit/ICSharpCode.AvalonEdit.Tests/Search/FindTests.cs
new file mode 100644
index 000000000..ffdde5533
--- /dev/null
+++ b/AvalonEdit/ICSharpCode.AvalonEdit.Tests/Search/FindTests.cs
@@ -0,0 +1,114 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+using System;
+using System.Linq;
+using ICSharpCode.AvalonEdit.Document;
+using NUnit.Framework;
+
+namespace ICSharpCode.AvalonEdit.Search
+{
+ [TestFixture]
+ public class FindTests
+ {
+ [Test]
+ public void SkipWordBorderSimple()
+ {
+ var strategy = SearchStrategyFactory.Create("All", false, true, SearchMode.Normal);
+ var text = new StringTextSource(" FindAllTests ");
+ var results = strategy.FindAll(text, 0, text.TextLength).ToArray();
+
+ Assert.IsEmpty(results, "No results should be found!");
+ }
+
+ [Test]
+ public void SkipWordBorder()
+ {
+ var strategy = SearchStrategyFactory.Create("AllTests", false, true, SearchMode.Normal);
+ var text = new StringTextSource("name=\"{FindAllTests}\"");
+ var results = strategy.FindAll(text, 0, text.TextLength).ToArray();
+
+ Assert.IsEmpty(results, "No results should be found!");
+ }
+
+ [Test]
+ public void SkipWordBorder2()
+ {
+ var strategy = SearchStrategyFactory.Create("AllTests", false, true, SearchMode.Normal);
+ var text = new StringTextSource("name=\"FindAllTests ");
+ var results = strategy.FindAll(text, 0, text.TextLength).ToArray();
+
+ Assert.IsEmpty(results, "No results should be found!");
+ }
+
+ [Test]
+ public void SkipWordBorder3()
+ {
+ var strategy = SearchStrategyFactory.Create("// find", false, true, SearchMode.Normal);
+ var text = new StringTextSource(" // findtest");
+ var results = strategy.FindAll(text, 0, text.TextLength).ToArray();
+
+ Assert.IsEmpty(results, "No results should be found!");
+ }
+
+ [Test]
+ public void WordBorderTest()
+ {
+ var strategy = SearchStrategyFactory.Create("// find", false, true, SearchMode.Normal);
+ var text = new StringTextSource(" // find me");
+ var results = strategy.FindAll(text, 0, text.TextLength).ToArray();
+
+ Assert.AreEqual(1, results.Length, "One result should be found!");
+ Assert.AreEqual(" ".Length, results[0].Offset);
+ Assert.AreEqual("// find".Length, results[0].Length);
+ }
+
+ [Test]
+ public void ResultAtStart()
+ {
+ var strategy = SearchStrategyFactory.Create("result", false, true, SearchMode.Normal);
+ var text = new StringTextSource("result // find me");
+ var results = strategy.FindAll(text, 0, text.TextLength).ToArray();
+
+ Assert.AreEqual(1, results.Length, "One result should be found!");
+ Assert.AreEqual(0, results[0].Offset);
+ Assert.AreEqual("result".Length, results[0].Length);
+ }
+
+ [Test]
+ public void ResultAtEnd()
+ {
+ var strategy = SearchStrategyFactory.Create("me", false, true, SearchMode.Normal);
+ var text = new StringTextSource("result // find me");
+ var results = strategy.FindAll(text, 0, text.TextLength).ToArray();
+
+ Assert.AreEqual(1, results.Length, "One result should be found!");
+ Assert.AreEqual("result // find ".Length, results[0].Offset);
+ Assert.AreEqual("me".Length, results[0].Length);
+ }
+
+ [Test]
+ public void TextWithDots()
+ {
+ var strategy = SearchStrategyFactory.Create("Text", false, true, SearchMode.Normal);
+ var text = new StringTextSource(".Text.");
+ var results = strategy.FindAll(text, 0, text.TextLength).ToArray();
+
+ Assert.AreEqual(1, results.Length, "One result should be found!");
+ Assert.AreEqual(".".Length, results[0].Offset);
+ Assert.AreEqual("Text".Length, results[0].Length);
+ }
+
+ [Test]
+ public void SimpleTest()
+ {
+ var strategy = SearchStrategyFactory.Create("AllTests", false, false, SearchMode.Normal);
+ var text = new StringTextSource("name=\"FindAllTests ");
+ var results = strategy.FindAll(text, 0, text.TextLength).ToArray();
+
+ Assert.AreEqual(1, results.Length, "One result should be found!");
+ Assert.AreEqual("name=\"Find".Length, results[0].Offset);
+ Assert.AreEqual("AllTests".Length, results[0].Length);
+ }
+ }
+}
diff --git a/AvalonEdit/ICSharpCode.AvalonEdit.Tests/WeakReferenceTests.cs b/AvalonEdit/ICSharpCode.AvalonEdit.Tests/WeakReferenceTests.cs
index 29ae3be83..2925945ce 100644
--- a/AvalonEdit/ICSharpCode.AvalonEdit.Tests/WeakReferenceTests.cs
+++ b/AvalonEdit/ICSharpCode.AvalonEdit.Tests/WeakReferenceTests.cs
@@ -2,6 +2,7 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
+using System.Windows.Threading;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Editing;
using ICSharpCode.AvalonEdit.Rendering;
@@ -45,7 +46,6 @@ namespace ICSharpCode.AvalonEdit
}
[Test]
- [Ignore]
public void DocumentDoesNotHoldReferenceToTextArea()
{
TextDocument textDocument = new TextDocument();
@@ -61,7 +61,6 @@ namespace ICSharpCode.AvalonEdit
}
[Test]
- [Ignore]
public void DocumentDoesNotHoldReferenceToTextEditor()
{
TextDocument textDocument = new TextDocument();
@@ -102,9 +101,12 @@ namespace ICSharpCode.AvalonEdit
static void GarbageCollect()
{
- GC.WaitForPendingFinalizers();
- GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
- GC.WaitForPendingFinalizers();
+ for (int i = 0; i < 3; i++) {
+ GC.WaitForPendingFinalizers();
+ GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
+ // pump WPF messages so that WeakEventManager can unregister
+ Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Background, new Action(delegate {}));
+ }
}
}
}
diff --git a/AvalonEdit/ICSharpCode.AvalonEdit/Editing/CaretNavigationCommandHandler.cs b/AvalonEdit/ICSharpCode.AvalonEdit/Editing/CaretNavigationCommandHandler.cs
index 4d995f5ee..036e57f59 100644
--- a/AvalonEdit/ICSharpCode.AvalonEdit/Editing/CaretNavigationCommandHandler.cs
+++ b/AvalonEdit/ICSharpCode.AvalonEdit/Editing/CaretNavigationCommandHandler.cs
@@ -73,6 +73,8 @@ namespace ICSharpCode.AvalonEdit.Editing
AddBinding(EditingCommands.SelectToDocumentEnd, Ctrl | Shift, Key.End, OnMoveCaretExtendSelection(CaretMovementType.DocumentEnd));
CommandBindings.Add(new CommandBinding(ApplicationCommands.SelectAll, OnSelectAll));
+
+ TextAreaDefaultInputHandler.WorkaroundWPFMemoryLeak(InputBindings);
}
static void OnSelectAll(object target, ExecutedRoutedEventArgs args)
diff --git a/AvalonEdit/ICSharpCode.AvalonEdit/Editing/EditingCommandHandler.cs b/AvalonEdit/ICSharpCode.AvalonEdit/Editing/EditingCommandHandler.cs
index 77d4d5f5b..239a32fdb 100644
--- a/AvalonEdit/ICSharpCode.AvalonEdit/Editing/EditingCommandHandler.cs
+++ b/AvalonEdit/ICSharpCode.AvalonEdit/Editing/EditingCommandHandler.cs
@@ -75,6 +75,8 @@ namespace ICSharpCode.AvalonEdit.Editing
CommandBindings.Add(new CommandBinding(AvalonEditCommands.ConvertLeadingTabsToSpaces, OnConvertLeadingTabsToSpaces));
CommandBindings.Add(new CommandBinding(AvalonEditCommands.ConvertLeadingSpacesToTabs, OnConvertLeadingSpacesToTabs));
CommandBindings.Add(new CommandBinding(AvalonEditCommands.IndentSelection, OnIndentSelection));
+
+ TextAreaDefaultInputHandler.WorkaroundWPFMemoryLeak(InputBindings);
}
static TextArea GetTextArea(object target)
diff --git a/AvalonEdit/ICSharpCode.AvalonEdit/Editing/TextArea.cs b/AvalonEdit/ICSharpCode.AvalonEdit/Editing/TextArea.cs
index 3f5b4448d..c74cebb68 100644
--- a/AvalonEdit/ICSharpCode.AvalonEdit/Editing/TextArea.cs
+++ b/AvalonEdit/ICSharpCode.AvalonEdit/Editing/TextArea.cs
@@ -806,11 +806,13 @@ namespace ICSharpCode.AvalonEdit.Editing
//Debug.WriteLine("TextInput: Text='" + e.Text + "' SystemText='" + e.SystemText + "' ControlText='" + e.ControlText + "'");
base.OnTextInput(e);
if (!e.Handled && this.Document != null) {
- if (string.IsNullOrEmpty(e.Text) || e.Text == "\x1b") {
+ if (string.IsNullOrEmpty(e.Text) || e.Text == "\x1b" || e.Text == "\b") {
// ASCII 0x1b = ESC.
// WPF produces a TextInput event with that old ASCII control char
// when Escape is pressed. We'll just ignore it.
+ // A deadkey followed by backspace causes a textinput event for the BS character.
+
// Similarly, some shortcuts like Alt+Space produce an empty TextInput event.
// We have to ignore those (not handle them) to keep the shortcut working.
return;
@@ -846,7 +848,7 @@ namespace ICSharpCode.AvalonEdit.Editing
throw ThrowUtil.NoDocumentAssigned();
OnTextEntering(e);
if (!e.Handled) {
- if (e.Text == "\n" || e.Text == "\r\n")
+ if (e.Text == "\n" || e.Text == "\r" || e.Text == "\r\n")
ReplaceSelectionWithNewLine();
else
ReplaceSelectionWithText(e.Text);
diff --git a/AvalonEdit/ICSharpCode.AvalonEdit/Editing/TextAreaDefaultInputHandlers.cs b/AvalonEdit/ICSharpCode.AvalonEdit/Editing/TextAreaDefaultInputHandlers.cs
index 2494fc676..24d817524 100644
--- a/AvalonEdit/ICSharpCode.AvalonEdit/Editing/TextAreaDefaultInputHandlers.cs
+++ b/AvalonEdit/ICSharpCode.AvalonEdit/Editing/TextAreaDefaultInputHandlers.cs
@@ -2,7 +2,7 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
-using System.Linq;
+using System.Collections.Generic;
using System.Windows;
using System.Windows.Input;
@@ -54,6 +54,16 @@ namespace ICSharpCode.AvalonEdit.Editing
return kb;
}
+ internal static void WorkaroundWPFMemoryLeak(List inputBindings)
+ {
+ // Work around WPF memory leak:
+ // KeyBinding retains a reference to whichever UIElement it is used in first.
+ // Using a dummy element for this purpose ensures that we don't leak
+ // a real text editor (which a potentially large document).
+ UIElement dummyElement = new UIElement();
+ dummyElement.InputBindings.AddRange(inputBindings);
+ }
+
#region Undo / Redo
UndoStack GetUndoStack()
{
diff --git a/AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingManager.cs b/AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingManager.cs
index 87ad45e8a..d20785728 100644
--- a/AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingManager.cs
+++ b/AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingManager.cs
@@ -68,13 +68,16 @@ namespace ICSharpCode.AvalonEdit.Folding
void OnDocumentChanged(DocumentChangeEventArgs e)
{
foldings.UpdateOffsets(e);
- FoldingSection s = foldings.FindFirstSegmentWithStartAfter(e.Offset);
- while (s != null && s.StartOffset == e.Offset) {
- FoldingSection next = foldings.GetNextSegment(s);
- if (s.Length == 0) {
- RemoveFolding(s);
+ int newEndOffset = e.Offset + e.InsertionLength;
+ // extend end offset to the end of the line (including delimiter)
+ var endLine = document.GetLineByOffset(newEndOffset);
+ newEndOffset = endLine.Offset + endLine.TotalLength;
+ foreach (var affectedFolding in foldings.FindOverlappingSegments(e.Offset, newEndOffset - e.Offset)) {
+ if (affectedFolding.Length == 0) {
+ RemoveFolding(affectedFolding);
+ } else {
+ affectedFolding.ValidateCollapsedLineSections();
}
- s = next;
}
}
#endregion
@@ -100,7 +103,7 @@ namespace ICSharpCode.AvalonEdit.Folding
throw new ArgumentException();
foreach (FoldingSection fs in foldings) {
if (fs.collapsedSections != null) {
- CollapsedLineSection[] c = new CollapsedLineSection[textViews.Count];
+ var c = new CollapsedLineSection[textViews.Count];
Array.Copy(fs.collapsedSections, 0, c, 0, pos);
Array.Copy(fs.collapsedSections, pos + 1, c, pos, c.Length - pos);
fs.collapsedSections = c;
@@ -108,15 +111,6 @@ namespace ICSharpCode.AvalonEdit.Folding
}
}
- internal CollapsedLineSection[] CollapseLines(DocumentLine start, DocumentLine end)
- {
- CollapsedLineSection[] c = new CollapsedLineSection[textViews.Count];
- for (int i = 0; i < c.Length; i++) {
- c[i] = textViews[i].CollapseLines(start, end);
- }
- return c;
- }
-
internal void Redraw()
{
foreach (TextView textView in textViews)
@@ -138,6 +132,8 @@ namespace ICSharpCode.AvalonEdit.Folding
{
if (startOffset >= endOffset)
throw new ArgumentException("startOffset must be less than endOffset");
+ if (startOffset < 0 || endOffset > document.TextLength)
+ throw new ArgumentException("Folding must be within document boundary");
FoldingSection fs = new FoldingSection(this, startOffset, endOffset);
foldings.Add(fs);
Redraw(fs);
@@ -254,6 +250,9 @@ namespace ICSharpCode.AvalonEdit.Folding
throw new ArgumentException("newFoldings must be sorted by start offset");
previousStartOffset = newFolding.StartOffset;
+ int startOffset = newFolding.StartOffset.CoerceValue(0, document.TextLength);
+ int endOffset = newFolding.EndOffset.CoerceValue(0, document.TextLength);
+
if (newFolding.StartOffset == newFolding.EndOffset)
continue; // ignore zero-length foldings
diff --git a/AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingSection.cs b/AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingSection.cs
index 7cf4364fe..0d16c9eb8 100644
--- a/AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingSection.cs
+++ b/AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingSection.cs
@@ -2,6 +2,7 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
+using System.Diagnostics;
using System.Text;
using System.Windows.Threading;
using ICSharpCode.AvalonEdit.Document;
@@ -28,15 +29,20 @@ namespace ICSharpCode.AvalonEdit.Folding
if (isFolded != value) {
isFolded = value;
if (value) {
+ // Create collapsed sections
if (manager != null) {
DocumentLine startLine = manager.document.GetLineByOffset(StartOffset);
DocumentLine endLine = manager.document.GetLineByOffset(EndOffset);
if (startLine != endLine) {
DocumentLine startLinePlusOne = startLine.NextLine;
- collapsedSections = manager.CollapseLines(startLinePlusOne, endLine);
+ collapsedSections = new CollapsedLineSection[manager.textViews.Count];
+ for (int i = 0; i < collapsedSections.Length; i++) {
+ collapsedSections[i] = manager.textViews[i].CollapseLines(startLinePlusOne, endLine);
+ }
}
}
} else {
+ // Destroy collapsed sections
RemoveCollapsedLineSection();
}
if (manager != null)
@@ -45,6 +51,9 @@ namespace ICSharpCode.AvalonEdit.Folding
}
}
+ ///
+ /// Creates new collapsed section when a text view is added to the folding manager.
+ ///
internal CollapsedLineSection CollapseSection(TextView textView)
{
DocumentLine startLine = manager.document.GetLineByOffset(StartOffset);
@@ -56,6 +65,34 @@ namespace ICSharpCode.AvalonEdit.Folding
return null;
}
+ internal void ValidateCollapsedLineSections()
+ {
+ if (!isFolded) {
+ RemoveCollapsedLineSection();
+ return;
+ }
+ DocumentLine startLine = manager.document.GetLineByOffset(StartOffset);
+ DocumentLine endLine = manager.document.GetLineByOffset(EndOffset);
+ if (startLine == endLine) {
+ RemoveCollapsedLineSection();
+ } else {
+ if (collapsedSections == null)
+ collapsedSections = new CollapsedLineSection[manager.textViews.Count];
+ // Validate collapsed line sections
+ DocumentLine startLinePlusOne = startLine.NextLine;
+ for (int i = 0; i < collapsedSections.Length; i++) {
+ var collapsedSection = collapsedSections[i];
+ if (collapsedSection == null || collapsedSection.Start != startLinePlusOne || collapsedSection.End != endLine) {
+ // recreate this collapsed section
+ Debug.WriteLine("CollapsedLineSection validation - recreate collapsed section from " + startLinePlusOne + " to " + endLine);
+ if (collapsedSection != null)
+ collapsedSection.Uncollapse();
+ collapsedSections[i] = manager.textViews[i].CollapseLines(startLinePlusOne, endLine);
+ }
+ }
+ }
+ }
+
///
/// Gets/Sets the text used to display the collapsed version of the folding section.
///
diff --git a/AvalonEdit/ICSharpCode.AvalonEdit/Folding/XmlFoldingStrategy.cs b/AvalonEdit/ICSharpCode.AvalonEdit/Folding/XmlFoldingStrategy.cs
index 2ade39284..5adaa2e30 100644
--- a/AvalonEdit/ICSharpCode.AvalonEdit/Folding/XmlFoldingStrategy.cs
+++ b/AvalonEdit/ICSharpCode.AvalonEdit/Folding/XmlFoldingStrategy.cs
@@ -110,7 +110,7 @@ namespace ICSharpCode.AvalonEdit.Folding
// into account the ");
foldMarkers.Add(new NewFolding(startOffset, endOffset) { Name = foldText } );
diff --git a/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj b/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj
index fb4088075..7dd5c6f12 100644
--- a/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj
+++ b/AvalonEdit/ICSharpCode.AvalonEdit/ICSharpCode.AvalonEdit.csproj
@@ -42,8 +42,9 @@
False
Auto
- 452984832
+ 4194304
AnyCPU
+ 4096
diff --git a/AvalonEdit/ICSharpCode.AvalonEdit/Properties/GlobalAssemblyInfo.cs b/AvalonEdit/ICSharpCode.AvalonEdit/Properties/GlobalAssemblyInfo.cs
index 28e1bfe57..3e81bb71a 100644
--- a/AvalonEdit/ICSharpCode.AvalonEdit/Properties/GlobalAssemblyInfo.cs
+++ b/AvalonEdit/ICSharpCode.AvalonEdit/Properties/GlobalAssemblyInfo.cs
@@ -18,7 +18,7 @@ using System.Reflection;
[assembly: AssemblyProduct("SharpDevelop")]
[assembly: AssemblyCopyright("2000-2012 AlphaSierraPapa for the SharpDevelop Team")]
[assembly: AssemblyVersion(RevisionClass.Major + "." + RevisionClass.Minor + "." + RevisionClass.Build + "." + RevisionClass.Revision)]
-[assembly: AssemblyInformationalVersion(RevisionClass.FullVersion + "-49ea0a14")]
+[assembly: AssemblyInformationalVersion(RevisionClass.FullVersion + "-ca8a8e28")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2243:AttributeStringLiteralsShouldParseCorrectly",
@@ -29,8 +29,8 @@ internal static class RevisionClass
public const string Major = "4";
public const string Minor = "2";
public const string Build = "0";
- public const string Revision = "8549";
- public const string VersionName = "beta";
+ public const string Revision = "8752";
+ public const string VersionName = "Beta 2";
- public const string FullVersion = Major + "." + Minor + "." + Build + ".8549-beta";
+ public const string FullVersion = Major + "." + Minor + "." + Build + ".8752-Beta 2";
}
diff --git a/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/CollapsedLineSection.cs b/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/CollapsedLineSection.cs
index 35e06f0e1..04dcbc1f9 100644
--- a/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/CollapsedLineSection.cs
+++ b/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/CollapsedLineSection.cs
@@ -11,9 +11,8 @@ namespace ICSharpCode.AvalonEdit.Rendering
/// Represents a collapsed line section.
/// Use the Uncollapse() method to uncollapse the section.
///
- public sealed class CollapsedLineSection : INotifyPropertyChanged
+ public sealed class CollapsedLineSection
{
- bool isCollapsed = true;
DocumentLine start, end;
HeightTree heightTree;
@@ -41,7 +40,7 @@ namespace ICSharpCode.AvalonEdit.Rendering
/// This property initially is true and turns to false when uncollapsing the section.
///
public bool IsCollapsed {
- get { return isCollapsed; }
+ get { return start != null; }
}
///
@@ -51,10 +50,7 @@ namespace ICSharpCode.AvalonEdit.Rendering
///
public DocumentLine Start {
get { return start; }
- internal set {
- start = value;
- // TODO: raised property changed event (but only after the operation is complete)
- }
+ internal set { start = value; }
}
///
@@ -64,46 +60,26 @@ namespace ICSharpCode.AvalonEdit.Rendering
///
public DocumentLine End {
get { return end; }
- internal set {
- end = value;
- // TODO: raised property changed event (but only after the operation is complete)
- }
+ internal set { end = value; }
}
///
/// Uncollapses the section.
/// This causes the Start and End properties to be set to null!
- /// Runtime: O(log(n))
+ /// Does nothing if the section is already uncollapsed.
///
- ///
- /// The section is already uncollapsed, or the text containing the section was deleted.
- ///
public void Uncollapse()
{
if (start == null)
- throw new InvalidOperationException();
+ return;
heightTree.Uncollapse(this);
#if DEBUG
heightTree.CheckProperties();
#endif
- start = end = null;
- isCollapsed = false;
- NotifyPropertyChanged("Start");
- NotifyPropertyChanged("End");
- NotifyPropertyChanged("IsCollapsed");
- }
-
- ///
- /// Is raised when of the properties Start,End,IsCollapsed changes.
- ///
- public event PropertyChangedEventHandler PropertyChanged;
-
- void NotifyPropertyChanged(string propertyName)
- {
- if (PropertyChanged != null)
- PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
+ start = null;
+ end = null;
}
///
@@ -113,7 +89,7 @@ namespace ICSharpCode.AvalonEdit.Rendering
public override string ToString()
{
return "[CollapsedSection" + ID + " Start=" + (start != null ? start.LineNumber.ToString() : "null")
- + " End=" + (end != null ? end.LineNumber.ToString() : "null") + " IsCollapsed=" + isCollapsed + "]";
+ + " End=" + (end != null ? end.LineNumber.ToString() : "null") + "]";
}
}
}
diff --git a/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs b/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs
index 920f9f895..e1ec32c7f 100644
--- a/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs
+++ b/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs
@@ -999,12 +999,18 @@ namespace ICSharpCode.AvalonEdit.Rendering
visualLine.ConstructVisualElements(textSource, elementGeneratorsArray);
- #if DEBUG
- for (int i = visualLine.FirstDocumentLine.LineNumber + 1; i <= visualLine.LastDocumentLine.LineNumber; i++) {
- if (!heightTree.GetIsCollapsed(i))
- throw new InvalidOperationException("Line " + i + " was skipped by a VisualLineElementGenerator, but it is not collapsed.");
+ if (visualLine.FirstDocumentLine != visualLine.LastDocumentLine) {
+ // Check whether the lines are collapsed correctly:
+ double firstLinePos = heightTree.GetVisualPosition(visualLine.FirstDocumentLine.NextLine);
+ double lastLinePos = heightTree.GetVisualPosition(visualLine.LastDocumentLine);
+ if (!firstLinePos.IsClose(lastLinePos)) {
+ for (int i = visualLine.FirstDocumentLine.LineNumber + 1; i <= visualLine.LastDocumentLine.LineNumber; i++) {
+ if (!heightTree.GetIsCollapsed(i))
+ throw new InvalidOperationException("Line " + i + " was skipped by a VisualLineElementGenerator, but it is not collapsed.");
+ }
+ throw new InvalidOperationException("All lines collapsed but visual pos different - height tree inconsistency?");
+ }
}
- #endif
visualLine.RunTransformers(textSource, lineTransformersArray);
diff --git a/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLine.cs b/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLine.cs
index db7e62747..8e2d67fdd 100644
--- a/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLine.cs
+++ b/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLine.cs
@@ -151,13 +151,13 @@ namespace ICSharpCode.AvalonEdit.Rendering
offset += element.DocumentLength;
if (offset > currentLineEnd) {
DocumentLine newEndLine = document.GetLineByOffset(offset);
- if (newEndLine == this.LastDocumentLine) {
+ currentLineEnd = newEndLine.Offset + newEndLine.Length;
+ this.LastDocumentLine = newEndLine;
+ if (currentLineEnd < offset) {
throw new InvalidOperationException(
"The VisualLineElementGenerator " + g.GetType().Name +
" produced an element which ends within the line delimiter");
}
- currentLineEnd = newEndLine.Offset + newEndLine.Length;
- this.LastDocumentLine = newEndLine;
}
break;
}
@@ -179,7 +179,7 @@ namespace ICSharpCode.AvalonEdit.Rendering
textOffset += element.DocumentLength;
}
VisualLength = visualOffset;
- Debug.Assert(textOffset == LastDocumentLine.Offset + LastDocumentLine.Length - FirstDocumentLine.Offset);
+ Debug.Assert(textOffset == LastDocumentLine.EndOffset - FirstDocumentLine.Offset);
}
internal void RunTransformers(ITextRunConstructionContext context, IVisualLineTransformer[] transformers)
diff --git a/AvalonEdit/ICSharpCode.AvalonEdit/Search/RegexSearchStrategy.cs b/AvalonEdit/ICSharpCode.AvalonEdit/Search/RegexSearchStrategy.cs
index a2535ac39..ad71b7ad2 100644
--- a/AvalonEdit/ICSharpCode.AvalonEdit/Search/RegexSearchStrategy.cs
+++ b/AvalonEdit/ICSharpCode.AvalonEdit/Search/RegexSearchStrategy.cs
@@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
+using System.Windows.Documents;
using ICSharpCode.AvalonEdit.Document;
@@ -14,23 +15,34 @@ namespace ICSharpCode.AvalonEdit.Search
class RegexSearchStrategy : ISearchStrategy
{
readonly Regex searchPattern;
+ readonly bool matchWholeWords;
- public RegexSearchStrategy(Regex searchPattern)
+ public RegexSearchStrategy(Regex searchPattern, bool matchWholeWords)
{
if (searchPattern == null)
throw new ArgumentNullException("searchPattern");
this.searchPattern = searchPattern;
+ this.matchWholeWords = matchWholeWords;
}
public IEnumerable FindAll(ITextSource document, int offset, int length)
{
int endOffset = offset + length;
foreach (Match result in searchPattern.Matches(document.Text)) {
- if (offset <= result.Index && endOffset >= (result.Length + result.Index))
- yield return new SearchResult { StartOffset = result.Index, Length = result.Length, Data = result };
+ int resultEndOffset = result.Length + result.Index;
+ if (offset > result.Index || endOffset < resultEndOffset)
+ continue;
+ if (matchWholeWords && (!IsWordBorder(document, result.Index) || !IsWordBorder(document, resultEndOffset)))
+ continue;
+ yield return new SearchResult { StartOffset = result.Index, Length = result.Length, Data = result };
}
}
+ static bool IsWordBorder(ITextSource document, int offset)
+ {
+ return TextUtilities.GetNextCaretPosition(document, offset - 1, LogicalDirection.Forward, CaretPositioningMode.WordBorder) == offset;
+ }
+
public ISearchResult FindNext(ITextSource document, int offset, int length)
{
return FindAll(document, offset, length).FirstOrDefault();
diff --git a/AvalonEdit/ICSharpCode.AvalonEdit/Search/SearchStrategyFactory.cs b/AvalonEdit/ICSharpCode.AvalonEdit/Search/SearchStrategyFactory.cs
index 25c4661a6..2156ba8e6 100644
--- a/AvalonEdit/ICSharpCode.AvalonEdit/Search/SearchStrategyFactory.cs
+++ b/AvalonEdit/ICSharpCode.AvalonEdit/Search/SearchStrategyFactory.cs
@@ -33,12 +33,9 @@ namespace ICSharpCode.AvalonEdit.Search
searchPattern = ConvertWildcardsToRegex(searchPattern);
break;
}
-
- if (matchWholeWords)
- searchPattern = "\\b" + searchPattern + "\\b";
try {
Regex pattern = new Regex(searchPattern, options);
- return new RegexSearchStrategy(pattern);
+ return new RegexSearchStrategy(pattern, matchWholeWords);
} catch (ArgumentException ex) {
throw new SearchPatternException(ex.Message, ex);
}
diff --git a/ILSpy/Properties/app.config.template b/ILSpy/Properties/app.config.template
index aa82408ee..bd6a5bc90 100644
--- a/ILSpy/Properties/app.config.template
+++ b/ILSpy/Properties/app.config.template
@@ -9,11 +9,11 @@
-
+
-
+
diff --git a/SharpTreeView/EditTextBox.cs b/SharpTreeView/EditTextBox.cs
index fd5fcd3a7..0b049fb5f 100644
--- a/SharpTreeView/EditTextBox.cs
+++ b/SharpTreeView/EditTextBox.cs
@@ -27,8 +27,7 @@ namespace ICSharpCode.TreeView
public SharpTreeViewItem Item { get; set; }
- public SharpTreeNode Node
- {
+ public SharpTreeNode Node {
get { return Item.Node; }
}
@@ -43,8 +42,7 @@ namespace ICSharpCode.TreeView
{
if (e.Key == Key.Enter) {
Commit();
- }
- else if (e.Key == Key.Escape) {
+ } else if (e.Key == Key.Escape) {
Node.IsEditing = false;
}
}
diff --git a/SharpTreeView/FlatListTreeNode.cs b/SharpTreeView/FlatListTreeNode.cs
index cf30a85e3..4f5a4d544 100644
--- a/SharpTreeView/FlatListTreeNode.cs
+++ b/SharpTreeView/FlatListTreeNode.cs
@@ -364,6 +364,8 @@ namespace ICSharpCode.TreeView
Debug.Assert(node.listParent == null);
Debug.Assert(node.left == null);
Debug.Assert(node.right == null);
+ node.height = 1;
+ node.totalListLength = -1;
if (balancingNode != null)
RebalanceUntilRoot(balancingNode);
}
diff --git a/SharpTreeView/Properties/GlobalAssemblyInfo.cs b/SharpTreeView/Properties/GlobalAssemblyInfo.cs
index f7639fad4..3e81bb71a 100644
--- a/SharpTreeView/Properties/GlobalAssemblyInfo.cs
+++ b/SharpTreeView/Properties/GlobalAssemblyInfo.cs
@@ -16,9 +16,9 @@ using System.Reflection;
[assembly: System.Runtime.InteropServices.ComVisible(false)]
[assembly: AssemblyCompany("ic#code")]
[assembly: AssemblyProduct("SharpDevelop")]
-[assembly: AssemblyCopyright("2000-2011 AlphaSierraPapa for the SharpDevelop Team")]
+[assembly: AssemblyCopyright("2000-2012 AlphaSierraPapa for the SharpDevelop Team")]
[assembly: AssemblyVersion(RevisionClass.Major + "." + RevisionClass.Minor + "." + RevisionClass.Build + "." + RevisionClass.Revision)]
-[assembly: AssemblyInformationalVersion(RevisionClass.FullVersion + "-d9a90d79")]
+[assembly: AssemblyInformationalVersion(RevisionClass.FullVersion + "-ca8a8e28")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2243:AttributeStringLiteralsShouldParseCorrectly",
@@ -27,10 +27,10 @@ using System.Reflection;
internal static class RevisionClass
{
public const string Major = "4";
- public const string Minor = "1";
+ public const string Minor = "2";
public const string Build = "0";
- public const string Revision = "7275";
- public const string VersionName = "alpha";
+ public const string Revision = "8752";
+ public const string VersionName = "Beta 2";
- public const string FullVersion = Major + "." + Minor + "." + Build + ".7275-alpha";
+ public const string FullVersion = Major + "." + Minor + "." + Build + ".8752-Beta 2";
}
diff --git a/SharpTreeView/SharpTreeNodeView.cs b/SharpTreeView/SharpTreeNodeView.cs
index 5ed2815e9..78481cf81 100644
--- a/SharpTreeView/SharpTreeNodeView.cs
+++ b/SharpTreeView/SharpTreeNodeView.cs
@@ -38,6 +38,15 @@ namespace ICSharpCode.TreeView
}
public SharpTreeViewItem ParentItem { get; private set; }
+
+ public static readonly DependencyProperty CellEditorProperty =
+ DependencyProperty.Register("CellEditor", typeof(Control), typeof(SharpTreeNodeView),
+ new FrameworkPropertyMetadata());
+
+ public Control CellEditor {
+ get { return (Control)GetValue(CellEditorProperty); }
+ set { SetValue(CellEditorProperty, value); }
+ }
public SharpTreeView ParentTreeView
{
@@ -104,7 +113,10 @@ namespace ICSharpCode.TreeView
{
var textEditorContainer = Template.FindName("textEditorContainer", this) as Border;
if (Node.IsEditing) {
- textEditorContainer.Child = new EditTextBox() { Item = ParentItem };
+ if (CellEditor == null)
+ textEditorContainer.Child = new EditTextBox() { Item = ParentItem };
+ else
+ textEditorContainer.Child = CellEditor;
}
else {
textEditorContainer.Child = null;
diff --git a/SharpTreeView/SharpTreeView.cs b/SharpTreeView/SharpTreeView.cs
index dc230faed..3addc9e03 100644
--- a/SharpTreeView/SharpTreeView.cs
+++ b/SharpTreeView/SharpTreeView.cs
@@ -176,6 +176,10 @@ namespace ICSharpCode.TreeView
base.PrepareContainerForItemOverride(element, item);
SharpTreeViewItem container = element as SharpTreeViewItem;
container.ParentTreeView = this;
+ // Make sure that the line renderer takes into account the new bound data
+ if (container.NodeView != null) {
+ container.NodeView.LinesRenderer.InvalidateVisual();
+ }
}
bool doNotScrollOnExpanding;