diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/DocumentAccessor.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/DocumentAccessor.cs
index 58fe0a1f41..6204559784 100644
--- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/DocumentAccessor.cs
+++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/DocumentAccessor.cs
@@ -99,7 +99,7 @@ namespace CSharpBinding.FormattingStrategy
public bool Next()
{
if (lineDirty) {
- doc.Replace(line.Offset, line.Length, text);
+ DefaultFormattingStrategy.SmartReplaceLine(doc, line, text);
lineDirty = false;
++changedLines;
}
diff --git a/src/AddIns/Misc/SearchAndReplace/Project/Engine/SearchReplaceManager.cs b/src/AddIns/Misc/SearchAndReplace/Project/Engine/SearchReplaceManager.cs
index 0a829c32cd..daf014d8e6 100644
--- a/src/AddIns/Misc/SearchAndReplace/Project/Engine/SearchReplaceManager.cs
+++ b/src/AddIns/Misc/SearchAndReplace/Project/Engine/SearchReplaceManager.cs
@@ -156,10 +156,11 @@ namespace SearchAndReplace
textAreas.Add(textArea);
}
textArea.ActiveTextAreaControl.Caret.Position = textArea.Document.OffsetToPosition(result.Offset);
- int lineNr = textArea.Document.GetLineNumberForOffset(result.Offset);
+ LineSegment segment = textArea.Document.GetLineSegmentForOffset(result.Offset);
+ int lineNr = segment.LineNumber;
if (!textArea.Document.BookmarkManager.IsMarked(lineNr)) {
- textArea.Document.BookmarkManager.ToggleMarkAt(lineNr);
+ textArea.Document.BookmarkManager.ToggleMarkAt(new TextLocation(result.Offset - segment.Offset, lineNr));
}
}
}
diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/ICSharpCode.TextEditor.csproj b/src/Libraries/ICSharpCode.TextEditor/Project/ICSharpCode.TextEditor.csproj
index 345f9f3d86..6234fa2bd0 100644
--- a/src/Libraries/ICSharpCode.TextEditor/Project/ICSharpCode.TextEditor.csproj
+++ b/src/Libraries/ICSharpCode.TextEditor/Project/ICSharpCode.TextEditor.csproj
@@ -59,6 +59,7 @@
+
diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Actions/BookmarkActions.cs b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Actions/BookmarkActions.cs
index f01faf6094..bc4f8d5e49 100644
--- a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Actions/BookmarkActions.cs
+++ b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Actions/BookmarkActions.cs
@@ -14,7 +14,7 @@ namespace ICSharpCode.TextEditor.Actions
{
public override void Execute(TextArea textArea)
{
- textArea.Document.BookmarkManager.ToggleMarkAt(textArea.Caret.Line);
+ textArea.Document.BookmarkManager.ToggleMarkAt(textArea.Caret.Position);
textArea.Document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.SingleLine, textArea.Caret.Line));
textArea.Document.CommitUpdate();
@@ -34,8 +34,9 @@ namespace ICSharpCode.TextEditor.Actions
{
Bookmark mark = textArea.Document.BookmarkManager.GetPrevMark(textArea.Caret.Line, predicate);
if (mark != null) {
- textArea.Caret.Line = mark.LineNumber;
+ textArea.Caret.Position = mark.Location;
textArea.SelectionManager.ClearSelection();
+ textArea.SetDesiredColumn();
}
}
}
@@ -53,8 +54,9 @@ namespace ICSharpCode.TextEditor.Actions
{
Bookmark mark = textArea.Document.BookmarkManager.GetNextMark(textArea.Caret.Line, predicate);
if (mark != null) {
- textArea.Caret.Line = mark.LineNumber;
+ textArea.Caret.Position = mark.Location;
textArea.SelectionManager.ClearSelection();
+ textArea.SetDesiredColumn();
}
}
}
diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/BookmarkManager/Bookmark.cs b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/BookmarkManager/Bookmark.cs
index 17aba3eeda..ed5e251d58 100644
--- a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/BookmarkManager/Bookmark.cs
+++ b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/BookmarkManager/Bookmark.cs
@@ -17,8 +17,8 @@ namespace ICSharpCode.TextEditor.Document
public class Bookmark
{
IDocument document;
- LineSegment line;
- int lineNumber;
+ TextAnchor anchor;
+ TextLocation location;
bool isEnabled = true;
public IDocument Document {
@@ -27,19 +27,54 @@ namespace ICSharpCode.TextEditor.Document
}
set {
if (document != value) {
- if (line != null) {
- lineNumber = line.LineNumber;
- line = null;
+ if (anchor != null) {
+ location = anchor.Location;
+ anchor = null;
}
document = value;
- if (document != null) {
- line = document.GetLineSegment(Math.Min(lineNumber, document.TotalNumberOfLines-1));
- }
+ CreateAnchor();
OnDocumentChanged(EventArgs.Empty);
}
}
}
+ void CreateAnchor()
+ {
+ if (document != null) {
+ LineSegment line = document.GetLineSegment(Math.Max(0, Math.Min(location.Line, document.TotalNumberOfLines-1)));
+ anchor = line.CreateAnchor(Math.Max(0, Math.Min(location.Column, line.Length)));
+ // after insertion: keep bookmarks after the initial whitespace (see DefaultFormattingStrategy.SmartReplaceLine)
+ anchor.MovementType = AnchorMovementType.AfterInsertion;
+ anchor.Deleted += AnchorDeleted;
+ }
+ }
+
+ void AnchorDeleted(object sender, EventArgs e)
+ {
+ document.BookmarkManager.RemoveMark(this);
+ }
+
+ ///
+ /// Gets the TextAnchor used for this bookmark.
+ /// Is null if the bookmark is not connected to a document.
+ ///
+ public TextAnchor Anchor {
+ get { return anchor; }
+ }
+
+ public TextLocation Location {
+ get {
+ if (anchor != null)
+ return anchor.Location;
+ else
+ return location;
+ }
+ set {
+ location = value;
+ CreateAnchor();
+ }
+ }
+
public event EventHandler DocumentChanged;
protected virtual void OnDocumentChanged(EventArgs e)
@@ -57,7 +92,7 @@ namespace ICSharpCode.TextEditor.Document
if (isEnabled != value) {
isEnabled = value;
if (document != null) {
- document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.SingleLine, lineNumber));
+ document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.SingleLine, LineNumber));
document.CommitUpdate();
}
OnIsEnabledChanged(EventArgs.Empty);
@@ -74,29 +109,21 @@ namespace ICSharpCode.TextEditor.Document
}
}
- ///
- /// Gets the line the bookmark belongs to.
- /// Is null if the bookmark is not connected to a document.
- ///
- public LineSegment Line {
- get { return line; }
- }
-
public int LineNumber {
get {
- if (line != null)
- return line.LineNumber;
+ if (anchor != null)
+ return anchor.LineNumber;
else
- return lineNumber;
+ return location.Line;
}
- set {
- if (value < 0)
- throw new ArgumentOutOfRangeException("value", value, "line number must be >= 0");
- if (document == null) {
- lineNumber = value;
- } else {
- line = document.GetLineSegment(value);
- }
+ }
+
+ public int ColumnNumber {
+ get {
+ if (anchor != null)
+ return anchor.ColumnNumber;
+ else
+ return location.Column;
}
}
@@ -109,15 +136,15 @@ namespace ICSharpCode.TextEditor.Document
}
}
- public Bookmark(IDocument document, int lineNumber) : this(document, lineNumber, true)
+ public Bookmark(IDocument document, TextLocation location) : this(document, location, true)
{
}
- public Bookmark(IDocument document, int lineNumber, bool isEnabled)
+ public Bookmark(IDocument document, TextLocation location, bool isEnabled)
{
- this.document = document;
- this.isEnabled = isEnabled;
- this.LineNumber = lineNumber;
+ this.document = document;
+ this.isEnabled = isEnabled;
+ this.Location = location;
}
public virtual bool Click(SWF.Control parent, SWF.MouseEventArgs e)
diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/BookmarkManager/BookmarkManager.cs b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/BookmarkManager/BookmarkManager.cs
index 8ffa35f14e..7105065671 100644
--- a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/BookmarkManager/BookmarkManager.cs
+++ b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/BookmarkManager/BookmarkManager.cs
@@ -14,7 +14,7 @@ namespace ICSharpCode.TextEditor.Document
{
public interface IBookmarkFactory
{
- Bookmark CreateBookmark(IDocument document, int lineNumber);
+ Bookmark CreateBookmark(IDocument document, TextLocation location);
}
///
@@ -50,46 +50,32 @@ namespace ICSharpCode.TextEditor.Document
internal BookmarkManager(IDocument document, LineManager lineTracker)
{
this.document = document;
- lineTracker.LineDeleted += delegate(object sender, LineEventArgs e) {
- for (int i = 0; i < bookmark.Count; i++) {
- Bookmark b = bookmark[i];
- if (b.Line == e.LineSegment) {
- bookmark.RemoveAt(i--);
- OnRemoved(new BookmarkEventArgs(b));
- }
- }
- };
}
- IBookmarkFactory factory;
-
- public IBookmarkFactory Factory {
- get {
- return factory;
- }
- set {
- factory = value;
- }
- }
+ ///
+ /// Gets/Sets the bookmark factory used to create bookmarks for "ToggleMarkAt".
+ ///
+ public IBookmarkFactory Factory { get; set;}
///
- /// Sets the mark at the line lineNr
if it is not set, if the
+ /// Sets the mark at the line location.Line
if it is not set, if the
/// line is already marked the mark is cleared.
///
- public void ToggleMarkAt(int lineNr)
+ public void ToggleMarkAt(TextLocation location)
{
Bookmark newMark;
- if (factory != null)
- newMark = factory.CreateBookmark(document, lineNr);
- else
- newMark = new Bookmark(document, lineNr);
+ if (Factory != null) {
+ newMark = Factory.CreateBookmark(document, location);
+ } else {
+ newMark = new Bookmark(document, location);
+ }
Type newMarkType = newMark.GetType();
for (int i = 0; i < bookmark.Count; ++i) {
Bookmark mark = bookmark[i];
- if (mark.LineNumber == lineNr && mark.CanToggle && mark.GetType() == newMarkType) {
+ if (mark.LineNumber == location.Line && mark.CanToggle && mark.GetType() == newMarkType) {
bookmark.RemoveAt(i);
OnRemoved(new BookmarkEventArgs(mark));
return;
diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/FormattingStrategy/DefaultFormattingStrategy.cs b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/FormattingStrategy/DefaultFormattingStrategy.cs
index 0147e407bb..7408e296f5 100644
--- a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/FormattingStrategy/DefaultFormattingStrategy.cs
+++ b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/FormattingStrategy/DefaultFormattingStrategy.cs
@@ -55,11 +55,57 @@ namespace ICSharpCode.TextEditor.Document
if(indentation.Length > 0) {
string newLineText = indentation + TextUtilities.GetLineAsString(textArea.Document, lineNumber).Trim();
LineSegment oldLine = textArea.Document.GetLineSegment(lineNumber);
- textArea.Document.Replace(oldLine.Offset, oldLine.Length, newLineText);
+ SmartReplaceLine(textArea.Document, oldLine, newLineText);
}
return indentation.Length;
}
+ static readonly char[] whitespaceChars = {' ', '\t'};
+
+ ///
+ /// Replaces the text in a line.
+ /// If only whitespace at the beginning and end of the line was changed, this method
+ /// only adjusts the whitespace and doesn't replace the other text.
+ ///
+ public static void SmartReplaceLine(IDocument document, LineSegment line, string newLineText)
+ {
+ if (document == null)
+ throw new ArgumentNullException("document");
+ if (line == null)
+ throw new ArgumentNullException("line");
+ if (newLineText == null)
+ throw new ArgumentNullException("newLineText");
+ string newLineTextTrim = newLineText.Trim(whitespaceChars);
+ string oldLineText = document.GetText(line);
+ if (oldLineText == newLineText)
+ return;
+ int pos = oldLineText.IndexOf(newLineTextTrim);
+ if (newLineTextTrim.Length > 0 && pos >= 0) {
+ document.UndoStack.StartUndoGroup();
+ try {
+ // find whitespace at beginning
+ int startWhitespaceLength = 0;
+ while (startWhitespaceLength < newLineText.Length) {
+ char c = newLineText[startWhitespaceLength];
+ if (c != ' ' && c != '\t')
+ break;
+ startWhitespaceLength++;
+ }
+ // find whitespace at end
+ int endWhitespaceLength = newLineText.Length - newLineTextTrim.Length - startWhitespaceLength;
+
+ // replace whitespace sections
+ int lineOffset = line.Offset;
+ document.Replace(lineOffset + pos + newLineTextTrim.Length, line.Length - pos - newLineTextTrim.Length, newLineText.Substring(newLineText.Length - endWhitespaceLength));
+ document.Replace(lineOffset, pos, newLineText.Substring(0, startWhitespaceLength));
+ } finally {
+ document.UndoStack.EndUndoGroup();
+ }
+ } else {
+ document.Replace(line.Offset, line.Length, newLineText);
+ }
+ }
+
///
/// Could be overwritten to define more complex indenting.
///
diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/LineManager/DeferredEventList.cs b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/LineManager/DeferredEventList.cs
new file mode 100644
index 0000000000..0ab08f1322
--- /dev/null
+++ b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/LineManager/DeferredEventList.cs
@@ -0,0 +1,44 @@
+//
+//
+//
+//
+// $Revision$
+//
+using System;
+using System.Collections.Generic;
+
+namespace ICSharpCode.TextEditor.Document
+{
+ ///
+ /// A list of events that are fired after the line manager has finished working.
+ ///
+ struct DeferredEventList
+ {
+ internal List removedLines;
+ internal List textAnchor;
+
+ public void AddRemovedLine(LineSegment line)
+ {
+ if (removedLines == null)
+ removedLines = new List();
+ removedLines.Add(line);
+ }
+
+ public void AddDeletedAnchor(TextAnchor anchor)
+ {
+ if (textAnchor == null)
+ textAnchor = new List();
+ textAnchor.Add(anchor);
+ }
+
+ public void RaiseEvents()
+ {
+ // removedLines is raised by the LineManager
+ if (textAnchor != null) {
+ foreach (TextAnchor a in textAnchor) {
+ a.RaiseDeleted();
+ }
+ }
+ }
+ }
+}
diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/LineManager/LineManager.cs b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/LineManager/LineManager.cs
index f114b304de..d00f136b08 100644
--- a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/LineManager/LineManager.cs
+++ b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/LineManager/LineManager.cs
@@ -77,10 +77,11 @@ namespace ICSharpCode.TextEditor.Document
public void Replace(int offset, int length, string text)
{
-// Console.WriteLine("Replace offset="+offset+" length="+length+" text.Length="+text.Length);
+ Debug.WriteLine("Replace offset="+offset+" length="+length+" text.Length="+text.Length);
int lineStart = GetLineNumberForOffset(offset);
int oldNumberOfLines = this.TotalNumberOfLines;
- List removedLines = RemoveInternal(offset, length);
+ DeferredEventList deferredEventList = new DeferredEventList();
+ RemoveInternal(ref deferredEventList, offset, length);
int numberOfLinesAfterRemoving = this.TotalNumberOfLines;
if (!string.IsNullOrEmpty(text)) {
InsertInternal(offset, text);
@@ -94,33 +95,34 @@ namespace ICSharpCode.TextEditor.Document
// Only fire events after RemoveInternal+InsertInternal finished completely:
// Otherwise we would expose inconsistent state to the event handlers.
RunHighlighter(lineStart, 1 + Math.Max(0, this.TotalNumberOfLines - numberOfLinesAfterRemoving));
- if (removedLines != null) {
- foreach (LineSegment ls in removedLines)
+ if (deferredEventList.removedLines != null) {
+ foreach (LineSegment ls in deferredEventList.removedLines)
OnLineDeleted(new LineEventArgs(document, ls));
}
if (this.TotalNumberOfLines != oldNumberOfLines) {
OnLineCountChanged(new LineCountChangeEventArgs(document, lineStart, this.TotalNumberOfLines - oldNumberOfLines));
}
+ deferredEventList.RaiseEvents();
}
- List RemoveInternal(int offset, int length)
+ void RemoveInternal(ref DeferredEventList deferredEventList, int offset, int length)
{
Debug.Assert(length >= 0);
- if (length == 0) return null;
+ if (length == 0) return;
LineSegmentTree.Enumerator it = lineCollection.GetEnumeratorForOffset(offset);
LineSegment startSegment = it.Current;
int startSegmentOffset = startSegment.Offset;
if (offset + length < startSegmentOffset + startSegment.TotalLength) {
// just removing a part of this line segment
- startSegment.RemovedLinePart(offset - startSegmentOffset, length);
+ startSegment.RemovedLinePart(ref deferredEventList, offset - startSegmentOffset, length);
SetSegmentLength(startSegment, startSegment.TotalLength - length);
- return null;
+ return;
}
// merge startSegment with another line segment because startSegment's delimiter was deleted
// possibly remove lines in between if multiple delimiters were deleted
int charactersRemovedInStartLine = startSegmentOffset + startSegment.TotalLength - offset;
Debug.Assert(charactersRemovedInStartLine > 0);
- startSegment.RemovedLinePart(offset - startSegmentOffset, charactersRemovedInStartLine);
+ startSegment.RemovedLinePart(ref deferredEventList, offset - startSegmentOffset, charactersRemovedInStartLine);
LineSegment endSegment = lineCollection.GetByOffset(offset + length);
@@ -128,26 +130,23 @@ namespace ICSharpCode.TextEditor.Document
// special case: we are removing a part of the last line up to the
// end of the document
SetSegmentLength(startSegment, startSegment.TotalLength - length);
- return null;
+ return;
}
int endSegmentOffset = endSegment.Offset;
int charactersLeftInEndLine = endSegmentOffset + endSegment.TotalLength - (offset + length);
- endSegment.RemovedLinePart(0, endSegment.TotalLength - charactersLeftInEndLine);
+ endSegment.RemovedLinePart(ref deferredEventList, 0, endSegment.TotalLength - charactersLeftInEndLine);
startSegment.MergedWith(endSegment, offset - startSegmentOffset);
SetSegmentLength(startSegment, startSegment.TotalLength - charactersRemovedInStartLine + charactersLeftInEndLine);
startSegment.DelimiterLength = endSegment.DelimiterLength;
// remove all segments between startSegment (excl.) and endSegment (incl.)
it.MoveNext();
- List removedLines = new List();
LineSegment segmentToRemove;
do {
segmentToRemove = it.Current;
it.MoveNext();
lineCollection.RemoveSegment(segmentToRemove);
- removedLines.Add(segmentToRemove);
- segmentToRemove.Deleted();
+ segmentToRemove.Deleted(ref deferredEventList);
} while (segmentToRemove != endSegment);
- return removedLines;
}
void InsertInternal(int offset, string text)
diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/LineManager/LineSegment.cs b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/LineManager/LineSegment.cs
index 554df72aea..2370e74dee 100644
--- a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/LineManager/LineSegment.cs
+++ b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/LineManager/LineSegment.cs
@@ -117,6 +117,8 @@ namespace ICSharpCode.TextEditor.Document
public TextAnchor CreateAnchor(int column)
{
+ if (column < 0 || column > Length)
+ throw new ArgumentOutOfRangeException("column");
TextAnchor anchor = new TextAnchor(this, column);
AddAnchor(anchor);
return anchor;
@@ -135,13 +137,13 @@ namespace ICSharpCode.TextEditor.Document
///
/// Is called when the LineSegment is deleted.
///
- internal void Deleted()
+ internal void Deleted(ref DeferredEventList deferredEventList)
{
//Console.WriteLine("Deleted");
treeEntry = LineSegmentTree.Enumerator.Invalid;
if (anchors != null) {
foreach (TextAnchor a in anchors) {
- a.Deleted();
+ a.Delete(ref deferredEventList);
}
anchors = null;
}
@@ -150,7 +152,7 @@ namespace ICSharpCode.TextEditor.Document
///
/// Is called when a part of the line is removed.
///
- internal void RemovedLinePart(int startColumn, int length)
+ internal void RemovedLinePart(ref DeferredEventList deferredEventList, int startColumn, int length)
{
if (length == 0)
return;
@@ -166,7 +168,7 @@ namespace ICSharpCode.TextEditor.Document
} else {
if (deletedAnchors == null)
deletedAnchors = new List();
- a.Deleted();
+ a.Delete(ref deferredEventList);
deletedAnchors.Add(a);
}
}
diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/TextAnchor.cs b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/TextAnchor.cs
index 066a316daa..8747e3c711 100644
--- a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/TextAnchor.cs
+++ b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/TextAnchor.cs
@@ -85,9 +85,20 @@ namespace ICSharpCode.TextEditor.Document
///
public AnchorMovementType MovementType { get; set; }
- internal void Deleted()
+ public event EventHandler Deleted;
+
+ internal void Delete(ref DeferredEventList deferredEventList)
{
+ // we cannot fire an event here because this method is called while the LineManager adjusts the
+ // lineCollection, so an event handler could see inconsistent state
lineSegment = null;
+ deferredEventList.AddDeletedAnchor(this);
+ }
+
+ internal void RaiseDeleted()
+ {
+ if (Deleted != null)
+ Deleted(this, EventArgs.Empty);
}
internal TextAnchor(LineSegment lineSegment, int columnNumber)
diff --git a/src/Main/Base/Project/Src/Services/Debugger/BreakpointBookmark.cs b/src/Main/Base/Project/Src/Services/Debugger/BreakpointBookmark.cs
index be9be3ebc7..dbb530dfc0 100644
--- a/src/Main/Base/Project/Src/Services/Debugger/BreakpointBookmark.cs
+++ b/src/Main/Base/Project/Src/Services/Debugger/BreakpointBookmark.cs
@@ -26,7 +26,7 @@ namespace ICSharpCode.SharpDevelop.Debugging
}
set {
isHealthy = value;
- if (Document != null && !Line.IsDeleted) {
+ if (Document != null && !Anchor.IsDeleted) {
Document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.SingleLine, LineNumber));
Document.CommitUpdate();
}
@@ -38,7 +38,7 @@ namespace ICSharpCode.SharpDevelop.Debugging
set { tooltip = value; }
}
- public BreakpointBookmark(string fileName, IDocument document, int lineNumber) : base(fileName, document, lineNumber)
+ public BreakpointBookmark(string fileName, IDocument document, TextLocation location) : base(fileName, document, location)
{
}
@@ -49,9 +49,7 @@ namespace ICSharpCode.SharpDevelop.Debugging
protected override TextMarker CreateMarker()
{
- if (LineNumber >= Document.TotalNumberOfLines)
- LineNumber = Document.TotalNumberOfLines - 1;
- LineSegment lineSeg = Document.GetLineSegment(LineNumber);
+ LineSegment lineSeg = Anchor.Line;
TextMarker marker = new TextMarker(lineSeg.Offset, lineSeg.Length, TextMarkerType.SolidBlock, defaultColor, Color.White);
Document.MarkerStrategy.AddMarker(marker);
return marker;
diff --git a/src/Main/Base/Project/Src/Services/Debugger/CurrentLineBookmark.cs b/src/Main/Base/Project/Src/Services/Debugger/CurrentLineBookmark.cs
index d494f42f6c..1e4bd9fd46 100644
--- a/src/Main/Base/Project/Src/Services/Debugger/CurrentLineBookmark.cs
+++ b/src/Main/Base/Project/Src/Services/Debugger/CurrentLineBookmark.cs
@@ -43,7 +43,7 @@ namespace ICSharpCode.SharpDevelop.Debugging
endColumn = makerEndColumn;
LineSegment line = document.GetLineSegment(startLine - 1);
- instance = new CurrentLineBookmark(fileName, document, startLine - 1);
+ instance = new CurrentLineBookmark(fileName, document, new TextLocation(startColumn - 1, startLine - 1));
document.BookmarkManager.AddMark(instance);
document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.LinesBetween, startLine - 1, endLine - 1));
document.CommitUpdate();
@@ -64,7 +64,7 @@ namespace ICSharpCode.SharpDevelop.Debugging
}
}
- public CurrentLineBookmark(string fileName, IDocument document, int startLine) : base(fileName, document, startLine)
+ public CurrentLineBookmark(string fileName, IDocument document, TextLocation location) : base(fileName, document, location)
{
this.IsSaved = false;
this.IsVisibleInBookmarkPad = false;
diff --git a/src/Main/Base/Project/Src/Services/Debugger/DebuggerService.cs b/src/Main/Base/Project/Src/Services/Debugger/DebuggerService.cs
index 6d1d1a7303..38aca55462 100644
--- a/src/Main/Base/Project/Src/Services/Debugger/DebuggerService.cs
+++ b/src/Main/Base/Project/Src/Services/Debugger/DebuggerService.cs
@@ -230,13 +230,15 @@ namespace ICSharpCode.SharpDevelop.Debugging
}
}
}
+ int column = 0;
foreach (char ch in document.GetText(document.GetLineSegment(lineNumber))) {
if (!char.IsWhiteSpace(ch)) {
- document.BookmarkManager.AddMark(new BreakpointBookmark(fileName, document, lineNumber));
+ document.BookmarkManager.AddMark(new BreakpointBookmark(fileName, document, new TextLocation(column, lineNumber)));
document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.SingleLine, lineNumber));
document.CommitUpdate();
break;
}
+ column++;
}
}
diff --git a/src/Main/Base/Project/Src/TextEditor/Bookmarks/Bookmark.cs b/src/Main/Base/Project/Src/TextEditor/Bookmarks/Bookmark.cs
index 486f9f426a..57a6cf06f7 100644
--- a/src/Main/Base/Project/Src/TextEditor/Bookmarks/Bookmark.cs
+++ b/src/Main/Base/Project/Src/TextEditor/Bookmarks/Bookmark.cs
@@ -18,7 +18,7 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
[TypeConverter(typeof(BookmarkConverter))]
public class SDBookmark : Bookmark
{
- public SDBookmark(string fileName, IDocument document, int lineNumber) : base(document, lineNumber)
+ public SDBookmark(string fileName, IDocument document, TextLocation location) : base(document, location)
{
this.fileName = fileName;
}
@@ -96,7 +96,7 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
///
public abstract class SDMarkerBookmark : SDBookmark
{
- public SDMarkerBookmark(string fileName, IDocument document, int lineNumber) : base(fileName, document, lineNumber)
+ public SDMarkerBookmark(string fileName, IDocument document, TextLocation location) : base(fileName, document, location)
{
SetMarker();
}
@@ -169,9 +169,9 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
}
}
- public Bookmark CreateBookmark(IDocument document, int lineNumber)
+ public Bookmark CreateBookmark(IDocument document, TextLocation location)
{
- return new SDBookmark(fileName, document, lineNumber);
+ return new SDBookmark(fileName, document, location);
}
}
}
diff --git a/src/Main/Base/Project/Src/TextEditor/Bookmarks/BookmarkConverter.cs b/src/Main/Base/Project/Src/TextEditor/Bookmarks/BookmarkConverter.cs
index 9e19244d5a..ab41b1ecaa 100644
--- a/src/Main/Base/Project/Src/TextEditor/Bookmarks/BookmarkConverter.cs
+++ b/src/Main/Base/Project/Src/TextEditor/Bookmarks/BookmarkConverter.cs
@@ -5,6 +5,7 @@
// $Revision$
//
+using ICSharpCode.TextEditor;
using System;
using System.ComponentModel;
using System.Globalization;
@@ -27,20 +28,25 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
{
if (value is string) {
string[] v = ((string)value).Split('|');
+ if (v.Length != 5)
+ return null;
string fileName = v[1];
int lineNumber = int.Parse(v[2], culture);
+ int columnNumber = int.Parse(v[3], culture);
if (lineNumber < 0)
return null;
+ if (columnNumber < 0)
+ return null;
SDBookmark bookmark;
switch (v[0]) {
case "Breakpoint":
- bookmark = new Debugging.BreakpointBookmark(fileName, null, lineNumber);
+ bookmark = new Debugging.BreakpointBookmark(fileName, null, new TextLocation(columnNumber, lineNumber));
break;
default:
- bookmark = new SDBookmark(fileName, null, lineNumber);
+ bookmark = new SDBookmark(fileName, null, new TextLocation(columnNumber, lineNumber));
break;
}
- bookmark.IsEnabled = bool.Parse(v[3]);
+ bookmark.IsEnabled = bool.Parse(v[4]);
return bookmark;
} else {
return base.ConvertFrom(context, culture, value);
@@ -62,6 +68,8 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
b.Append('|');
b.Append(bookmark.LineNumber);
b.Append('|');
+ b.Append(bookmark.ColumnNumber);
+ b.Append('|');
b.Append(bookmark.IsEnabled.ToString());
return b.ToString();
} else {
diff --git a/src/Main/Base/Project/Src/TextEditor/Bookmarks/BookmarkManager.cs b/src/Main/Base/Project/Src/TextEditor/Bookmarks/BookmarkManager.cs
index cee5478c65..e52291e4e2 100644
--- a/src/Main/Base/Project/Src/TextEditor/Bookmarks/BookmarkManager.cs
+++ b/src/Main/Base/Project/Src/TextEditor/Bookmarks/BookmarkManager.cs
@@ -40,6 +40,7 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
public static void AddMark(SDBookmark bookmark)
{
+ if (bookmark == null) return;
if (bookmarks.Contains(bookmark)) return;
if (bookmarks.Exists(b => IsEqualBookmark(b, bookmark))) return;
bookmarks.Add(bookmark);
diff --git a/src/Main/Base/Project/Src/TextEditor/Bookmarks/ClassMemberBookmark.cs b/src/Main/Base/Project/Src/TextEditor/Bookmarks/ClassMemberBookmark.cs
index 8902f1c92b..a7c037d855 100644
--- a/src/Main/Base/Project/Src/TextEditor/Bookmarks/ClassMemberBookmark.cs
+++ b/src/Main/Base/Project/Src/TextEditor/Bookmarks/ClassMemberBookmark.cs
@@ -32,20 +32,14 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
}
public ClassMemberBookmark(IDocument document, IMember member)
- : base(document, GetLineNumberFromMember(document, member))
+ : base(document, GetTextLocationFromMember(document, member))
{
this.member = member;
}
- static int GetLineNumberFromMember(IDocument document, IMember member)
+ static TextLocation GetTextLocationFromMember(IDocument document, IMember member)
{
- int line = member.Region.BeginLine - 1;
- if (line < 0)
- return 0;
- else if (document != null && line >= document.TotalNumberOfLines)
- return document.TotalNumberOfLines - 1;
- else
- return line;
+ return new TextLocation(member.Region.BeginColumn - 1, member.Region.BeginLine - 1);
}
public const string ContextMenuPath = "/SharpDevelop/ViewContent/DefaultTextEditor/ClassMemberContextMenu";
@@ -84,20 +78,14 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
}
public ClassBookmark(IDocument document, IClass @class)
- : base(document, GetLineNumberFromClass(document, @class))
+ : base(document, GetTextLocationFromClass(document, @class))
{
this.@class = @class;
}
- static int GetLineNumberFromClass(IDocument document, IClass @class)
+ static TextLocation GetTextLocationFromClass(IDocument document, IClass @class)
{
- int line = @class.Region.BeginLine - 1;
- if (line < 0)
- return 0;
- else if (document != null && line >= document.TotalNumberOfLines)
- return document.TotalNumberOfLines - 1;
- else
- return line;
+ return new TextLocation(@class.Region.BeginColumn - 1, @class.Region.BeginLine - 1);
}
public const string ContextMenuPath = "/SharpDevelop/ViewContent/DefaultTextEditor/ClassBookmarkContextMenu";