~halega/+junk/sharpdevelop

« back to all changes in this revision

Viewing changes to src/Main/Base/Project/Src/Editor/ReadOnlyDocument.cs

  • Committer: sk
  • Date: 2011-09-10 05:17:57 UTC
  • Revision ID: halega@halega.com-20110910051757-qfouz1llya9m6boy
4.1.0.7915 Release Candidate 1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
 
2
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
 
3
 
 
4
using System;
 
5
using System.Collections.Generic;
 
6
using ICSharpCode.Core;
 
7
using ICSharpCode.NRefactory;
 
8
 
 
9
namespace ICSharpCode.SharpDevelop.Editor
 
10
{
 
11
        /// <summary>
 
12
        /// Read-only implementation of IDocument.
 
13
        /// </summary>
 
14
        sealed class ReadOnlyDocument : IDocument
 
15
        {
 
16
                ITextBuffer textBuffer;
 
17
                int[] lines;
 
18
                
 
19
                public ReadOnlyDocument(ITextBuffer textBuffer)
 
20
                {
 
21
                        if (textBuffer == null)
 
22
                                throw new ArgumentNullException("textBuffer");
 
23
                        // ensure that underlying buffer is immutable
 
24
                        this.textBuffer = textBuffer.CreateSnapshot();
 
25
                        List<int> lines = new List<int>();
 
26
                        lines.Add(0);
 
27
                        int offset = 0;
 
28
                        string newlineType;
 
29
                        var textSource = DocumentUtilitites.GetTextSource(this.textBuffer);
 
30
                        while ((offset = ICSharpCode.AvalonEdit.Document.TextUtilities.FindNextNewLine(textSource, offset, out newlineType)) >= 0) {
 
31
                                offset += newlineType.Length;
 
32
                                lines.Add(offset);
 
33
                        }
 
34
                        this.lines = lines.ToArray();
 
35
                }
 
36
                
 
37
                public IDocumentLine GetLine(int lineNumber)
 
38
                {
 
39
                        if (lineNumber < 1 || lineNumber > lines.Length)
 
40
                                throw new ArgumentOutOfRangeException("lineNumber", lineNumber, "Value must be between 1 and " + lines.Length);
 
41
                        return new ReadOnlyDocumentLine(this, lineNumber);
 
42
                }
 
43
                
 
44
                sealed class ReadOnlyDocumentLine : IDocumentLine
 
45
                {
 
46
                        readonly ReadOnlyDocument doc;
 
47
                        readonly int lineNumber;
 
48
                        readonly int offset, endOffset;
 
49
                        
 
50
                        public ReadOnlyDocumentLine(ReadOnlyDocument doc, int lineNumber)
 
51
                        {
 
52
                                this.doc = doc;
 
53
                                this.lineNumber = lineNumber;
 
54
                                this.offset = doc.GetStartOffset(lineNumber);
 
55
                                this.endOffset = doc.GetEndOffset(lineNumber);
 
56
                        }
 
57
                        
 
58
                        public int Offset {
 
59
                                get { return offset; }
 
60
                        }
 
61
                        
 
62
                        public int Length {
 
63
                                get { return endOffset - offset; }
 
64
                        }
 
65
                        
 
66
                        public int EndOffset {
 
67
                                get { return endOffset; }
 
68
                        }
 
69
                        
 
70
                        public int TotalLength {
 
71
                                get {
 
72
                                        return doc.GetTotalEndOffset(lineNumber) - offset;
 
73
                                }
 
74
                        }
 
75
                        
 
76
                        public int DelimiterLength {
 
77
                                get {
 
78
                                        return doc.GetTotalEndOffset(lineNumber) - endOffset;
 
79
                                }
 
80
                        }
 
81
                        
 
82
                        public int LineNumber {
 
83
                                get { return lineNumber; }
 
84
                        }
 
85
                        
 
86
                        public string Text {
 
87
                                get {
 
88
                                        return doc.GetText(this.Offset, this.Length);
 
89
                                }
 
90
                        }
 
91
                }
 
92
                
 
93
                int GetStartOffset(int lineNumber)
 
94
                {
 
95
                        return lines[lineNumber-1];
 
96
                }
 
97
                
 
98
                int GetTotalEndOffset(int lineNumber)
 
99
                {
 
100
                        return lineNumber < lines.Length ? lines[lineNumber] : textBuffer.TextLength;
 
101
                }
 
102
                
 
103
                int GetEndOffset(int lineNumber)
 
104
                {
 
105
                        if (lineNumber == lines.Length)
 
106
                                return textBuffer.TextLength;
 
107
                        int off = lines[lineNumber] - 1;
 
108
                        if (off > 0 && textBuffer.GetCharAt(off - 1) == '\r' && textBuffer.GetCharAt(off) == '\n')
 
109
                                off--;
 
110
                        return off;
 
111
                }
 
112
                
 
113
                public IDocumentLine GetLineForOffset(int offset)
 
114
                {
 
115
                        return GetLine(GetLineNumberForOffset(offset));
 
116
                }
 
117
                
 
118
                int GetLineNumberForOffset(int offset)
 
119
                {
 
120
                        int r = Array.BinarySearch(lines, offset);
 
121
                        return r < 0 ? ~r : r + 1;
 
122
                }
 
123
                
 
124
                public int PositionToOffset(int line, int column)
 
125
                {
 
126
                        if (line < 1 || line > lines.Length)
 
127
                                throw new ArgumentOutOfRangeException("line", line, "Value must be between 1 and " + lines.Length);
 
128
                        int lineStart = GetStartOffset(line);
 
129
                        if (column <= 0)
 
130
                                return lineStart;
 
131
                        int lineEnd = GetEndOffset(line);
 
132
                        if (column >= lineEnd - lineStart)
 
133
                                return lineEnd;
 
134
                        return lineStart + column - 1;
 
135
                }
 
136
                
 
137
                public Location OffsetToPosition(int offset)
 
138
                {
 
139
                        if (offset < 0 || offset > textBuffer.TextLength)
 
140
                                throw new ArgumentOutOfRangeException("offset", offset, "Value must be between 0 and " + textBuffer.TextLength);
 
141
                        int line = GetLineNumberForOffset(offset);
 
142
                        return new Location(offset-GetStartOffset(line)+1, line);
 
143
                }
 
144
                
 
145
                public event EventHandler<TextChangeEventArgs> Changing { add {} remove {} }
 
146
                
 
147
                public event EventHandler<TextChangeEventArgs> Changed { add {} remove {} }
 
148
                
 
149
                public event EventHandler TextChanged { add {} remove {} }
 
150
                
 
151
                public string Text {
 
152
                        get { return textBuffer.Text; }
 
153
                        set {
 
154
                                throw new NotSupportedException();
 
155
                        }
 
156
                }
 
157
                
 
158
                public int TotalNumberOfLines {
 
159
                        get { return lines.Length; }
 
160
                }
 
161
                
 
162
                public ITextBufferVersion Version {
 
163
                        get { return null; }
 
164
                }
 
165
                
 
166
                public int TextLength {
 
167
                        get { return textBuffer.TextLength; }
 
168
                }
 
169
                
 
170
                void IDocument.Insert(int offset, string text)
 
171
                {
 
172
                        throw new NotSupportedException();
 
173
                }
 
174
                
 
175
                void IDocument.Insert(int offset, string text, AnchorMovementType defaultAnchorMovementType)
 
176
                {
 
177
                        throw new NotSupportedException();
 
178
                }
 
179
                
 
180
                void IDocument.Remove(int offset, int length)
 
181
                {
 
182
                        throw new NotSupportedException();
 
183
                }
 
184
                
 
185
                void IDocument.Replace(int offset, int length, string newText)
 
186
                {
 
187
                        throw new NotSupportedException();
 
188
                }
 
189
                
 
190
                public void StartUndoableAction()
 
191
                {
 
192
                }
 
193
                
 
194
                public void EndUndoableAction()
 
195
                {
 
196
                }
 
197
                
 
198
                public IDisposable OpenUndoGroup()
 
199
                {
 
200
                        return new CallbackOnDispose(EndUndoableAction);
 
201
                }
 
202
                
 
203
                public ITextAnchor CreateAnchor(int offset)
 
204
                {
 
205
                        return new ReadOnlyDocumentTextAnchor(OffsetToPosition(offset), offset);
 
206
                }
 
207
                
 
208
                sealed class ReadOnlyDocumentTextAnchor : ITextAnchor
 
209
                {
 
210
                        readonly Location location;
 
211
                        readonly int offset;
 
212
                        
 
213
                        public ReadOnlyDocumentTextAnchor(Location location, int offset)
 
214
                        {
 
215
                                this.location = location;
 
216
                                this.offset = offset;
 
217
                        }
 
218
                        
 
219
                        public event EventHandler Deleted { add {} remove {} }
 
220
                        
 
221
                        public Location Location {
 
222
                                get { return location; }
 
223
                        }
 
224
                        
 
225
                        public int Offset {
 
226
                                get { return offset; }
 
227
                        }
 
228
                        
 
229
                        public AnchorMovementType MovementType { get; set; }
 
230
                        
 
231
                        public bool SurviveDeletion { get; set; }
 
232
                        
 
233
                        public bool IsDeleted {
 
234
                                get { return false; }
 
235
                        }
 
236
                        
 
237
                        public int Line {
 
238
                                get { return location.Line; }
 
239
                        }
 
240
                        
 
241
                        public int Column {
 
242
                                get { return location.Column; }
 
243
                        }
 
244
                }
 
245
                
 
246
                public ITextBuffer CreateSnapshot()
 
247
                {
 
248
                        return textBuffer; // textBuffer is immutable
 
249
                }
 
250
                
 
251
                public ITextBuffer CreateSnapshot(int offset, int length)
 
252
                {
 
253
                        return textBuffer.CreateSnapshot(offset, length);
 
254
                }
 
255
                
 
256
                public System.IO.TextReader CreateReader()
 
257
                {
 
258
                        return textBuffer.CreateReader();
 
259
                }
 
260
                
 
261
                public System.IO.TextReader CreateReader(int offset, int length)
 
262
                {
 
263
                        return textBuffer.CreateReader(offset, length);
 
264
                }
 
265
                
 
266
                public char GetCharAt(int offset)
 
267
                {
 
268
                        return textBuffer.GetCharAt(offset);
 
269
                }
 
270
                
 
271
                public string GetText(int offset, int length)
 
272
                {
 
273
                        return textBuffer.GetText(offset, length);
 
274
                }
 
275
                
 
276
                public object GetService(Type serviceType)
 
277
                {
 
278
                        return null;
 
279
                }
 
280
        }
 
281
}