Code Coverage Statistics for Source File

c:\Tools\SD3\src\Libraries\ICSharpCode.TextEditor\Project\Src\Gui\TextEditorControlBase.cs

Sequence Point Coverage
N/A
0 of 0
Branch Coverage
N/A
0 of 0
Lines
757
Highlight: Uncovered Code Covered Code
L V Source
1
// <file>
2
//     <copyright see="prj:///doc/copyright.txt"/>
3
//     <license see="prj:///doc/license.txt"/>
4
//     <owner name="Mike Krüger" email="mike@icsharpcode.net"/>
5
//     <version>$Revision: 2739 $</version>
6
// </file>
7
8
using System;
9
using System.Collections.Generic;
10
using System.ComponentModel;
11
using System.Diagnostics;
12
using System.Drawing;
13
using System.Drawing.Text;
14
using System.IO;
15
using System.Text;
16
using System.Windows.Forms;
17
18
using ICSharpCode.TextEditor.Actions;
19
using ICSharpCode.TextEditor.Document;
20
21
namespace ICSharpCode.TextEditor
22
{
23
	/// <summary>
24
	/// This class is used for a basic text area control
25
	/// </summary>
26
	[ToolboxItem(false)]
27
	public abstract class TextEditorControlBase : UserControl
28
	{
29
		string    currentFileName = null;
30
		int       updateLevel     = 0;
31
		IDocument document;
32
		
33
		/// <summary>
34
		/// This hashtable contains all editor keys, where
35
		/// the key is the key combination and the value the
36
		/// action.
37
		/// </summary>
38
		protected Dictionary<Keys, IEditAction> editactions = new Dictionary<Keys, IEditAction>();
39
		
40
		[Browsable(false)]
41
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
42
		public ITextEditorProperties TextEditorProperties {
43
			get {
44
				return document.TextEditorProperties;
45
			}
46
			set {
47
				document.TextEditorProperties = value;
48
				OptionsChanged();
49
			}
50
		}
51
		
52
		Encoding encoding;
53
		
54
		/// <value>
55
		/// Current file's character encoding
56
		/// </value>
57
		[Browsable(false)]
58
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
59
		public Encoding Encoding {
60
			get {
61
				if (encoding == null)
62
					return TextEditorProperties.Encoding;
63
				return encoding;
64
			}
65
			set {
66
				encoding = value;
67
			}
68
		}
69
		
70
		/// <value>
71
		/// The current file name
72
		/// </value>
73
		[Browsable(false)]
74
		[ReadOnly(true)]
75
		public string FileName {
76
			get {
77
				return currentFileName;
78
			}
79
			set {
80
				if (currentFileName != value) {
81
					currentFileName = value;
82
					OnFileNameChanged(EventArgs.Empty);
83
				}
84
			}
85
		}
86
		
87
		/// <value>
88
		/// The current document
89
		/// </value>
90
		[Browsable(false)]
91
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
92
		public IDocument Document {
93
			get {
94
				return document;
95
			}
96
			set {
97
				if (value == null)
98
					throw new ArgumentNullException("value");
99
				if (document != null) {
100
					document.DocumentChanged -= OnDocumentChanged;
101
				}
102
				document = value;
103
				document.UndoStack.TextEditorControl = this;
104
				document.DocumentChanged += OnDocumentChanged;
105
			}
106
		}
107
		
108
		void OnDocumentChanged(object sender, EventArgs e)
109
		{
110
			OnTextChanged(e);
111
		}
112
		
113
		[EditorBrowsable(EditorBrowsableState.Always), Browsable(true)]
114
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
115
		[Editor("System.ComponentModel.Design.MultilineStringEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(System.Drawing.Design.UITypeEditor))]
116
		public override string Text {
117
			get {
118
				return Document.TextContent;
119
			}
120
			set {
121
				Document.TextContent = value;
122
			}
123
		}
124
		
125
		[EditorBrowsable(EditorBrowsableState.Always), Browsable(true)]
126
		public new event EventHandler TextChanged
127
		{
128
			add { base.TextChanged += value; }
129
			remove { base.TextChanged -= value; }
130
		}
131
		
132
		static Font ParseFont(string font)
133
		{
134
			string[] descr = font.Split(new char[]{',', '='});
135
			return new Font(descr[1], Single.Parse(descr[3]));
136
		}
137
		
138
		/// <value>
139
		/// If set to true the contents can't be altered.
140
		/// </value>
141
		[Browsable(false)]
142
		public bool IsReadOnly {
143
			get {
144
				return Document.ReadOnly;
145
			}
146
			set {
147
				Document.ReadOnly = value;
148
			}
149
		}
150
		
151
		/// <value>
152
		/// true, if the textarea is updating it's status, while
153
		/// it updates it status no redraw operation occurs.
154
		/// </value>
155
		[Browsable(false)]
156
		public bool IsInUpdate {
157
			get {
158
				return updateLevel > 0;
159
			}
160
		}
161
		
162
		/// <value>
163
		/// supposedly this is the way to do it according to .NET docs,
164
		/// as opposed to setting the size in the constructor
165
		/// </value>
166
		protected override Size DefaultSize {
167
			get {
168
				return new Size(100, 100);
169
			}
170
		}
171
		
172
		#region Document Properties
173
		/// <value>
174
		/// If true spaces are shown in the textarea
175
		/// </value>
176
		[Category("Appearance")]
177
		[DefaultValue(false)]
178
		[Description("If true spaces are shown in the textarea")]
179
		public bool ShowSpaces {
180
			get {
181
				return document.TextEditorProperties.ShowSpaces;
182
			}
183
			set {
184
				document.TextEditorProperties.ShowSpaces = value;
185
				OptionsChanged();
186
			}
187
		}
188
		
189
		/// <value>
190
		/// Specifies the quality of text rendering (whether to use hinting and/or anti-aliasing).
191
		/// </value>
192
		[Category("Appearance")]
193
		[DefaultValue(TextRenderingHint.SystemDefault)]
194
		[Description("Specifies the quality of text rendering (whether to use hinting and/or anti-aliasing).")]
195
		public TextRenderingHint TextRenderingHint {
196
			get {
197
				return document.TextEditorProperties.TextRenderingHint;
198
			}
199
			set {
200
				document.TextEditorProperties.TextRenderingHint = value;
201
				OptionsChanged();
202
			}
203
		}
204
		
205
		/// <value>
206
		/// If true tabs are shown in the textarea
207
		/// </value>
208
		[Category("Appearance")]
209
		[DefaultValue(false)]
210
		[Description("If true tabs are shown in the textarea")]
211
		public bool ShowTabs {
212
			get {
213
				return document.TextEditorProperties.ShowTabs;
214
			}
215
			set {
216
				document.TextEditorProperties.ShowTabs = value;
217
				OptionsChanged();
218
			}
219
		}
220
		
221
		/// <value>
222
		/// If true EOL markers are shown in the textarea
223
		/// </value>
224
		[Category("Appearance")]
225
		[DefaultValue(false)]
226
		[Description("If true EOL markers are shown in the textarea")]
227
		public bool ShowEOLMarkers {
228
			get {
229
				return document.TextEditorProperties.ShowEOLMarker;
230
			}
231
			set {
232
				document.TextEditorProperties.ShowEOLMarker = value;
233
				OptionsChanged();
234
			}
235
		}
236
		
237
		/// <value>
238
		/// If true the horizontal ruler is shown in the textarea
239
		/// </value>
240
		[Category("Appearance")]
241
		[DefaultValue(false)]
242
		[Description("If true the horizontal ruler is shown in the textarea")]
243
		public bool ShowHRuler {
244
			get {
245
				return document.TextEditorProperties.ShowHorizontalRuler;
246
			}
247
			set {
248
				document.TextEditorProperties.ShowHorizontalRuler = value;
249
				OptionsChanged();
250
			}
251
		}
252
		
253
		/// <value>
254
		/// If true the vertical ruler is shown in the textarea
255
		/// </value>
256
		[Category("Appearance")]
257
		[DefaultValue(true)]
258
		[Description("If true the vertical ruler is shown in the textarea")]
259
		public bool ShowVRuler {
260
			get {
261
				return document.TextEditorProperties.ShowVerticalRuler;
262
			}
263
			set {
264
				document.TextEditorProperties.ShowVerticalRuler = value;
265
				OptionsChanged();
266
			}
267
		}
268
		
269
		/// <value>
270
		/// The row in which the vertical ruler is displayed
271
		/// </value>
272
		[Category("Appearance")]
273
		[DefaultValue(80)]
274
		[Description("The row in which the vertical ruler is displayed")]
275
		public int VRulerRow {
276
			get {
277
				return document.TextEditorProperties.VerticalRulerRow;
278
			}
279
			set {
280
				document.TextEditorProperties.VerticalRulerRow = value;
281
				OptionsChanged();
282
			}
283
		}
284
		
285
		/// <value>
286
		/// If true line numbers are shown in the textarea
287
		/// </value>
288
		[Category("Appearance")]
289
		[DefaultValue(true)]
290
		[Description("If true line numbers are shown in the textarea")]
291
		public bool ShowLineNumbers {
292
			get {
293
				return document.TextEditorProperties.ShowLineNumbers;
294
			}
295
			set {
296
				document.TextEditorProperties.ShowLineNumbers = value;
297
				OptionsChanged();
298
			}
299
		}
300
		
301
		/// <value>
302
		/// If true invalid lines are marked in the textarea
303
		/// </value>
304
		[Category("Appearance")]
305
		[DefaultValue(false)]
306
		[Description("If true invalid lines are marked in the textarea")]
307
		public bool ShowInvalidLines {
308
			get {
309
				return document.TextEditorProperties.ShowInvalidLines;
310
			}
311
			set {
312
				document.TextEditorProperties.ShowInvalidLines = value;
313
				OptionsChanged();
314
			}
315
		}
316
		
317
		/// <value>
318
		/// If true folding is enabled in the textarea
319
		/// </value>
320
		[Category("Appearance")]
321
		[DefaultValue(true)]
322
		[Description("If true folding is enabled in the textarea")]
323
		public bool EnableFolding {
324
			get {
325
				return document.TextEditorProperties.EnableFolding;
326
			}
327
			set {
328
				document.TextEditorProperties.EnableFolding = value;
329
				OptionsChanged();
330
			}
331
		}
332
		
333
		[Category("Appearance")]
334
		[DefaultValue(true)]
335
		[Description("If true matching brackets are highlighted")]
336
		public bool ShowMatchingBracket {
337
			get {
338
				return document.TextEditorProperties.ShowMatchingBracket;
339
			}
340
			set {
341
				document.TextEditorProperties.ShowMatchingBracket = value;
342
				OptionsChanged();
343
			}
344
		}
345
		
346
		[Category("Appearance")]
347
		[DefaultValue(false)]
348
		[Description("If true the icon bar is displayed")]
349
		public bool IsIconBarVisible {
350
			get {
351
				return document.TextEditorProperties.IsIconBarVisible;
352
			}
353
			set {
354
				document.TextEditorProperties.IsIconBarVisible = value;
355
				OptionsChanged();
356
			}
357
		}
358
		
359
		/// <value>
360
		/// The width in spaces of a tab character
361
		/// </value>
362
		[Category("Appearance")]
363
		[DefaultValue(4)]
364
		[Description("The width in spaces of a tab character")]
365
		public int TabIndent {
366
			get {
367
				return document.TextEditorProperties.TabIndent;
368
			}
369
			set {
370
				document.TextEditorProperties.TabIndent = value;
371
				OptionsChanged();
372
			}
373
		}
374
		
375
		/// <value>
376
		/// The line viewer style
377
		/// </value>
378
		[Category("Appearance")]
379
		[DefaultValue(LineViewerStyle.None)]
380
		[Description("The line viewer style")]
381
		public LineViewerStyle LineViewerStyle {
382
			get {
383
				return document.TextEditorProperties.LineViewerStyle;
384
			}
385
			set {
386
				document.TextEditorProperties.LineViewerStyle = value;
387
				OptionsChanged();
388
			}
389
		}
390
391
		/// <value>
392
		/// The indent style
393
		/// </value>
394
		[Category("Behavior")]
395
		[DefaultValue(IndentStyle.Smart)]
396
		[Description("The indent style")]
397
		public IndentStyle IndentStyle {
398
			get {
399
				return document.TextEditorProperties.IndentStyle;
400
			}
401
			set {
402
				document.TextEditorProperties.IndentStyle = value;
403
				OptionsChanged();
404
			}
405
		}
406
		
407
		/// <value>
408
		/// if true spaces are converted to tabs
409
		/// </value>
410
		[Category("Behavior")]
411
		[DefaultValue(false)]
412
		[Description("Converts tabs to spaces while typing")]
413
		public bool ConvertTabsToSpaces {
414
			get {
415
				return document.TextEditorProperties.ConvertTabsToSpaces;
416
			}
417
			set {
418
				document.TextEditorProperties.ConvertTabsToSpaces = value;
419
				OptionsChanged();
420
			}
421
		}
422
		
423
		/// <value>
424
		/// if true spaces are converted to tabs
425
		/// </value>
426
		[Category("Behavior")]
427
		[DefaultValue(false)]
428
		[Description("Hide the mouse cursor while typing")]
429
		public bool HideMouseCursor {
430
			get {
431
				return document.TextEditorProperties.HideMouseCursor;
432
			}
433
			set {
434
				document.TextEditorProperties.HideMouseCursor = value;
435
				OptionsChanged();
436
			}
437
		}
438
		
439
		/// <value>
440
		/// if true spaces are converted to tabs
441
		/// </value>
442
		[Category("Behavior")]
443
		[DefaultValue(false)]
444
		[Description("Allows the caret to be placed beyond the end of line")]
445
		public bool AllowCaretBeyondEOL {
446
			get {
447
				return document.TextEditorProperties.AllowCaretBeyondEOL;
448
			}
449
			set {
450
				document.TextEditorProperties.AllowCaretBeyondEOL = value;
451
				OptionsChanged();
452
			}
453
		}
454
		/// <value>
455
		/// if true spaces are converted to tabs
456
		/// </value>
457
		[Category("Behavior")]
458
		[DefaultValue(BracketMatchingStyle.After)]
459
		[Description("Specifies if the bracket matching should match the bracket before or after the caret.")]
460
		public BracketMatchingStyle BracketMatchingStyle {
461
			get {
462
				return document.TextEditorProperties.BracketMatchingStyle;
463
			}
464
			set {
465
				document.TextEditorProperties.BracketMatchingStyle = value;
466
				OptionsChanged();
467
			}
468
		}
469
		
470
		/// <value>
471
		/// The base font of the text area. No bold or italic fonts
472
		/// can be used because bold/italic is reserved for highlighting
473
		/// purposes.
474
		/// </value>
475
		[Browsable(true)]
476
		[Description("The base font of the text area. No bold or italic fonts can be used because bold/italic is reserved for highlighting purposes.")]
477
		public override Font Font {
478
			get {
479
				return document.TextEditorProperties.Font;
480
			}
481
			set {
482
				document.TextEditorProperties.Font = value;
483
				OptionsChanged();
484
			}
485
		}
486
		
487
		#endregion
488
		public abstract TextAreaControl ActiveTextAreaControl {
489
			get;
490
		}
491
		
492
		protected TextEditorControlBase()
493
		{
494
			GenerateDefaultActions();
495
			HighlightingManager.Manager.ReloadSyntaxHighlighting += new EventHandler(OnReloadHighlighting);
496
		}
497
		
498
		protected virtual void OnReloadHighlighting(object sender, EventArgs e)
499
		{
500
			if (Document.HighlightingStrategy != null) {
501
				try {
502
					Document.HighlightingStrategy = HighlightingStrategyFactory.CreateHighlightingStrategy(Document.HighlightingStrategy.Name);
503
				} catch (HighlightingDefinitionInvalidException ex) {
504
					MessageBox.Show(ex.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
505
				}
506
				OptionsChanged();
507
			}
508
		}
509
		
510
		public bool IsEditAction(Keys keyData)
511
		{
512
			return editactions.ContainsKey(keyData);
513
		}
514
		
515
		internal IEditAction GetEditAction(Keys keyData)
516
		{
517
			if (!IsEditAction(keyData)) {
518
				return null;
519
			}
520
			return (IEditAction)editactions[keyData];
521
		}
522
523
		void GenerateDefaultActions()
524
		{
525
			editactions[Keys.Left] = new CaretLeft();
526
			editactions[Keys.Left | Keys.Shift] = new ShiftCaretLeft();
527
			editactions[Keys.Left | Keys.Control] = new WordLeft();
528
			editactions[Keys.Left | Keys.Control | Keys.Shift] = new ShiftWordLeft();
529
			editactions[Keys.Right] = new CaretRight();
530
			editactions[Keys.Right | Keys.Shift] = new ShiftCaretRight();
531
			editactions[Keys.Right | Keys.Control] = new WordRight();
532
			editactions[Keys.Right | Keys.Control | Keys.Shift] = new ShiftWordRight();
533
			editactions[Keys.Up] = new CaretUp();
534
			editactions[Keys.Up | Keys.Shift] = new ShiftCaretUp();
535
			editactions[Keys.Up | Keys.Control] = new ScrollLineUp();
536
			editactions[Keys.Down] = new CaretDown();
537
			editactions[Keys.Down | Keys.Shift] = new ShiftCaretDown();
538
			editactions[Keys.Down | Keys.Control] = new ScrollLineDown();
539
			
540
			editactions[Keys.Insert] = new ToggleEditMode();
541
			editactions[Keys.Insert | Keys.Control] = new Copy();
542
			editactions[Keys.Insert | Keys.Shift] = new Paste();
543
			editactions[Keys.Delete] = new Delete();
544
			editactions[Keys.Delete | Keys.Shift] = new Cut();
545
			editactions[Keys.Home] = new Home();
546
			editactions[Keys.Home | Keys.Shift] = new ShiftHome();
547
			editactions[Keys.Home | Keys.Control] = new MoveToStart();
548
			editactions[Keys.Home | Keys.Control | Keys.Shift] = new ShiftMoveToStart();
549
			editactions[Keys.End] = new End();
550
			editactions[Keys.End | Keys.Shift] = new ShiftEnd();
551
			editactions[Keys.End | Keys.Control] = new MoveToEnd();
552
			editactions[Keys.End | Keys.Control | Keys.Shift] = new ShiftMoveToEnd();
553
			editactions[Keys.PageUp] = new MovePageUp();
554
			editactions[Keys.PageUp | Keys.Shift] = new ShiftMovePageUp();
555
			editactions[Keys.PageDown] = new MovePageDown();
556
			editactions[Keys.PageDown | Keys.Shift] = new ShiftMovePageDown();
557
			
558
			editactions[Keys.Return] = new Return();
559
			editactions[Keys.Tab] = new Tab();
560
			editactions[Keys.Tab | Keys.Shift] = new ShiftTab();
561
			editactions[Keys.Back] = new Backspace();
562
			editactions[Keys.Back | Keys.Shift] = new Backspace();
563
			
564
			editactions[Keys.X | Keys.Control] = new Cut();
565
			editactions[Keys.C | Keys.Control] = new Copy();
566
			editactions[Keys.V | Keys.Control] = new Paste();
567
			
568
			editactions[Keys.A | Keys.Control] = new SelectWholeDocument();
569
			editactions[Keys.Escape] = new ClearAllSelections();
570
			
571
			editactions[Keys.Divide | Keys.Control] = new ToggleComment();
572
			editactions[Keys.OemQuestion | Keys.Control] = new ToggleComment();
573
			
574
			editactions[Keys.Back | Keys.Alt]  = new Actions.Undo();
575
			editactions[Keys.Z | Keys.Control] = new Actions.Undo();
576
			editactions[Keys.Y | Keys.Control] = new Redo();
577
			
578
			editactions[Keys.Delete | Keys.Control] = new DeleteWord();
579
			editactions[Keys.Back | Keys.Control]   = new WordBackspace();
580
			editactions[Keys.D | Keys.Control]      = new DeleteLine();
581
			editactions[Keys.D | Keys.Shift | Keys.Control]      = new DeleteToLineEnd();
582
			
583
			editactions[Keys.B | Keys.Control]      = new GotoMatchingBrace();
584
		}
585
		
586
		/// <remarks>
587
		/// Call this method before a long update operation this
588
		/// 'locks' the text area so that no screen update occurs.
589
		/// </remarks>
590
		public virtual void BeginUpdate()
591
		{
592
			++updateLevel;
593
		}
594
		
595
		/// <remarks>
596
		/// Call this method to 'unlock' the text area. After this call
597
		/// screen update can occur. But no automatical refresh occurs you
598
		/// have to commit the updates in the queue.
599
		/// </remarks>
600
		public virtual void EndUpdate()
601
		{
602
			Debug.Assert(updateLevel > 0);
603
			updateLevel = Math.Max(0, updateLevel - 1);
604
		}
605
		
606
		public void LoadFile(string fileName)
607
		{
608
			LoadFile(fileName, true, true);
609
		}
610
		
611
		/// <remarks>
612
		/// Loads a file given by fileName
613
		/// </remarks>
614
		/// <param name="fileName">The name of the file to open</param>
615
		/// <param name="autoLoadHighlighting">Automatically load the highlighting for the file</param>
616
		/// <param name="autodetectEncoding">Automatically detect file encoding and set Encoding property to the detected encoding.</param>
617
		public void LoadFile(string fileName, bool autoLoadHighlighting, bool autodetectEncoding)
618
		{
619
			using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read)) {
620
				LoadFile(fileName, fs, autoLoadHighlighting, autodetectEncoding);
621
			}
622
		}
623
		
624
		/// <remarks>
625
		/// Loads a file from the specified stream.
626
		/// </remarks>
627
		/// <param name="fileName">The name of the file to open. Used to find the correct highlighting strategy
628
		/// if autoLoadHighlighting is active, and sets the filename property to this value.</param>
629
		/// <param name="stream">The stream to actually load the file content from.</param>
630
		/// <param name="autoLoadHighlighting">Automatically load the highlighting for the file</param>
631
		/// <param name="autodetectEncoding">Automatically detect file encoding and set Encoding property to the detected encoding.</param>
632
		public void LoadFile(string fileName, Stream stream, bool autoLoadHighlighting, bool autodetectEncoding)
633
		{
634
			if (stream == null)
635
				throw new ArgumentNullException("stream");
636
			
637
			BeginUpdate();
638
			document.TextContent = String.Empty;
639
			document.UndoStack.ClearAll();
640
			document.BookmarkManager.Clear();
641
			if (autoLoadHighlighting) {
642
				try {
643
					document.HighlightingStrategy = HighlightingStrategyFactory.CreateHighlightingStrategyForFile(fileName);
644
				} catch (HighlightingDefinitionInvalidException ex) {
645
					MessageBox.Show(ex.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
646
				}
647
			}
648
			
649
			if (autodetectEncoding) {
650
				Encoding encoding = this.Encoding;
651
				Document.TextContent = Util.FileReader.ReadFileContent(stream, ref encoding);
652
				this.Encoding = encoding;
653
			} else {
654
				using (StreamReader reader = new StreamReader(fileName, this.Encoding)) {
655
					Document.TextContent = reader.ReadToEnd();
656
				}
657
			}
658
			
659
			this.FileName = fileName;
660
			OptionsChanged();
661
			Document.UpdateQueue.Clear();
662
			EndUpdate();
663
			
664
			Refresh();
665
		}
666
		
667
		/// <summary>
668
		/// Gets if the document can be saved with the current encoding without losing data.
669
		/// </summary>
670
		public bool CanSaveWithCurrentEncoding()
671
		{
672
			if (encoding == null || Util.FileReader.IsUnicode(encoding))
673
				return true;
674
			// not a unicode codepage
675
			string text = document.TextContent;
676
			return encoding.GetString(encoding.GetBytes(text)) == text;
677
		}
678
		
679
		/// <remarks>
680
		/// Saves the text editor content into the file.
681
		/// </remarks>
682
		public void SaveFile(string fileName)
683
		{
684
			using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write)) {
685
				SaveFile(fs);
686
			}
687
			this.FileName = fileName;
688
		}
689
		
690
		/// <remarks>
691
		/// Saves the text editor content into the specified stream.
692
		/// Does not close the stream.
693
		/// </remarks>
694
		public void SaveFile(Stream stream)
695
		{
696
			StreamWriter streamWriter = new StreamWriter(stream, this.Encoding ?? Encoding.UTF8);
697
			
698
			// save line per line to apply the LineTerminator to all lines
699
			// (otherwise we might save files with mixed-up line endings)
700
			foreach (LineSegment line in Document.LineSegmentCollection) {
701
				streamWriter.Write(Document.GetText(line.Offset, line.Length));
702
				if (line.DelimiterLength > 0) {
703
					char charAfterLine = Document.GetCharAt(line.Offset + line.Length);
704
					if (charAfterLine != '\n' && charAfterLine != '\r')
705
						throw new InvalidOperationException("The document cannot be saved because it is corrupted.");
706
					// only save line terminator if the line has one
707
					streamWriter.Write(document.TextEditorProperties.LineTerminator);
708
				}
709
			}
710
			streamWriter.Flush();
711
		}
712
		
713
		public abstract void OptionsChanged();
714
		
715
		// Localization ISSUES
716
		
717
		// used in insight window
718
		public virtual string GetRangeDescription(int selectedItem, int itemCount)
719
		{
720
			StringBuilder sb=new StringBuilder(selectedItem.ToString());
721
			sb.Append(" from ");
722
			sb.Append(itemCount.ToString());
723
			return sb.ToString();
724
		}
725
		
726
		/// <remarks>
727
		/// Overwritten refresh method that does nothing if the control is in
728
		/// an update cycle.
729
		/// </remarks>
730
		public override void Refresh()
731
		{
732
			if (IsInUpdate) {
733
				return;
734
			}
735
			base.Refresh();
736
		}
737
		
738
		protected override void Dispose(bool disposing)
739
		{
740
			if (disposing) {
741
				HighlightingManager.Manager.ReloadSyntaxHighlighting -= new EventHandler(OnReloadHighlighting);
742
				document.HighlightingStrategy = null;
743
				document.UndoStack.TextEditorControl = null;
744
			}
745
			base.Dispose(disposing);
746
		}
747
		
748
		protected virtual void OnFileNameChanged(EventArgs e)
749
		{
750
			if (FileNameChanged != null) {
751
				FileNameChanged(this, e);
752
			}
753
		}
754
		
755
		public event EventHandler FileNameChanged;
756
	}
757
}