Code Coverage Statistics for Source File

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

Sequence Point Coverage
N/A
0 of 0
Branch Coverage
N/A
0 of 0
Lines
948
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: 2683 $</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.Text;
15
using System.Windows.Forms;
16
17
using ICSharpCode.TextEditor.Actions;
18
using ICSharpCode.TextEditor.Document;
19
using ICSharpCode.TextEditor.Gui.CompletionWindow;
20
21
namespace ICSharpCode.TextEditor
22
{
23
	public delegate bool KeyEventHandler(char ch);
24
	public delegate bool DialogKeyProcessor(Keys keyData);
25
	
26
	/// <summary>
27
	/// This class paints the textarea.
28
	/// </summary>
29
	[ToolboxItem(false)]
30
	public class TextArea : Control
31
	{
32
		bool hiddenMouseCursor = false;
33
		/// <summary>
34
		/// The position where the mouse cursor was when it was hidden. Sometimes the text editor gets MouseMove
35
		/// events when typing text even if the mouse is not moved.
36
		/// </summary>
37
		Point mouseCursorHidePosition;
38
		
39
		Point virtualTop        = new Point(0, 0);
40
		TextAreaControl         motherTextAreaControl;
41
		TextEditorControl       motherTextEditorControl;
42
		
43
		List<BracketHighlightingSheme> bracketshemes  = new List<BracketHighlightingSheme>();
44
		TextAreaClipboardHandler  textAreaClipboardHandler;
45
		bool autoClearSelection = false;
46
		
47
		List<AbstractMargin> leftMargins = new List<AbstractMargin>();
48
		
49
		TextView      textView;
50
		GutterMargin  gutterMargin;
51
		FoldMargin    foldMargin;
52
		IconBarMargin iconBarMargin;
53
		
54
		SelectionManager selectionManager;
55
		Caret            caret;
56
57
		internal Point mousepos = new Point(0, 0);
58
		//public Point selectionStartPos = new Point(0,0);
59
60
		bool disposed;
61
		
62
		[Browsable(false)]
63
		public IList<AbstractMargin> LeftMargins {
64
			get {
65
				return leftMargins.AsReadOnly();
66
			}
67
		}
68
		
69
		public void InsertLeftMargin(int index, AbstractMargin margin)
70
		{
71
			leftMargins.Insert(index, margin);
72
			Refresh();
73
		}
74
		
75
		public TextEditorControl MotherTextEditorControl {
76
			get {
77
				return motherTextEditorControl;
78
			}
79
		}
80
		
81
		public TextAreaControl MotherTextAreaControl {
82
			get {
83
				return motherTextAreaControl;
84
			}
85
		}
86
		
87
		public SelectionManager SelectionManager {
88
			get {
89
				return selectionManager;
90
			}
91
		}
92
		
93
		public Caret Caret {
94
			get {
95
				return caret;
96
			}
97
		}
98
		
99
		public TextView TextView {
100
			get {
101
				return textView;
102
			}
103
		}
104
		
105
		public GutterMargin GutterMargin {
106
			get {
107
				return gutterMargin;
108
			}
109
		}
110
		
111
		public FoldMargin FoldMargin {
112
			get {
113
				return foldMargin;
114
			}
115
		}
116
		
117
		public IconBarMargin IconBarMargin {
118
			get {
119
				return iconBarMargin;
120
			}
121
		}
122
		
123
		public Encoding Encoding {
124
			get {
125
				return motherTextEditorControl.Encoding;
126
			}
127
		}
128
		public int MaxVScrollValue {
129
			get {
130
				return (Document.GetVisibleLine(Document.TotalNumberOfLines - 1) + 1 + TextView.VisibleLineCount * 2 / 3) * TextView.FontHeight;
131
			}
132
		}
133
		
134
		public Point VirtualTop {
135
			get {
136
				return virtualTop;
137
			}
138
			set {
139
				Point newVirtualTop = new Point(value.X, Math.Min(MaxVScrollValue, Math.Max(0, value.Y)));
140
				if (virtualTop != newVirtualTop) {
141
					virtualTop = newVirtualTop;
142
					motherTextAreaControl.VScrollBar.Value = virtualTop.Y;
143
					Invalidate();
144
				}
145
			}
146
		}
147
		
148
		public bool AutoClearSelection {
149
			get {
150
				return autoClearSelection;
151
			}
152
			set {
153
				autoClearSelection = value;
154
			}
155
		}
156
		
157
		[Browsable(false)]
158
		public IDocument Document {
159
			get {
160
				return motherTextEditorControl.Document;
161
			}
162
		}
163
		
164
		public TextAreaClipboardHandler ClipboardHandler {
165
			get {
166
				return textAreaClipboardHandler;
167
			}
168
		}
169
		
170
		
171
		public ITextEditorProperties TextEditorProperties {
172
			get {
173
				return motherTextEditorControl.TextEditorProperties;
174
			}
175
		}
176
		
177
		public TextArea(TextEditorControl motherTextEditorControl, TextAreaControl motherTextAreaControl)
178
		{
179
			this.motherTextAreaControl      = motherTextAreaControl;
180
			this.motherTextEditorControl    = motherTextEditorControl;
181
			
182
			caret            = new Caret(this);
183
			selectionManager = new SelectionManager(Document, this);
184
			
185
			this.textAreaClipboardHandler = new TextAreaClipboardHandler(this);
186
			
187
			ResizeRedraw = true;
188
			
189
			SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
190
//			SetStyle(ControlStyles.AllPaintingInWmPaint, true);
191
//			SetStyle(ControlStyles.UserPaint, true);
192
			SetStyle(ControlStyles.Opaque, false);
193
			SetStyle(ControlStyles.ResizeRedraw, true);
194
			SetStyle(ControlStyles.Selectable, true);
195
			
196
			textView = new TextView(this);
197
			
198
			gutterMargin = new GutterMargin(this);
199
			foldMargin   = new FoldMargin(this);
200
			iconBarMargin = new IconBarMargin(this);
201
			leftMargins.AddRange(new AbstractMargin[] { iconBarMargin, gutterMargin, foldMargin });
202
			OptionsChanged();
203
			
204
			
205
			new TextAreaMouseHandler(this).Attach();
206
			new TextAreaDragDropHandler().Attach(this);
207
			
208
			bracketshemes.Add(new BracketHighlightingSheme('{', '}'));
209
			bracketshemes.Add(new BracketHighlightingSheme('(', ')'));
210
			bracketshemes.Add(new BracketHighlightingSheme('[', ']'));
211
			
212
			caret.PositionChanged += new EventHandler(SearchMatchingBracket);
213
			Document.TextContentChanged += new EventHandler(TextContentChanged);
214
			Document.FoldingManager.FoldingsChanged += new EventHandler(DocumentFoldingsChanged);
215
		}
216
		
217
		public void UpdateMatchingBracket()
218
		{
219
			SearchMatchingBracket(null, null);
220
		}
221
		
222
		void TextContentChanged(object sender, EventArgs e)
223
		{
224
			Caret.Position = new TextLocation(0, 0);
225
			SelectionManager.SelectionCollection.Clear();
226
		}
227
		void SearchMatchingBracket(object sender, EventArgs e)
228
		{
229
			if (!TextEditorProperties.ShowMatchingBracket) {
230
				textView.Highlight = null;
231
				return;
232
			}
233
			int oldLine1 = -1, oldLine2 = -1;
234
			if (textView.Highlight != null && textView.Highlight.OpenBrace.Y >=0 && textView.Highlight.OpenBrace.Y < Document.TotalNumberOfLines) {
235
				oldLine1 = textView.Highlight.OpenBrace.Y;
236
			}
237
			if (textView.Highlight != null && textView.Highlight.CloseBrace.Y >=0 && textView.Highlight.CloseBrace.Y < Document.TotalNumberOfLines) {
238
				oldLine2 = textView.Highlight.CloseBrace.Y;
239
			}
240
			textView.Highlight = FindMatchingBracketHighlight();
241
			if (oldLine1 >= 0)
242
				UpdateLine(oldLine1);
243
			if (oldLine2 >= 0 && oldLine2 != oldLine1)
244
				UpdateLine(oldLine2);
245
			if (textView.Highlight != null) {
246
				int newLine1 = textView.Highlight.OpenBrace.Y;
247
				int newLine2 = textView.Highlight.CloseBrace.Y;
248
				if (newLine1 != oldLine1 && newLine1 != oldLine2)
249
					UpdateLine(newLine1);
250
				if (newLine2 != oldLine1 && newLine2 != oldLine2 && newLine2 != newLine1)
251
					UpdateLine(newLine2);
252
			}
253
		}
254
		
255
		public Highlight FindMatchingBracketHighlight()
256
		{
257
			if (Caret.Offset == 0)
258
				return null;
259
			foreach (BracketHighlightingSheme bracketsheme in bracketshemes) {
260
				Highlight highlight = bracketsheme.GetHighlight(Document, Caret.Offset - 1);
261
				if (highlight != null) {
262
					return highlight;
263
				}
264
			}
265
			return null;
266
		}
267
		
268
		public void SetDesiredColumn()
269
		{
270
			Caret.DesiredColumn = TextView.GetDrawingXPos(Caret.Line, Caret.Column) + VirtualTop.X;
271
		}
272
		
273
		public void SetCaretToDesiredColumn()
274
		{
275
			FoldMarker dummy;
276
			Caret.Position = textView.GetLogicalColumn(Caret.Line, Caret.DesiredColumn + VirtualTop.X, out dummy);
277
		}
278
		
279
		public void OptionsChanged()
280
		{
281
			UpdateMatchingBracket();
282
			textView.OptionsChanged();
283
			caret.RecreateCaret();
284
			caret.UpdateCaretPosition();
285
			Refresh();
286
		}
287
		
288
		AbstractMargin lastMouseInMargin;
289
		
290
		protected override void OnMouseLeave(System.EventArgs e)
291
		{
292
			base.OnMouseLeave(e);
293
			this.Cursor = Cursors.Default;
294
			if (lastMouseInMargin != null) {
295
				lastMouseInMargin.HandleMouseLeave(EventArgs.Empty);
296
				lastMouseInMargin = null;
297
			}
298
			CloseToolTip();
299
		}
300
		
301
		protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e)
302
		{
303
			// this corrects weird problems when text is selected,
304
			// then a menu item is selected, then the text is
305
			// clicked again - it correctly synchronises the
306
			// click position
307
			mousepos = new Point(e.X, e.Y);
308
309
			base.OnMouseDown(e);
310
			CloseToolTip();
311
			
312
			foreach (AbstractMargin margin in leftMargins) {
313
				if (margin.DrawingPosition.Contains(e.X, e.Y)) {
314
					margin.HandleMouseDown(new Point(e.X, e.Y), e.Button);
315
				}
316
			}
317
		}
318
		
319
		/// <summary>
320
		/// Shows the mouse cursor if it has been hidden.
321
		/// </summary>
322
		/// <param name="forceShow"><c>true</c> to always show the cursor or <c>false</c> to show it only if it has been moved since it was hidden.</param>
323
		internal void ShowHiddenCursor(bool forceShow)
324
		{
325
			if (hiddenMouseCursor) {
326
				if (mouseCursorHidePosition != Cursor.Position || forceShow) {
327
					Cursor.Show();
328
					hiddenMouseCursor = false;
329
				}
330
			}
331
		}
332
		
333
		
334
		// static because the mouse can only be in one text area and we don't want to have
335
		// tooltips of text areas from inactive tabs floating around.
336
		static DeclarationViewWindow toolTip;
337
		static string oldToolTip;
338
		
339
		void SetToolTip(string text, int lineNumber)
340
		{
341
			if (toolTip == null || toolTip.IsDisposed)
342
				toolTip = new DeclarationViewWindow(this.FindForm());
343
			if (oldToolTip == text)
344
				return;
345
			if (text == null) {
346
				toolTip.Hide();
347
			} else {
348
				Point p = Control.MousePosition;
349
				Point cp = PointToClient(p);
350
				if (lineNumber >= 0) {
351
					lineNumber = this.Document.GetVisibleLine(lineNumber);
352
					p.Y = (p.Y - cp.Y) + (lineNumber * this.TextView.FontHeight) - this.virtualTop.Y;
353
				}
354
				p.Offset(3, 3);
355
				toolTip.Location = p;
356
				toolTip.Description = text;
357
				toolTip.HideOnClick = true;
358
				toolTip.Show();
359
			}
360
			oldToolTip = text;
361
		}
362
		
363
		public event ToolTipRequestEventHandler ToolTipRequest;
364
		
365
		protected virtual void OnToolTipRequest(ToolTipRequestEventArgs e)
366
		{
367
			if (ToolTipRequest != null) {
368
				ToolTipRequest(this, e);
369
			}
370
		}
371
		
372
		bool toolTipActive;
373
		/// <summary>
374
		/// Rectangle in text area that caused the current tool tip.
375
		/// Prevents tooltip from re-showing when it was closed because of a click or keyboard
376
		/// input and the mouse was not used.
377
		/// </summary>
378
		Rectangle toolTipRectangle;
379
		
380
		void CloseToolTip()
381
		{
382
			if (toolTipActive) {
383
				//Console.WriteLine("Closing tooltip");
384
				toolTipActive = false;
385
				SetToolTip(null, -1);
386
			}
387
			ResetMouseEventArgs();
388
		}
389
		
390
		protected override void OnMouseHover(EventArgs e)
391
		{
392
			base.OnMouseHover(e);
393
			//Console.WriteLine("Hover raised at " + PointToClient(Control.MousePosition));
394
			if (MouseButtons == MouseButtons.None) {
395
				RequestToolTip(PointToClient(Control.MousePosition));
396
			} else {
397
				CloseToolTip();
398
			}
399
		}
400
		
401
		protected void RequestToolTip(Point mousePos)
402
		{
403
			if (toolTipRectangle.Contains(mousePos)) {
404
				if (!toolTipActive)
405
					ResetMouseEventArgs();
406
				return;
407
			}
408
			
409
			//Console.WriteLine("Request tooltip for " + mousePos);
410
			
411
			toolTipRectangle = new Rectangle(mousePos.X - 4, mousePos.Y - 4, 8, 8);
412
			
413
			TextLocation logicPos = textView.GetLogicalPosition(mousePos.X - textView.DrawingPosition.Left,
414
			                                                    mousePos.Y - textView.DrawingPosition.Top);
415
			bool inDocument = textView.DrawingPosition.Contains(mousePos)
416
				&& logicPos.Y >= 0 && logicPos.Y < Document.TotalNumberOfLines;
417
			ToolTipRequestEventArgs args = new ToolTipRequestEventArgs(mousePos, logicPos, inDocument);
418
			OnToolTipRequest(args);
419
			if (args.ToolTipShown) {
420
				//Console.WriteLine("Set tooltip to " + args.toolTipText);
421
				toolTipActive = true;
422
				SetToolTip(args.toolTipText, inDocument ? logicPos.Y + 1 : -1);
423
			} else {
424
				CloseToolTip();
425
			}
426
		}
427
		
428
		// external interface to the attached event
429
		internal void RaiseMouseMove(MouseEventArgs e)
430
		{
431
			OnMouseMove(e);
432
		}
433
434
		protected override void OnMouseMove(MouseEventArgs e)
435
		{
436
			base.OnMouseMove(e);
437
			if (!toolTipRectangle.Contains(e.Location)) {
438
				toolTipRectangle = Rectangle.Empty;
439
				if (toolTipActive)
440
					RequestToolTip(e.Location);
441
			}
442
			foreach (AbstractMargin margin in leftMargins) {
443
				if (margin.DrawingPosition.Contains(e.X, e.Y)) {
444
					this.Cursor = margin.Cursor;
445
					margin.HandleMouseMove(new Point(e.X, e.Y), e.Button);
446
					if (lastMouseInMargin != margin) {
447
						if (lastMouseInMargin != null) {
448
							lastMouseInMargin.HandleMouseLeave(EventArgs.Empty);
449
						}
450
						lastMouseInMargin = margin;
451
					}
452
					return;
453
				}
454
			}
455
			if (lastMouseInMargin != null) {
456
				lastMouseInMargin.HandleMouseLeave(EventArgs.Empty);
457
				lastMouseInMargin = null;
458
			}
459
			if (textView.DrawingPosition.Contains(e.X, e.Y)) {
460
				TextLocation realmousepos = TextView.GetLogicalPosition(e.X - TextView.DrawingPosition.X, e.Y - TextView.DrawingPosition.Y);
461
				if(SelectionManager.IsSelected(Document.PositionToOffset(realmousepos)) && MouseButtons == MouseButtons.None) {
462
					// mouse is hovering over a selection, so show default mouse
463
					this.Cursor = Cursors.Default;
464
				} else {
465
					// mouse is hovering over text area, not a selection, so show the textView cursor
466
					this.Cursor = textView.Cursor;
467
				}
468
				return;
469
			}
470
			this.Cursor = Cursors.Default;
471
		}
472
		AbstractMargin updateMargin = null;
473
		
474
		public void Refresh(AbstractMargin margin)
475
		{
476
			updateMargin = margin;
477
			Invalidate(updateMargin.DrawingPosition);
478
			Update();
479
			updateMargin = null;
480
		}
481
		
482
		protected override void OnPaintBackground(System.Windows.Forms.PaintEventArgs pevent)
483
		{
484
		}
485
		
486
		protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
487
		{
488
			int currentXPos = 0;
489
			int currentYPos = 0;
490
			bool adjustScrollBars = false;
491
			Graphics  g             = e.Graphics;
492
			Rectangle clipRectangle = e.ClipRectangle;
493
			
494
			bool isFullRepaint = clipRectangle.X == 0 && clipRectangle.Y == 0
495
				&& clipRectangle.Width == this.Width && clipRectangle.Height == this.Height;
496
			
497
			g.TextRenderingHint = this.TextEditorProperties.TextRenderingHint;
498
			
499
			if (updateMargin != null) {
500
				updateMargin.Paint(g, updateMargin.DrawingPosition);
501
//				clipRectangle.Intersect(updateMargin.DrawingPosition);
502
			}
503
			
504
			if (clipRectangle.Width <= 0 || clipRectangle.Height <= 0) {
505
				return;
506
			}
507
			
508
			foreach (AbstractMargin margin in leftMargins) {
509
				if (margin.IsVisible) {
510
					Rectangle marginRectangle = new Rectangle(currentXPos , currentYPos, margin.Size.Width, Height - currentYPos);
511
					if (marginRectangle != margin.DrawingPosition) {
512
						// margin changed size
513
						if (!isFullRepaint && !clipRectangle.Contains(marginRectangle)) {
514
							Invalidate(); // do a full repaint
515
						}
516
						adjustScrollBars = true;
517
						margin.DrawingPosition = marginRectangle;
518
					}
519
					currentXPos += margin.DrawingPosition.Width;
520
					if (clipRectangle.IntersectsWith(marginRectangle)) {
521
						marginRectangle.Intersect(clipRectangle);
522
						if (!marginRectangle.IsEmpty) {
523
							margin.Paint(g, marginRectangle);
524
						}
525
					}
526
				}
527
			}
528
			
529
			Rectangle textViewArea = new Rectangle(currentXPos, currentYPos, Width - currentXPos, Height - currentYPos);
530
			if (textViewArea != textView.DrawingPosition) {
531
				adjustScrollBars = true;
532
				textView.DrawingPosition = textViewArea;
533
			}
534
			if (clipRectangle.IntersectsWith(textViewArea)) {
535
				textViewArea.Intersect(clipRectangle);
536
				if (!textViewArea.IsEmpty) {
537
					textView.Paint(g, textViewArea);
538
				}
539
			}
540
			
541
			if (adjustScrollBars) {
542
				this.motherTextAreaControl.AdjustScrollBars();
543
			}
544
			
545
			Caret.UpdateCaretPosition();
546
			
547
			base.OnPaint(e);
548
		}
549
		void DocumentFoldingsChanged(object sender, EventArgs e)
550
		{
551
			Invalidate();
552
			this.motherTextAreaControl.AdjustScrollBars();
553
		}
554
		
555
		#region keyboard handling methods
556
		
557
		/// <summary>
558
		/// This method is called on each Keypress
559
		/// </summary>
560
		/// <returns>
561
		/// True, if the key is handled by this method and should NOT be
562
		/// inserted in the textarea.
563
		/// </returns>
564
		protected internal virtual bool HandleKeyPress(char ch)
565
		{
566
			if (KeyEventHandler != null) {
567
				return KeyEventHandler(ch);
568
			}
569
			return false;
570
		}
571
		
572
		// Fixes SD2-747: Form containing the text editor and a button with a shortcut
573
		protected override bool IsInputChar(char charCode)
574
		{
575
			return true;
576
		}
577
		
578
		public void SimulateKeyPress(char ch)
579
		{
580
			if (Document.ReadOnly) {
581
				return;
582
			}
583
			
584
			if (TextEditorProperties.UseCustomLine == true) {
585
				if (SelectionManager.HasSomethingSelected) {
586
					if (SelectionManager.SelectionIsReadonly)
587
						return;
588
				} else if (Document.CustomLineManager.IsReadOnly(Caret.Line, false) == true)
589
					return;
590
			}
591
			
592
			if (ch < ' ') {
593
				return;
594
			}
595
			
596
			if (!hiddenMouseCursor && TextEditorProperties.HideMouseCursor) {
597
				if (this.ClientRectangle.Contains(PointToClient(Cursor.Position))) {
598
					mouseCursorHidePosition = Cursor.Position;
599
					hiddenMouseCursor = true;
600
					Cursor.Hide();
601
				}
602
			}
603
			CloseToolTip();
604
			
605
			motherTextEditorControl.BeginUpdate();
606
			Document.UndoStack.StartUndoGroup();
607
			// INSERT char
608
			if (!HandleKeyPress(ch)) {
609
				switch (Caret.CaretMode) {
610
					case CaretMode.InsertMode:
611
						InsertChar(ch);
612
						break;
613
					case CaretMode.OverwriteMode:
614
						ReplaceChar(ch);
615
						break;
616
					default:
617
						Debug.Assert(false, "Unknown caret mode " + Caret.CaretMode);
618
						break;
619
				}
620
			}
621
			
622
			int currentLineNr = Caret.Line;
623
			Document.FormattingStrategy.FormatLine(this, currentLineNr, Document.PositionToOffset(Caret.Position), ch);
624
			
625
			motherTextEditorControl.EndUpdate();
626
			Document.UndoStack.EndUndoGroup();
627
		}
628
		
629
		protected override void OnKeyPress(KeyPressEventArgs e)
630
		{
631
			base.OnKeyPress(e);
632
			SimulateKeyPress(e.KeyChar);
633
			e.Handled = true;
634
		}
635
		
636
		/// <summary>
637
		/// This method executes a dialog key
638
		/// </summary>
639
		public bool ExecuteDialogKey(Keys keyData)
640
		{
641
			// try, if a dialog key processor was set to use this
642
			if (DoProcessDialogKey != null && DoProcessDialogKey(keyData)) {
643
				return true;
644
			}
645
			
646
			if (keyData == Keys.Back || keyData == Keys.Delete || keyData == Keys.Enter) {
647
				if (TextEditorProperties.UseCustomLine == true) {
648
					if (SelectionManager.HasSomethingSelected) {
649
						if (SelectionManager.SelectionIsReadonly)
650
							return true;
651
					} else {
652
						int curLineNr   = Document.GetLineNumberForOffset(Caret.Offset);
653
						if (Document.CustomLineManager.IsReadOnly(curLineNr, false) == true)
654
							return true;
655
						if ((Caret.Column == 0) && (curLineNr - 1 >= 0) && keyData == Keys.Back &&
656
						    Document.CustomLineManager.IsReadOnly(curLineNr - 1, false) == true)
657
							return true;
658
						if (keyData == Keys.Delete) {
659
							LineSegment curLine = Document.GetLineSegment(curLineNr);
660
							if (curLine.Offset + curLine.Length == Caret.Offset &&
661
							    Document.CustomLineManager.IsReadOnly(curLineNr + 1, false) == true) {
662
								return true;
663
							}
664
						}
665
					}
666
				}
667
			}
668
			
669
			// if not (or the process was 'silent', use the standard edit actions
670
			IEditAction action =  motherTextEditorControl.GetEditAction(keyData);
671
			AutoClearSelection = true;
672
			if (action != null) {
673
				motherTextEditorControl.BeginUpdate();
674
				try {
675
					lock (Document) {
676
						action.Execute(this);
677
						if (SelectionManager.HasSomethingSelected && AutoClearSelection /*&& caretchanged*/) {
678
							if (Document.TextEditorProperties.DocumentSelectionMode == DocumentSelectionMode.Normal) {
679
								SelectionManager.ClearSelection();
680
							}
681
						}
682
					}
683
				} finally {
684
					motherTextEditorControl.EndUpdate();
685
					Caret.UpdateCaretPosition();
686
				}
687
				return true;
688
			}
689
			return false;
690
		}
691
		
692
		protected override bool ProcessDialogKey(Keys keyData)
693
		{
694
			return ExecuteDialogKey(keyData) || base.ProcessDialogKey(keyData);
695
		}
696
		#endregion
697
		
698
		public void ScrollToCaret()
699
		{
700
			motherTextAreaControl.ScrollToCaret();
701
		}
702
		
703
		public void ScrollTo(int line)
704
		{
705
			motherTextAreaControl.ScrollTo(line);
706
		}
707
		
708
		public void BeginUpdate()
709
		{
710
			motherTextEditorControl.BeginUpdate();
711
		}
712
		
713
		public void EndUpdate()
714
		{
715
			motherTextEditorControl.EndUpdate();
716
		}
717
		
718
		public bool EnableCutOrPaste {
719
			get {
720
				if (motherTextAreaControl == null)
721
					return false;
722
				if (TextEditorProperties.UseCustomLine == true) {
723
					if (SelectionManager.HasSomethingSelected == true) {
724
						if (SelectionManager.SelectionIsReadonly)
725
							return false;
726
					}
727
					if (Document.CustomLineManager.IsReadOnly(Caret.Line, false) == true)
728
						return false;
729
				}
730
				return true;
731
				
732
			}
733
		}
734
		
735
		string GenerateWhitespaceString(int length)
736
		{
737
			return new String(' ', length);
738
		}
739
		/// <remarks>
740
		/// Inserts a single character at the caret position
741
		/// </remarks>
742
		public void InsertChar(char ch)
743
		{
744
			bool updating = motherTextEditorControl.IsInUpdate;
745
			if (!updating) {
746
				BeginUpdate();
747
			}
748
			
749
			// filter out forgein whitespace chars and replace them with standard space (ASCII 32)
750
			if (Char.IsWhiteSpace(ch) && ch != '\t' && ch != '\n') {
751
				ch = ' ';
752
			}
753
			
754
			Document.UndoStack.StartUndoGroup();
755
			if (Document.TextEditorProperties.DocumentSelectionMode == DocumentSelectionMode.Normal &&
756
			    SelectionManager.SelectionCollection.Count > 0) {
757
				Caret.Position = SelectionManager.SelectionCollection[0].StartPosition;
758
				SelectionManager.RemoveSelectedText();
759
			}
760
			LineSegment caretLine = Document.GetLineSegment(Caret.Line);
761
			int offset = Caret.Offset;
762
			// use desired column for generated whitespaces
763
			int dc=Math.Min(Caret.Column,Caret.DesiredColumn);
764
			if (caretLine.Length < dc && ch != '\n') {
765
				Document.Insert(offset, GenerateWhitespaceString(dc - caretLine.Length) + ch);
766
			} else {
767
				Document.Insert(offset, ch.ToString());
768
			}
769
			Document.UndoStack.EndUndoGroup();
770
			++Caret.Column;
771
			
772
			if (!updating) {
773
				EndUpdate();
774
				UpdateLineToEnd(Caret.Line, Caret.Column);
775
			}
776
			
777
			// I prefer to set NOT the standard column, if you type something
778
//			++Caret.DesiredColumn;
779
		}
780
		
781
		/// <remarks>
782
		/// Inserts a whole string at the caret position
783
		/// </remarks>
784
		public void InsertString(string str)
785
		{
786
			bool updating = motherTextEditorControl.IsInUpdate;
787
			if (!updating) {
788
				BeginUpdate();
789
			}
790
			try {
791
				Document.UndoStack.StartUndoGroup();
792
				if (Document.TextEditorProperties.DocumentSelectionMode == DocumentSelectionMode.Normal &&
793
				    SelectionManager.SelectionCollection.Count > 0) {
794
					Caret.Position = SelectionManager.SelectionCollection[0].StartPosition;
795
					SelectionManager.RemoveSelectedText();
796
				}
797
				
798
				int oldOffset = Document.PositionToOffset(Caret.Position);
799
				int oldLine   = Caret.Line;
800
				LineSegment caretLine = Document.GetLineSegment(Caret.Line);
801
				if (caretLine.Length < Caret.Column) {
802
					int whiteSpaceLength = Caret.Column - caretLine.Length;
803
					Document.Insert(oldOffset, GenerateWhitespaceString(whiteSpaceLength) + str);
804
					Caret.Position = Document.OffsetToPosition(oldOffset + str.Length + whiteSpaceLength);
805
				} else {
806
					Document.Insert(oldOffset, str);
807
					Caret.Position = Document.OffsetToPosition(oldOffset + str.Length);
808
				}
809
				Document.UndoStack.EndUndoGroup();
810
				if (oldLine != Caret.Line) {
811
					UpdateToEnd(oldLine);
812
				} else {
813
					UpdateLineToEnd(Caret.Line, Caret.Column);
814
				}
815
			} finally {
816
				if (!updating) {
817
					EndUpdate();
818
				}
819
			}
820
		}
821
		
822
		/// <remarks>
823
		/// Replaces a char at the caret position
824
		/// </remarks>
825
		public void ReplaceChar(char ch)
826
		{
827
			bool updating = motherTextEditorControl.IsInUpdate;
828
			if (!updating) {
829
				BeginUpdate();
830
			}
831
			if (Document.TextEditorProperties.DocumentSelectionMode == DocumentSelectionMode.Normal && SelectionManager.SelectionCollection.Count > 0) {
832
				Caret.Position = SelectionManager.SelectionCollection[0].StartPosition;
833
				SelectionManager.RemoveSelectedText();
834
			}
835
			
836
			int lineNr   = Caret.Line;
837
			LineSegment  line = Document.GetLineSegment(lineNr);
838
			int offset = Document.PositionToOffset(Caret.Position);
839
			if (offset < line.Offset + line.Length) {
840
				Document.Replace(offset, 1, ch.ToString());
841
			} else {
842
				Document.Insert(offset, ch.ToString());
843
			}
844
			if (!updating) {
845
				EndUpdate();
846
				UpdateLineToEnd(lineNr, Caret.Column);
847
			}
848
			++Caret.Column;
849
//			++Caret.DesiredColumn;
850
		}
851
		
852
		protected override void Dispose(bool disposing)
853
		{
854
			base.Dispose(disposing);
855
			if (disposing) {
856
				if (!disposed) {
857
					disposed = true;
858
					if (caret != null) {
859
						caret.PositionChanged -= new EventHandler(SearchMatchingBracket);
860
						caret.Dispose();
861
					}
862
					if (selectionManager != null) {
863
						selectionManager.Dispose();
864
					}
865
					Document.TextContentChanged -= new EventHandler(TextContentChanged);
866
					Document.FoldingManager.FoldingsChanged -= new EventHandler(DocumentFoldingsChanged);
867
					motherTextAreaControl = null;
868
					motherTextEditorControl = null;
869
					foreach (AbstractMargin margin in leftMargins) {
870
						if (margin is IDisposable)
871
							(margin as IDisposable).Dispose();
872
					}
873
					textView.Dispose();
874
				}
875
			}
876
		}
877
		
878
		#region UPDATE Commands
879
		internal void UpdateLine(int line)
880
		{
881
			UpdateLines(0, line, line);
882
		}
883
		
884
		internal void UpdateLines(int lineBegin, int lineEnd)
885
		{
886
			UpdateLines(0, lineBegin, lineEnd);
887
		}
888
		
889
		internal void UpdateToEnd(int lineBegin)
890
		{
891
//			if (lineBegin > FirstPhysicalLine + textView.VisibleLineCount) {
892
//				return;
893
//			}
894
			
895
			lineBegin = Document.GetVisibleLine(lineBegin);
896
			int y         = Math.Max(    0, (int)(lineBegin * textView.FontHeight));
897
			y = Math.Max(0, y - this.virtualTop.Y);
898
			Rectangle r = new Rectangle(0,
899
			                            y,
900
			                            Width,
901
			                            Height - y);
902
			Invalidate(r);
903
		}
904
		
905
		internal void UpdateLineToEnd(int lineNr, int xStart)
906
		{
907
			UpdateLines(xStart, lineNr, lineNr);
908
		}
909
		
910
		internal void UpdateLine(int line, int begin, int end)
911
		{
912
			UpdateLines(line, line);
913
		}
914
		int FirstPhysicalLine {
915
			get {
916
				return VirtualTop.Y / textView.FontHeight;
917
			}
918
		}
919
		internal void UpdateLines(int xPos, int lineBegin, int lineEnd)
920
		{
921
//			if (lineEnd < FirstPhysicalLine || lineBegin > FirstPhysicalLine + textView.VisibleLineCount) {
922
//				return;
923
//			}
924
			
925
			InvalidateLines((int)(xPos * this.TextView.WideSpaceWidth), lineBegin, lineEnd);
926
		}
927
		
928
		void InvalidateLines(int xPos, int lineBegin, int lineEnd)
929
		{
930
			lineBegin     = Math.Max(Document.GetVisibleLine(lineBegin), FirstPhysicalLine);
931
			lineEnd       = Math.Min(Document.GetVisibleLine(lineEnd),   FirstPhysicalLine + textView.VisibleLineCount);
932
			int y         = Math.Max(    0, (int)(lineBegin  * textView.FontHeight));
933
			int height    = Math.Min(textView.DrawingPosition.Height, (int)((1 + lineEnd - lineBegin) * (textView.FontHeight + 1)));
934
			
935
			Rectangle r = new Rectangle(0,
936
			                            y - 1 - this.virtualTop.Y,
937
			                            Width,
938
			                            height + 3);
939
			
940
			Invalidate(r);
941
		}
942
		#endregion
943
		public event KeyEventHandler    KeyEventHandler;
944
		public event DialogKeyProcessor DoProcessDialogKey;
945
		
946
		//internal void
947
	}
948
}