39
39
namespace Mono.TextEditor
41
public class TextDocument : AbstractAnnotatable, IBuffer, ICSharpCode.NRefactory.Editor.IDocument
41
public class TextDocument : AbstractAnnotatable, ICSharpCode.NRefactory.Editor.IDocument
43
43
readonly IBuffer buffer;
44
44
readonly ILineSplitter splitter;
60
60
if (mimeType != value) {
62
SyntaxMode = SyntaxModeService.GetSyntaxMode (this);
63
SyntaxMode = SyntaxModeService.GetSyntaxMode (this, value);
67
70
public string FileName {
76
OnFileNameChanged (EventArgs.Empty);
80
public event EventHandler FileNameChanged;
82
protected virtual void OnFileNameChanged (EventArgs e)
84
EventHandler handler = this.FileNameChanged;
72
89
public bool HeightChanged {
116
133
splitter.LineChanged += SplitterLineSegmentTreeLineChanged;
117
134
splitter.LineRemoved += HandleSplitterLineSegmentTreeLineRemoved;
118
135
foldSegmentTree.tree.NodeRemoved += HandleFoldSegmentTreetreeNodeRemoved;
136
textSegmentMarkerTree.InstallListener (this);
121
139
void HandleFoldSegmentTreetreeNodeRemoved (object sender, RedBlackTree<FoldSegment>.RedBlackTreeNodeEventArgs e)
168
186
var args = new DocumentChangeEventArgs (0, Text, value);
187
textSegmentMarkerTree.Clear ();
169
188
OnTextReplacing (args);
170
189
buffer.Text = value;
190
extendingTextMarkers = new List<TextLineMarker> ();
171
191
splitter.Initalize (value);
172
192
ClearFoldSegments ();
173
193
OnTextReplaced (args);
181
public void Insert (int offset, string text)
201
public void Insert (int offset, string text, ICSharpCode.NRefactory.Editor.AnchorMovementType anchorMovementType = AnchorMovementType.Default)
183
Replace (offset, 0, text);
203
Replace (offset, 0, text, anchorMovementType);
186
206
public void Remove (int offset, int count)
196
216
public void Replace (int offset, int count, string value)
218
Replace (offset, count, value, AnchorMovementType.Default);
221
public void Replace (int offset, int count, string value, ICSharpCode.NRefactory.Editor.AnchorMovementType anchorMovementType = AnchorMovementType.Default)
199
224
throw new ArgumentOutOfRangeException ("offset", "must be > 0, was: " + offset);
200
225
if (offset > TextLength)
205
230
InterruptFoldWorker ();
207
232
//int oldLineCount = LineCount;
208
var args = new DocumentChangeEventArgs (offset, count > 0 ? GetTextAt (offset, count) : "", value);
233
var args = new DocumentChangeEventArgs (offset, count > 0 ? GetTextAt (offset, count) : "", value, anchorMovementType);
209
234
OnTextReplacing (args);
210
value = args.InsertedText;
235
value = args.InsertedText.Text;
211
236
UndoOperation operation = null;
213
238
operation = new UndoOperation (args);
454
479
if (lineNr < DocumentLocation.MinLine)
455
480
return DocumentLocation.Empty;
456
481
DocumentLine line = GetLine (lineNr);
457
return new DocumentLocation (lineNr, System.Math.Min (line.LengthIncludingDelimiter, offset - line.Offset) + 1);
482
var col = System.Math.Max (1, System.Math.Min (line.LengthIncludingDelimiter, offset - line.Offset) + 1);
483
return new DocumentLocation (lineNr, col);
460
486
public string GetLineIndent (int lineNumber)
545
571
public virtual void Undo (TextDocument doc)
547
doc.Replace (args.Offset, args.InsertionLength, args.RemovedText);
573
doc.Replace (args.Offset, args.InsertionLength, args.RemovedText.Text);
551
577
public virtual void Redo (TextDocument doc)
553
doc.Replace (args.Offset, args.RemovalLength, args.InsertedText);
579
doc.Replace (args.Offset, args.RemovalLength, args.InsertedText.Text);
666
692
// op.InformTextReplace (args);
696
internal int UndoBeginOffset {
698
if (undoStack.Count == 0)
700
var op = undoStack.Peek ();
701
while (op is AtomicUndoOperation)
702
op = ((AtomicUndoOperation)op).Operations.FirstOrDefault ();
705
return ((UndoOperation)op).Args.Offset;
709
internal int RedoBeginOffset {
711
if (redoStack.Count == 0)
713
var op = redoStack.Peek ();
714
while (op is AtomicUndoOperation)
715
op = ((AtomicUndoOperation)op).Operations.FirstOrDefault ();
718
return ((UndoOperation)op).Args.Offset;
670
722
public bool CanUndo {
672
724
return this.undoStack.Count > 0 || currentAtomicOperation != null;
797
849
this.RequestUpdate (new UpdateAll ());
798
850
this.CommitDocumentUpdate ();
853
public void RollbackTo (ICSharpCode.NRefactory.Editor.ITextSourceVersion version)
855
var steps = Version.CompareAge (version);
857
throw new InvalidOperationException ("Invalid version");
858
while (steps-- > 0) {
859
undoStack.Pop ().Undo (this);
801
863
internal protected virtual void OnUndone (UndoOperationEventArgs e)
803
865
EventHandler<UndoOperationEventArgs> handler = this.Undone;
1227
List<TextMarker> extendingTextMarkers = new List<TextMarker> ();
1290
List<TextLineMarker> extendingTextMarkers = new List<TextLineMarker> ();
1228
1291
public IEnumerable<DocumentLine> LinesWithExtendingTextMarkers {
1230
1293
return from marker in extendingTextMarkers where marker.LineSegment != null select marker.LineSegment;
1234
public void AddMarker (int lineNumber, TextMarker marker)
1297
public void AddMarker (int lineNumber, TextLineMarker marker)
1236
1299
AddMarker (this.GetLine (lineNumber), marker);
1239
public void AddMarker (DocumentLine line, TextMarker marker)
1302
public void AddMarker (DocumentLine line, TextLineMarker marker)
1241
1304
AddMarker (line, marker, true);
1244
public void AddMarker (DocumentLine line, TextMarker marker, bool commitUpdate)
1307
public void AddMarker (DocumentLine line, TextLineMarker marker, bool commitUpdate)
1246
1309
if (line == null || marker == null)
1248
if (marker is IExtendingTextMarker) {
1311
if (marker is IExtendingTextLineMarker) {
1249
1312
lock (extendingTextMarkers) {
1250
1313
HeightChanged = true;
1251
1314
extendingTextMarkers.Add (marker);
1258
1321
this.CommitLineUpdate (line);
1261
static int CompareMarkers (TextMarker left, TextMarker right)
1324
static int CompareMarkers (TextLineMarker left, TextLineMarker right)
1263
1326
if (left.LineSegment == null || right.LineSegment == null)
1265
1328
return left.LineSegment.Offset.CompareTo (right.LineSegment.Offset);
1268
public void RemoveMarker (TextMarker marker)
1331
public void RemoveMarker (TextLineMarker marker)
1270
1333
RemoveMarker (marker, true);
1273
public void RemoveMarker (TextMarker marker, bool updateLine)
1336
public void RemoveMarker (TextLineMarker marker, bool updateLine)
1275
1338
if (marker == null)
1277
1340
var line = marker.LineSegment;
1278
1341
if (line == null)
1280
if (marker is IExtendingTextMarker) {
1343
if (marker is IExtendingTextLineMarker) {
1281
1344
lock (extendingTextMarkers) {
1282
1345
HeightChanged = true;
1283
1346
extendingTextMarkers.Remove (marker);
1308
1371
if (line == null || type == null)
1310
if (typeof(IExtendingTextMarker).IsAssignableFrom (type)) {
1373
if (typeof(IExtendingTextLineMarker).IsAssignableFrom (type)) {
1311
1374
lock (extendingTextMarkers) {
1312
1375
HeightChanged = true;
1313
foreach (TextMarker marker in line.Markers.Where (marker => marker is IExtendingTextMarker)) {
1376
foreach (TextLineMarker marker in line.Markers.Where (marker => marker is IExtendingTextLineMarker)) {
1314
1377
extendingTextMarkers.Remove (marker);
1319
1382
if (updateLine)
1320
1383
this.CommitLineUpdate (line);
1388
#region Text segment markers
1390
SegmentTree<TextSegmentMarker> textSegmentMarkerTree = new SegmentTree<TextSegmentMarker> ();
1392
public IEnumerable<TextSegmentMarker> GetTextSegmentMarkersAt (DocumentLine line)
1394
return textSegmentMarkerTree.GetSegmentsOverlapping (line.Segment);
1397
public IEnumerable<TextSegmentMarker> GetTextSegmentMarkersAt (TextSegment segment)
1399
return textSegmentMarkerTree.GetSegmentsOverlapping (segment);
1402
public IEnumerable<TextSegmentMarker> GetTextSegmentMarkersAt (int offset)
1404
return textSegmentMarkerTree.GetSegmentsAt (offset);
1408
public void AddMarker (TextSegmentMarker marker)
1410
CommitLineUpdate (GetLineByOffset (marker.Offset));
1411
textSegmentMarkerTree.Add (marker);
1415
/// Removes a marker from the document.
1417
/// <returns><c>true</c>, if marker was removed, <c>false</c> otherwise.</returns>
1418
/// <param name="marker">Marker.</param>
1419
public bool RemoveMarker (TextSegmentMarker marker)
1421
bool wasRemoved = textSegmentMarkerTree.Remove (marker);
1423
CommitLineUpdate (GetLineByOffset (marker.Offset));
1323
1429
void HandleSplitterLineSegmentTreeLineRemoved (object sender, LineEventArgs e)
1325
foreach (TextMarker marker in e.Line.Markers) {
1326
if (marker is IExtendingTextMarker) {
1431
foreach (TextLineMarker marker in e.Line.Markers) {
1432
if (marker is IExtendingTextLineMarker) {
1327
1433
lock (extendingTextMarkers) {
1328
1434
HeightChanged = true;
1329
1435
extendingTextMarkers.Remove (marker);
1331
UnRegisterVirtualTextMarker ((IExtendingTextMarker)marker);
1437
UnRegisterVirtualTextMarker ((IExtendingTextLineMarker)marker);
1540
Dictionary<int, IExtendingTextMarker> virtualTextMarkers = new Dictionary<int, IExtendingTextMarker> ();
1541
public void RegisterVirtualTextMarker (int lineNumber, IExtendingTextMarker marker)
1646
Dictionary<int, IExtendingTextLineMarker> virtualTextMarkers = new Dictionary<int, IExtendingTextLineMarker> ();
1647
public void RegisterVirtualTextMarker (int lineNumber, IExtendingTextLineMarker marker)
1543
1649
virtualTextMarkers[lineNumber] = marker;
1546
public IExtendingTextMarker GetExtendingTextMarker (int lineNumber)
1652
public IExtendingTextLineMarker GetExtendingTextMarker (int lineNumber)
1548
IExtendingTextMarker result;
1654
IExtendingTextLineMarker result;
1549
1655
if (virtualTextMarkers.TryGetValue (lineNumber, out result))
1557
1663
/// <param name='marker'>
1560
public void UnRegisterVirtualTextMarker (IExtendingTextMarker marker)
1666
public void UnRegisterVirtualTextMarker (IExtendingTextLineMarker marker)
1562
1668
var keys = new List<int> (from pair in virtualTextMarkers where pair.Value == marker select pair.Key);
1563
1669
keys.ForEach (key => { virtualTextMarkers.Remove (key); CommitLineUpdate (key); });
1692
1798
return OffsetToLocation (offset);
1801
void ICSharpCode.NRefactory.Editor.IDocument.Insert (int offset, ITextSource text)
1803
Insert (offset, text.Text);
1806
void ICSharpCode.NRefactory.Editor.IDocument.Replace (int offset, int count, ITextSource text)
1808
Replace (offset, count, text.Text);
1695
1811
void ICSharpCode.NRefactory.Editor.IDocument.Insert (int offset, string text)
1697
1813
Insert (offset, text);
1700
public void Insert (int offset, string text, ICSharpCode.NRefactory.Editor.AnchorMovementType defaultAnchorMovementType)
1702
Insert (offset, text);
1816
void ICSharpCode.NRefactory.Editor.IDocument.Insert (int offset, ITextSource text, AnchorMovementType anchorMovementType)
1818
Insert (offset, text.Text, anchorMovementType);
1821
void ICSharpCode.NRefactory.Editor.IDocument.Insert (int offset, string text, AnchorMovementType anchorMovementType)
1823
Insert (offset, text, anchorMovementType);
1705
1826
void ICSharpCode.NRefactory.Editor.IDocument.StartUndoableAction ()
1728
1849
#region ITextSource implementation
1850
void ICSharpCode.NRefactory.Editor.ITextSource.WriteTextTo (System.IO.TextWriter writer)
1852
throw new NotImplementedException ();
1855
void ICSharpCode.NRefactory.Editor.ITextSource.WriteTextTo (System.IO.TextWriter writer, int offset, int length)
1857
throw new NotImplementedException ();
1729
1860
ICSharpCode.NRefactory.Editor.ITextSource ICSharpCode.NRefactory.Editor.ITextSource.CreateSnapshot ()
1731
1862
throw new NotImplementedException ();