0:   //  TextBuffer.cs
1:   //  Copyright (C) 2000 Mike Krueger
2:   //  Copyright (C) 2000 Andrea Paatz
3:   //
4:   //  This program is free software; you can redistribute it and/or modify
5:   //  it under the terms of the GNU General Public License as published by
6:   //  the Free Software Foundation; either version 2 of the License, or
7:   //  (at your option) any later version.
8:   //
9:   //  This program is distributed in the hope that it will be useful,
10:   //  but WITHOUT ANY WARRANTY; without even the implied warranty of
11:   //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12:   //  GNU General Public License for more details.
13:   //
14:   //  You should have received a copy of the GNU General Public License
15:   //  along with this program; if not, write to the Free Software
16:   //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17:  
18:   using System;
19:   using System.Drawing;
20:   using System.Diagnostics;
21:   using System.Collections;
22:   using System.IO;
23:   using System.Text;
24:   using System.Windows.Forms;
25:  
26:   using SharpDevelop.Tool.Data;
27:   using SharpDevelop.Internal.Undo;
28:   using SharpDevelop.Gui.Edit// for the ProgressEventHandler
29:  
30:   namespace SharpDevelop.Internal.Text {
31:       
32:       public class Fold
33:       {
34:           public int Start;
35:           public int Length;
36:           
37:           public Fold(int startint length)
38:           {
39:               this.Start  start;
40:               this.Length length;
41:           }
42:       }
43:       
44:       public class Foldings
45:       {
46:           TextBuffer buffer;
47:           public SortedList   foldings new SortedList();
48:           
49:           public Foldings(TextBuffer buffer)
50:           {
51:               this.buffer buffer;
52:               buffer.MoveIndices += new MoveIndicesHandler(MoveIndices);
53:           }
54:           
55:           public void MoveIndices(int indexint count)
56:           {
57:               SortedList newfoldings new SortedList();
58:               bool redraw false;
59:               foreach (DictionaryEntry folding in foldings) {
60:                   int foldat = (int)folding.Key;
61:                   Console.WriteLine("index " index " count " count " foldat " foldat);
62:                   if (count < && foldat >= index count && foldat < index) {// delete cleared folding;
63:                       Console.WriteLine("ShouldRedraw");
64:                       redraw true;
65:                       continue;
66:                   }
67:                   if (foldat >= index) {
68:                       foldat += count;
69:                   }
70:                   newfoldings[foldat] = folding.Value;
71:               }
72:               buffer.UpdateRequested |= redraw;
73:               foldings newfoldings;
74:           }
75:           
76:           public int  GetPhysicalLine(int linenumber)
77:           {
78:               int maxline 0;
79:               foreach (DictionaryEntry folding in foldings) {
80:                   if (folding.Value == null)
81:                       continue;
82:                   int foldat = (int)folding.Key;
83:                   int length = (int)folding.Value;
84:                   if (foldat <= linenumber && maxline <= foldat length) {
85:                       maxline foldat length;
86:                       linenumber += length;
87:                   else
88:                       break;
89:               }
90:               return linenumber;
91:           }
92:           
93:           public int  GetLogicalLine(int linenumber)
94:           {
95:               int folded 0;
96:               int maxline 0;
97:               foreach (DictionaryEntry folding in foldings) {
98:                   if (folding.Value == null)
99:                       continue;
100:                   int foldat = (int)folding.Key;
101:                   int length = (int)folding.Value;
102:                   if (foldat <= linenumber && maxline <= foldat length) {
103:                       maxline foldat length;
104:                       folded += length;
105:                   else
106:                       break;
107:               }
108:               return linenumber folded;
109:           }
110:           
111:           public void FoldPos(Point start)
112:           {
113:               int y1 = -1;
114:               int y2 = -1;
115:               
116:               int foldlevel 1;
117:               for (int start.Y;  >= 0; --i) {
118:                   if (buffer[i].foldoff)
119:                       ++foldlevel;
120:                   if (buffer[i].foldon) {
121:                       --foldlevel;
122:                       if (foldlevel <= 0) {
123:                           y1 i;
124:                           break;
125:                       }
126:                   }                    
127:               }
128:               
129:               foldlevel 1;
130:               if (buffer[start.Y].foldon)
131:                   foldlevel--;
132:               for (int start.Y;  < buffer.Length; ++i) {
133:                   if (buffer[i].foldon
134:                       ++foldlevel;
135:                   if (buffer[i].foldoff) {
136:                       --foldlevel;
137:                       if (foldlevel <= 0) {
138:                           y2 i;
139:                           break;
140:                       }
141:                   }
142:               }
143:               if (y1 == -|| y2 == -1)
144:                   return;
145:               buffer.Foldings.Fold(y1 1y2 y1 1);
146:           }
147:           
148:           public void Fold(int startint length)
149:           {
150:               if (foldings[start] == null) {
151:                   foldings[start] = length;
152:                   for (int 0< length; ++i) {
153:                       buffer[start i].Visible false;
154:                   }
155:               }
156:           }
157:           
158:           public void UnFold(int start)
159:           {
160:               if (foldings[start] != null) {
161:                   int length = (int)foldings[start];
162:                   buffer[start].Visible true;
163:                   for (int 1< length; ++i) {
164:                       if (foldings[start i] != null// skip inner folding
165:                           i += (int)foldings[start i];
166:                       buffer[start i].Visible true;
167:                   }
168:                   foldings[start] = null;
169:               }
170:           }
171:           public void UnFoldAll()
172:           {
173:               foldings.Clear();
174:               for (int 0< buffer.Length; ++i)
175:                   buffer[i].Visible true;
176:           }
177:       }
178:       
179:       public delegate void MoveIndicesHandler(int indexint count);
180:       
181:       /// <summary>
182:       /// This class represents a Text. The text is in the container MyArrayList line
183:       /// it is divided up in TextLines and TextLines provide the string as a line or 
184:       /// as divided up into words, which contain syntax highlighting information.
185:       /// </summary>
186:       public class TextBuffer
187:       {
188:           Syntax    syntax     new Syntax();
189:           UndoStack undostack  null;
190:           
191:           MyArrayList line     null;
192:           
193:           Bookmark    bookmark;
194:           bool updaterequested false;
195:           bool onlyreadable    false;
196:           bool updated         false;
197:           
198:           BufferOptions options = (BufferOptions)((ICloneable)Options.GetProperty("SharpDevelop.Internal.Text.TextBuffer.BufferOptions"new BufferOptions())).Clone();
199:           
200:           public Foldings Foldings null;
201:           
202:           public BufferOptions BufferOptions {
203:               get {
204:                   return options;
205:               }
206:           }
207:           
208:           public event MoveIndicesHandler   MoveIndices;
209:           public event ProgressEventHandler Progress;
210:           public event EventHandler         Changed;
211:           public event EventHandler         FoldChanged;
212:           public event EventHandler         LineCountChanged;
213:           
214:           public UndoStack UndoStack {
215:               get {
216:                   return undostack;
217:               }
218:           }
219:           public bool ReadOnly {
220:               get {
221:                   return onlyreadable;
222:               }
223:               set {
224:                   onlyreadable value;
225:               }
226:           }
227:           
228:           public Syntax Syntax {
229:               get {
230:                   return syntax;
231:               }
232:           }
233:           
234:           public Bookmark Bookmark {
235:               get {
236:                   return bookmark;
237:               }
238:           }
239:           
240:           public bool UpdateRequested {
241:               get {
242:                   return updaterequested;
243:               }
244:               set {
245:                   updaterequestedvalue;
246:               }
247:           }
248:           
249:           public string Text {
250:               get {
251:                   string back "";
252:                   for (int 0< line.Count 1; ++i)
253:                       back += ((TextLine)line[i]).Text "\n";
254:                   back += ((TextLine)line[line.Count 1]).Text;
255:                   return back;
256:               }
257:               set {
258:                   line            new MyArrayList(this);
259:                   string[] lines  value.Split(new char[] {'\n'});
260:                   for (int 0< lines.Length; ++i)
261:                       line.Add(new TextLine(thisilines[i]));
262:               }
263:           }
264:           
265:           public ArrayList Line {
266:               get {
267:                   return line;
268:               }
269:           }
270:           
271:           public int Length {
272:               get {
273:                   return line.Count;
274:               }
275:           }
276:           
277:           public TextLine this[int i] {
278:               get {
279:                   if (line.Count == 0)
280:                       throw new ArgumentException("TextBuffer public TextLine this[int i] : Buffer is empty");
281:                   return (TextLine)line[i];
282:               }
283:           }
284:           
285:           public TextBuffer()
286:           {
287:               undostack new UndoStack();
288:               bookmark new Bookmark(this);
289:               Foldings new Foldings(this);
290:               line new MyArrayList(this);
291:               line.Add(new TextLine(this0""));
292:               
293:               SetDefaultHighlighting();
294:               
295:               OnChanged();
296:           }
297:           
298:           void Reparse()
299:           {
300:               for (int 0< this.Length; ++i
301:                   this[i].SetText(ithis[i].Text);
302:           }
303:           
304:           public void BeginUpdate()
305:           {
306:               updated true;
307:           }
308:           public void EndUpdate()
309:           {
310:               updated false;
311:           }
312:           
313:           protected virtual void OnChanged()
314:           {
315:               if (!updated && Changed != null) {
316:                   Changed(thisnull);
317:               }
318:           }
319:           
320:           public void OnMoveIndices(int indexint count)
321:           {
322:               if (MoveIndices != null)
323:                   MoveIndices(indexcount);
324:           }
325:           
326:           void OnLineCountChanged()
327:           {
328:               if (LineCountChanged != null) {
329:                   LineCountChanged(thisnull);
330:               }
331:           }
332:  
333:           protected virtual void OnFoldEvent()
334:           {
335:               if (!updated && FoldChanged != null)
336:                   FoldChanged(thisnull);
337:           }
338:           
339:           public void Load(string filename)
340:           {
341:               line          new MyArrayList(this);
342:               StreamReader stream File.OpenText(filename);
343:               int linenumber 0;
344:               int lastpercent = -1;
345:               while (true) {
346:                   string curLine stream.ReadLine();
347:                   int percent = (int)((stream.BaseStream.Position 100) / (stream.BaseStream.Length 1));
348:                   
349:                   if (Progress != null && percent != lastpercent) {
350:                       Progress(thispercent);
351:                       lastpercent percent;
352:                   }
353:                       
354:                   if (curLine == null) {
355:                       if (linenumber == 0)
356:                           line.Add(new TextLine(this, ++linenumber""));
357:                       break;
358:                   }
359:                   
360:                   line.Add(new TextLine(this, ++linenumbercurLine));
361:               }
362:               if (line.Count == 0// file empty, insert a blank line
363:                   line.Add(new TextLine(this, ++linenumber""));
364:               stream.Close();
365:               OnChanged();
366:           }
367:           
368:           public void SetDefaultHighlighting()
369:           {
370:               SetHighlightingTo("Default");
371:               Reparse();
372:           }
373:           
374:           public void SetHighlightingFor(string filename)
375:           {
376:               string extension Path.GetExtension(filename).ToUpper();
377:               foreach (Syntax syn in Syntax.SyntaxDefinitions) {
378: