1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2004-2006 Novell, Inc. (http://www.novell.com)
23 // Peter Bartok pbartok@novell.com
31 using System.ComponentModel;
32 using System.ComponentModel.Design;
34 using System.Drawing.Text;
36 using System.Runtime.InteropServices;
37 using System.Collections;
39 namespace System.Windows.Forms {
40 [DefaultEvent("TextChanged")]
41 [Designer("System.Windows.Forms.Design.TextBoxBaseDesigner, " + Consts.AssemblySystem_Design)]
42 public abstract class TextBoxBase : Control {
43 #region Local Variables
44 internal HorizontalAlignment alignment;
45 internal bool accepts_tab;
46 internal bool accepts_return;
47 internal bool auto_size;
48 internal bool backcolor_set;
49 internal CharacterCasing character_casing;
50 internal bool hide_selection;
51 internal int max_length;
52 internal bool modified;
53 internal char password_char;
54 internal bool read_only;
55 internal bool word_wrap;
56 internal Document document;
57 internal LineTag caret_tag; // tag our cursor is in
58 internal int caret_pos; // position on the line our cursor is in (can be 0 = beginning of line)
59 internal ImplicitHScrollBar hscroll;
60 internal ImplicitVScrollBar vscroll;
61 internal RichTextBoxScrollBars scrollbars;
62 internal Timer scroll_timer;
63 internal bool richtext;
64 internal bool show_selection; // set to true to always show selection, even if no focus is set
65 internal int selection_length = -1; // set to the user-specified selection length, or -1 if none
66 internal bool show_caret_w_selection; // TextBox shows the caret when the selection is visible
67 internal int requested_height;
68 internal int canvas_width;
69 internal int canvas_height;
70 static internal int track_width = 2; //
71 static internal int track_border = 5; //
72 internal DateTime click_last;
73 internal int click_point_x;
74 internal int click_point_y;
75 internal CaretSelection click_mode;
77 internal BorderStyle actual_border_style;
78 internal bool shortcuts_enabled = true;
80 internal static bool draw_lines = false;
83 #endregion // Local Variables
85 #region Internal Constructor
86 // Constructor will go when complete, only for testing - pdb
87 internal TextBoxBase() {
88 alignment = HorizontalAlignment.Left;
89 accepts_return = false;
92 border_style = BorderStyle.Fixed3D;
93 actual_border_style = BorderStyle.Fixed3D;
94 character_casing = CharacterCasing.Normal;
95 hide_selection = true;
102 show_selection = false;
103 show_caret_w_selection = (this is TextBox);
104 document = new Document(this);
105 document.WidthChanged += new EventHandler(document_WidthChanged);
106 document.HeightChanged += new EventHandler(document_HeightChanged);
107 //document.CaretMoved += new EventHandler(CaretMoved);
108 document.Wrap = false;
109 requested_height = -1;
110 click_last = DateTime.Now;
111 click_mode = CaretSelection.Position;
112 bmp = new Bitmap(1, 1, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
114 MouseDown += new MouseEventHandler(TextBoxBase_MouseDown);
115 MouseUp += new MouseEventHandler(TextBoxBase_MouseUp);
116 MouseMove += new MouseEventHandler(TextBoxBase_MouseMove);
117 SizeChanged += new EventHandler(TextBoxBase_SizeChanged);
118 FontChanged += new EventHandler(TextBoxBase_FontOrColorChanged);
119 ForeColorChanged += new EventHandler(TextBoxBase_FontOrColorChanged);
120 MouseWheel += new MouseEventHandler(TextBoxBase_MouseWheel);
122 scrollbars = RichTextBoxScrollBars.None;
124 hscroll = new ImplicitHScrollBar();
125 hscroll.ValueChanged += new EventHandler(hscroll_ValueChanged);
126 hscroll.SetStyle (ControlStyles.Selectable, false);
127 hscroll.Enabled = false;
128 hscroll.Visible = false;
129 hscroll.Maximum = Int32.MaxValue;
131 vscroll = new ImplicitVScrollBar();
132 vscroll.ValueChanged += new EventHandler(vscroll_ValueChanged);
133 vscroll.SetStyle (ControlStyles.Selectable, false);
134 vscroll.Enabled = false;
135 vscroll.Visible = false;
136 vscroll.Maximum = Int32.MaxValue;
139 this.Controls.AddImplicit (hscroll);
140 this.Controls.AddImplicit (vscroll);
143 SetStyle(ControlStyles.UserPaint | ControlStyles.StandardClick, false);
145 SetStyle(ControlStyles.UseTextForAccessibility, false);
148 canvas_width = ClientSize.Width;
149 canvas_height = ClientSize.Height;
150 document.ViewPortWidth = canvas_width;
151 document.ViewPortHeight = canvas_height;
153 Cursor = Cursors.IBeam;
155 CalculateScrollBars();
157 #endregion // Internal Constructor
159 #region Private and Internal Methods
160 internal string CaseAdjust(string s) {
161 if (character_casing == CharacterCasing.Normal) {
164 if (character_casing == CharacterCasing.Lower) {
171 internal override void HandleClick(int clicks, MouseEventArgs me) {
172 // MS seems to fire the click event in spite of the styles they set
173 bool click_set = GetStyle (ControlStyles.StandardClick);
174 bool doubleclick_set = GetStyle (ControlStyles.StandardDoubleClick);
176 // so explicitly set them to true first
177 SetStyle (ControlStyles.StandardClick | ControlStyles.StandardDoubleClick, true);
179 base.HandleClick (clicks, me);
181 // then revert to our previous state
183 SetStyle (ControlStyles.StandardClick, false);
184 if (!doubleclick_set)
185 SetStyle (ControlStyles.StandardDoubleClick, false);
188 #endregion // Private and Internal Methods
190 #region Public Instance Properties
191 [DefaultValue(false)]
192 [MWFCategory("Behavior")]
193 public bool AcceptsTab {
199 if (value != accepts_tab) {
201 OnAcceptsTabChanged(EventArgs.Empty);
208 [RefreshProperties(RefreshProperties.Repaint)]
209 [MWFCategory("Behavior")]
222 if (value != auto_size) {
225 if (PreferredHeight != ClientSize.Height) {
226 ClientSize = new Size(ClientSize.Width, PreferredHeight);
229 OnAutoSizeChanged(EventArgs.Empty);
235 public override System.Drawing.Color BackColor {
237 return base.BackColor;
240 backcolor_set = true;
241 base.BackColor = value;
246 [EditorBrowsable(EditorBrowsableState.Never)]
247 public override System.Drawing.Image BackgroundImage {
249 return base.BackgroundImage;
252 base.BackgroundImage = value;
256 [DefaultValue(BorderStyle.Fixed3D)]
258 [MWFCategory("Appearance")]
259 public BorderStyle BorderStyle {
260 get { return actual_border_style; }
262 if (value == actual_border_style)
265 if (actual_border_style != BorderStyle.Fixed3D || value != BorderStyle.Fixed3D)
268 actual_border_style = value;
269 if (value != BorderStyle.Fixed3D)
270 value = BorderStyle.None;
272 InternalBorderStyle = value;
273 OnBorderStyleChanged(EventArgs.Empty);
278 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
279 public bool CanUndo {
281 return document.undo.CanUndo;
286 public override System.Drawing.Color ForeColor {
288 return base.ForeColor;
291 base.ForeColor = value;
296 [MWFCategory("Behavior")]
297 public bool HideSelection {
299 return hide_selection;
303 if (value != hide_selection) {
304 hide_selection = value;
305 OnHideSelectionChanged(EventArgs.Empty);
307 if (hide_selection) {
308 document.selection_visible = false;
310 document.selection_visible = true;
312 document.InvalidateSelectionArea();
317 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
318 [Editor("System.Windows.Forms.Design.StringArrayEditor, " + Consts.AssemblySystem_Design, typeof(System.Drawing.Design.UITypeEditor))]
320 [MWFCategory("Appearance")]
321 public string[] Lines {
326 count = document.Lines;
328 // Handle empty document
329 if ((count == 1) && (document.GetLine (1).text.Length == 0)) {
330 return new string [0];
333 lines = new ArrayList ();
338 StringBuilder lt = new StringBuilder ();
341 line = document.GetLine (i++);
342 lt.Append (line.TextWithoutEnding ());
343 } while (line.ending == LineEnding.Wrap && i <= count);
345 lines.Add (lt.ToString ());
348 return (string []) lines.ToArray (typeof (string));
359 brush = ThemeEngine.Current.ResPool.GetSolidBrush(this.ForeColor);
361 document.SuspendRecalc ();
362 for (i = 0; i < l; i++) {
364 // Don't add the last line if it is just an empty line feed
365 // the line feed is reflected in the previous line's ending
366 if (i == l - 1 && value [i].Length == 0)
369 LineEnding ending = LineEnding.Rich;
370 if (value [i].EndsWith ("\r"))
371 ending = LineEnding.Hard;
373 document.Add (i + 1, CaseAdjust (value [i]), alignment, Font, brush, ending);
376 document.ResumeRecalc (true);
378 // CalculateDocument();
379 OnTextChanged(EventArgs.Empty);
383 [DefaultValue(32767)]
385 [MWFCategory("Behavior")]
386 public virtual int MaxLength {
388 if (max_length == 2147483646) { // We don't distinguish between single and multi-line limits
395 if (value != max_length) {
402 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
403 public bool Modified {
409 if (value != modified) {
411 OnModifiedChanged(EventArgs.Empty);
416 [DefaultValue(false)]
418 [RefreshProperties(RefreshProperties.All)]
419 [MWFCategory("Behavior")]
420 public virtual bool Multiline {
422 return document.multiline;
426 if (value != document.multiline) {
427 document.multiline = value;
428 // Make sure we update our size; the user may have already set the size before going to multiline
429 if (document.multiline && requested_height != -1) {
430 Height = requested_height;
431 requested_height = -1;
435 Parent.PerformLayout ();
437 OnMultilineChanged(EventArgs.Empty);
440 if (document.multiline) {
441 document.Wrap = word_wrap;
442 document.PasswordChar = "";
445 document.Wrap = false;
446 if (this.password_char != '\0') {
447 document.PasswordChar = password_char.ToString();
449 document.PasswordChar = "";
454 CalculateDocument ();
459 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
460 [EditorBrowsable(EditorBrowsableState.Advanced)]
461 public int PreferredHeight {
463 return Font.Height + (BorderStyle != BorderStyle.Fixed3D ? 0 : 7);
467 [DefaultValue(false)]
468 [MWFCategory("Behavior")]
469 public bool ReadOnly {
475 if (value != read_only) {
478 if (!backcolor_set) {
480 background_color = SystemColors.Control;
482 background_color = SystemColors.Window;
485 OnReadOnlyChanged(EventArgs.Empty);
492 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
493 public virtual string SelectedText {
495 return document.GetSelection();
499 document.ReplaceSelection(CaseAdjust(value), false);
502 OnTextChanged(EventArgs.Empty);
507 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
508 public virtual int SelectionLength {
510 int res = document.SelectionLength ();
518 throw new ArgumentException(String.Format("{0} is not a valid value", value), "value");
527 selection_length = value;
529 start = document.LineTagToCharIndex(document.selection_start.line, document.selection_start.pos);
531 document.CharIndexToLineTag(start + value, out line, out tag, out pos);
532 document.SetSelectionEnd(line, pos, true);
533 document.PositionCaret(line, pos);
535 selection_length = -1;
537 document.SetSelectionEnd(document.selection_start.line, document.selection_start.pos, true);
538 document.PositionCaret(document.selection_start.line, document.selection_start.pos);
544 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
545 public int SelectionStart {
549 index = document.LineTagToCharIndex(document.selection_start.line, document.selection_start.pos);
555 document.SetSelectionStart(value, false);
556 if (selection_length > -1 ) {
557 document.SetSelectionEnd(value + selection_length, true);
559 document.SetSelectionEnd(value, true);
561 document.PositionCaret(document.selection_start.line, document.selection_start.pos);
567 public virtual bool ShortcutsEnabled {
568 get { return shortcuts_enabled; }
569 set { shortcuts_enabled = value; }
574 public override string Text {
576 if (document == null || document.Root == null || document.Root.text == null) {
580 StringBuilder sb = new StringBuilder();
583 for (int i = 1; i <= document.Lines; i++) {
584 line = document.GetLine (i);
585 sb.Append(line.text.ToString ());
588 return sb.ToString();
595 if ((value != null) && (value != "")) {
599 document.Insert (document.GetLine (1), 0, false, value);
601 document.PositionCaret (document.GetLine (1), 0);
602 document.SetSelectionToCaret (true);
608 CalculateDocument ();
611 // set the var so OnModifiedChanged is not raised
613 OnTextChanged(EventArgs.Empty);
618 public virtual int TextLength {
620 if (document == null || document.Root == null || document.Root.text == null) {
629 [MWFCategory("Behavior")]
630 public bool WordWrap {
636 if (value != word_wrap) {
637 if (document.multiline) {
639 document.Wrap = value;
644 #endregion // Public Instance Properties
646 #region Protected Instance Properties
647 protected override CreateParams CreateParams {
649 return base.CreateParams;
653 protected override System.Drawing.Size DefaultSize {
655 return new Size(100, 20);
658 #endregion // Protected Instance Properties
660 #region Public Instance Methods
661 public void AppendText(string text) {
662 document.MoveCaret (CaretDirection.CtrlEnd);
663 document.Insert (document.caret.line, document.caret.pos, false, text);
664 document.MoveCaret (CaretDirection.CtrlEnd);
665 document.SetSelectionToCaret (true);
667 OnTextChanged(EventArgs.Empty);
670 public void Clear() {
674 public void ClearUndo() {
675 document.undo.Clear();
681 o = new DataObject(DataFormats.Text, SelectedText);
682 if (this is RichTextBox) {
683 o.SetData(DataFormats.Rtf, ((RichTextBox)this).SelectedRtf);
685 Clipboard.SetDataObject(o);
691 o = new DataObject(DataFormats.Text, SelectedText);
692 if (this is RichTextBox) {
693 o.SetData(DataFormats.Rtf, ((RichTextBox)this).SelectedRtf);
695 Clipboard.SetDataObject (o);
697 document.undo.BeginUserAction (Locale.GetText ("Cut"));
698 document.ReplaceSelection (String.Empty, false);
699 document.undo.EndUserAction ();
702 public void Paste() {
703 Paste(Clipboard.GetDataObject(), null, false);
706 public void ScrollToCaret() {
707 if (IsHandleCreated) {
708 CaretMoved(this, EventArgs.Empty);
712 public void Select(int start, int length) {
713 SelectionStart = start;
714 SelectionLength = length;
718 public void SelectAll() {
721 last = document.GetLine(document.Lines);
722 document.SetSelectionStart(document.GetLine(1), 0, false);
723 document.SetSelectionEnd(last, last.text.Length, true);
724 document.PositionCaret (document.selection_end.line, document.selection_end.pos);
725 selection_length = -1;
727 CaretMoved (this, null);
729 document.DisplayCaret ();
732 /// Sync with above (except the invalidation of course)
733 internal void SelectAllNoInvalidate ()
737 last = document.GetLine(document.Lines);
738 document.SetSelectionStart(document.GetLine(1), 0, false);
739 document.SetSelectionEnd(last, last.text.Length, false);
740 document.PositionCaret (document.selection_end.line, document.selection_end.pos);
741 selection_length = -1;
744 public override string ToString() {
745 return String.Concat (base.ToString (), ", Text: ", Text);
749 document.undo.Undo();
751 #endregion // Public Instance Methods
753 #region Protected Instance Methods
754 protected override void CreateHandle() {
755 CalculateDocument ();
756 base.CreateHandle ();
757 document.AlignCaret();
761 protected override bool IsInputKey(Keys keyData) {
762 if ((keyData & Keys.Alt) != 0) {
763 return base.IsInputKey(keyData);
766 switch (keyData & Keys.KeyCode) {
768 if (accepts_return) {
775 if (accepts_tab && document.multiline) {
776 if ((keyData & Keys.Control) == 0) {
798 protected virtual void OnAcceptsTabChanged(EventArgs e) {
799 EventHandler eh = (EventHandler)(Events [AcceptsTabChangedEvent]);
804 protected virtual void OnAutoSizeChanged(EventArgs e) {
805 EventHandler eh = (EventHandler)(Events [AutoSizeChangedEvent]);
810 protected virtual void OnBorderStyleChanged(EventArgs e) {
811 EventHandler eh = (EventHandler)(Events [BorderStyleChangedEvent]);
816 protected override void OnFontChanged(EventArgs e) {
817 base.OnFontChanged (e);
819 if (auto_size && !document.multiline) {
820 if (PreferredHeight != ClientSize.Height) {
821 Height = PreferredHeight;
826 protected override void OnHandleCreated(EventArgs e) {
827 base.OnHandleCreated (e);
830 protected override void OnHandleDestroyed(EventArgs e) {
831 base.OnHandleDestroyed (e);
834 protected virtual void OnHideSelectionChanged(EventArgs e) {
835 EventHandler eh = (EventHandler)(Events [HideSelectionChangedEvent]);
840 protected virtual void OnModifiedChanged(EventArgs e) {
841 EventHandler eh = (EventHandler)(Events [ModifiedChangedEvent]);
846 protected virtual void OnMultilineChanged(EventArgs e) {
847 EventHandler eh = (EventHandler)(Events [MultilineChangedEvent]);
852 protected virtual void OnReadOnlyChanged(EventArgs e) {
853 EventHandler eh = (EventHandler)(Events [ReadOnlyChangedEvent]);
858 protected override bool ProcessDialogKey(Keys keyData) {
859 return base.ProcessDialogKey(keyData);
862 private bool ProcessKey(Keys keyData) {
866 control = (Control.ModifierKeys & Keys.Control) != 0;
867 shift = (Control.ModifierKeys & Keys.Shift) != 0;
869 if (shortcuts_enabled) {
870 switch (keyData & Keys.KeyCode) {
887 return Paste(Clipboard.GetDataObject(), null, true);
907 Paste(Clipboard.GetDataObject(), null, true);
927 if (document.selection_visible) {
928 document.ReplaceSelection("", false);
930 // DeleteChar only deletes on the line, doesn't do the combine
931 if (document.CaretPosition == document.CaretLine.Text.Length) {
932 if (document.CaretLine.LineNo < document.Lines) {
935 line = document.GetLine(document.CaretLine.LineNo + 1);
936 document.Combine(document.CaretLine, line);
937 document.UpdateView(document.CaretLine, 2, 0);
943 check_first = document.GetLine(document.CaretLine.LineNo);
944 check_second = document.GetLine(check_first.line_no + 1);
946 Console.WriteLine("Post-UpdateView: Y of first line: {0}, second line: {1}", check_first.Y, check_second.Y);
949 // Caret doesn't move
953 document.DeleteChar(document.CaretTag, document.CaretPosition, true);
957 end_pos = document.CaretPosition;
959 while ((end_pos < document.CaretLine.Text.Length) && !Document.IsWordSeparator(document.CaretLine.Text[end_pos])) {
963 if (end_pos < document.CaretLine.Text.Length) {
966 document.DeleteChars(document.CaretTag, document.CaretPosition, end_pos - document.CaretPosition);
971 OnTextChanged(EventArgs.Empty);
972 document.AlignCaret();
973 document.UpdateCaret();
974 CaretMoved(this, null);
979 switch (keyData & Keys.KeyCode) {
982 document.MoveCaret(CaretDirection.WordBack);
984 if (!document.selection_visible || shift) {
985 document.MoveCaret(CaretDirection.CharBack);
987 document.MoveCaret(CaretDirection.SelectionStart);
992 document.SetSelectionToCaret(true);
994 document.SetSelectionToCaret(false);
997 CaretMoved(this, null);
1003 document.MoveCaret(CaretDirection.WordForward);
1005 if (!document.selection_visible || shift) {
1006 document.MoveCaret(CaretDirection.CharForward);
1008 document.MoveCaret(CaretDirection.SelectionEnd);
1012 document.SetSelectionToCaret(true);
1014 document.SetSelectionToCaret(false);
1017 CaretMoved(this, null);
1023 if (document.CaretPosition == 0) {
1024 document.MoveCaret(CaretDirection.LineUp);
1026 document.MoveCaret(CaretDirection.Home);
1029 document.MoveCaret(CaretDirection.LineUp);
1032 if ((Control.ModifierKeys & Keys.Shift) == 0) {
1033 document.SetSelectionToCaret(true);
1035 document.SetSelectionToCaret(false);
1038 CaretMoved(this, null);
1044 if (document.CaretPosition == document.CaretLine.Text.Length) {
1045 document.MoveCaret(CaretDirection.LineDown);
1047 document.MoveCaret(CaretDirection.End);
1050 document.MoveCaret(CaretDirection.LineDown);
1053 if ((Control.ModifierKeys & Keys.Shift) == 0) {
1054 document.SetSelectionToCaret(true);
1056 document.SetSelectionToCaret(false);
1059 CaretMoved(this, null);
1064 if ((Control.ModifierKeys & Keys.Control) != 0) {
1065 document.MoveCaret(CaretDirection.CtrlHome);
1067 document.MoveCaret(CaretDirection.Home);
1070 if ((Control.ModifierKeys & Keys.Shift) == 0) {
1071 document.SetSelectionToCaret(true);
1073 document.SetSelectionToCaret(false);
1076 CaretMoved(this, null);
1081 if ((Control.ModifierKeys & Keys.Control) != 0) {
1082 document.MoveCaret(CaretDirection.CtrlEnd);
1084 document.MoveCaret(CaretDirection.End);
1087 if ((Control.ModifierKeys & Keys.Shift) == 0) {
1088 document.SetSelectionToCaret(true);
1090 document.SetSelectionToCaret(false);
1093 CaretMoved(this, null);
1098 // ignoring accepts_return, fixes bug #76355
1099 if (!read_only && (accepts_return || (FindForm() != null && FindForm().AcceptButton == null) || ((Control.ModifierKeys & Keys.Control) != 0))) {
1102 if (document.selection_visible) {
1103 document.ReplaceSelection("", false);
1106 line = document.CaretLine;
1108 document.Split (document.CaretLine, document.CaretTag, document.CaretPosition);
1109 line.ending = LineEnding.Rich;
1110 OnTextChanged(EventArgs.Empty);
1111 document.UpdateView(line, 2, 0);
1113 CaretMoved(this, null);
1120 if (!read_only && accepts_tab && document.multiline) {
1121 document.InsertChar(document.CaretLine, document.CaretPosition, '\t');
1122 if (document.selection_visible) {
1123 document.ReplaceSelection("", false);
1125 document.SetSelectionToCaret(true);
1127 OnTextChanged(EventArgs.Empty);
1128 CaretMoved(this, null);
1135 if ((Control.ModifierKeys & Keys.Control) != 0) {
1136 document.MoveCaret(CaretDirection.CtrlPgUp);
1138 document.MoveCaret(CaretDirection.PgUp);
1143 case Keys.PageDown: {
1144 if ((Control.ModifierKeys & Keys.Control) != 0) {
1145 document.MoveCaret(CaretDirection.CtrlPgDn);
1147 document.MoveCaret(CaretDirection.PgDn);
1156 private void HandleBackspace(bool control) {
1159 fire_changed = false;
1161 // delete only deletes on the line, doesn't do the combine
1162 if (document.selection_visible) {
1163 document.undo.BeginUserAction (Locale.GetText ("Delete"));
1164 document.ReplaceSelection("", false);
1165 document.undo.EndUserAction ();
1166 fire_changed = true;
1168 document.SetSelectionToCaret(true);
1170 if (document.CaretPosition == 0) {
1171 if (document.CaretLine.LineNo > 1) {
1175 line = document.GetLine(document.CaretLine.LineNo - 1);
1176 new_caret_pos = line.text.Length;
1178 document.Combine(line, document.CaretLine);
1179 document.UpdateView(line, 1, 0);
1180 document.PositionCaret(line, new_caret_pos);
1181 document.SetSelectionToCaret (true);
1182 document.UpdateCaret();
1183 fire_changed = true;
1186 if (!control || document.CaretPosition == 0) {
1188 // Move before we delete because the delete will change positions around
1189 // if we cross a wrap border
1190 LineTag tag = document.CaretTag;
1191 int pos = document.CaretPosition;
1192 document.MoveCaret (CaretDirection.CharBack);
1193 document.DeleteChar (tag, pos, false);
1194 document.SetSelectionToCaret (true);
1199 start_pos = document.CaretPosition - 1;
1200 while ((start_pos > 0) && !Document.IsWordSeparator(document.CaretLine.Text[start_pos - 1])) {
1204 document.undo.BeginUserAction (Locale.GetText ("Delete"));
1205 document.DeleteChars(document.CaretTag, start_pos, document.CaretPosition - start_pos);
1206 document.undo.EndUserAction ();
1207 document.PositionCaret(document.CaretLine, start_pos);
1208 document.SetSelectionToCaret (true);
1210 document.UpdateCaret();
1211 fire_changed = true;
1215 OnTextChanged(EventArgs.Empty);
1217 CaretMoved(this, null);
1220 protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified) {
1221 // Make sure we don't get sized bigger than we want to be
1223 if (!document.multiline) {
1224 if (height != PreferredHeight) {
1225 requested_height = height;
1226 height = PreferredHeight;
1227 specified |= BoundsSpecified.Height;
1232 base.SetBoundsCore (x, y, width, height, specified);
1235 protected override void WndProc(ref Message m) {
1236 switch ((Msg)m.Msg) {
1237 case Msg.WM_KEYDOWN: {
1238 if (ProcessKeyMessage(ref m) || ProcessKey((Keys)m.WParam.ToInt32() | XplatUI.State.ModifierKeys)) {
1239 m.Result = IntPtr.Zero;
1249 if (ProcessKeyMessage(ref m)) {
1250 m.Result = IntPtr.Zero;
1258 m.Result = IntPtr.Zero;
1260 ch = m.WParam.ToInt32();
1263 HandleBackspace(true);
1264 } else if (ch >= 32) {
1265 if (document.selection_visible) {
1266 document.ReplaceSelection("", false);
1269 char c = (char)m.WParam;
1270 switch (character_casing) {
1271 case CharacterCasing.Upper:
1272 c = Char.ToUpper((char) m.WParam);
1274 case CharacterCasing.Lower:
1275 c = Char.ToLower((char) m.WParam);
1279 if (document.Length < max_length) {
1280 document.InsertCharAtCaret(c, true);
1284 OnTextChanged(EventArgs.Empty);
1285 CaretMoved(this, null);
1287 XplatUI.AudibleAlert();
1290 } else if (ch == 8) {
1291 HandleBackspace(false);
1297 case Msg.WM_SETFOCUS:
1298 base.WndProc(ref m);
1299 document.CaretHasFocus ();
1302 case Msg.WM_KILLFOCUS:
1303 base.WndProc(ref m);
1304 document.CaretLostFocus ();
1308 base.WndProc(ref m);
1313 #endregion // Protected Instance Methods
1316 static object AcceptsTabChangedEvent = new object ();
1317 static object AutoSizeChangedEvent = new object ();
1318 static object BorderStyleChangedEvent = new object ();
1319 static object HideSelectionChangedEvent = new object ();
1320 static object ModifiedChangedEvent = new object ();
1321 static object MultilineChangedEvent = new object ();
1322 static object ReadOnlyChangedEvent = new object ();
1323 static object HScrolledEvent = new object ();
1324 static object VScrolledEvent = new object ();
1326 public event EventHandler AcceptsTabChanged {
1327 add { Events.AddHandler (AcceptsTabChangedEvent, value); }
1328 remove { Events.RemoveHandler (AcceptsTabChangedEvent, value); }
1331 public new event EventHandler AutoSizeChanged {
1332 add { Events.AddHandler (AutoSizeChangedEvent, value); }
1333 remove { Events.RemoveHandler (AutoSizeChangedEvent, value); }
1336 public event EventHandler BorderStyleChanged {
1337 add { Events.AddHandler (BorderStyleChangedEvent, value); }
1338 remove { Events.RemoveHandler (BorderStyleChangedEvent, value); }
1341 public event EventHandler HideSelectionChanged {
1342 add { Events.AddHandler (HideSelectionChangedEvent, value); }
1343 remove { Events.RemoveHandler (HideSelectionChangedEvent, value); }
1346 public event EventHandler ModifiedChanged {
1347 add { Events.AddHandler (ModifiedChangedEvent, value); }
1348 remove { Events.RemoveHandler (ModifiedChangedEvent, value); }
1351 public event EventHandler MultilineChanged {
1352 add { Events.AddHandler (MultilineChangedEvent, value); }
1353 remove { Events.RemoveHandler (MultilineChangedEvent, value); }
1356 public event EventHandler ReadOnlyChanged {
1357 add { Events.AddHandler (ReadOnlyChangedEvent, value); }
1358 remove { Events.RemoveHandler (ReadOnlyChangedEvent, value); }
1361 internal event EventHandler HScrolled {
1362 add { Events.AddHandler (HScrolledEvent, value); }
1363 remove { Events.RemoveHandler (HScrolledEvent, value); }
1366 internal event EventHandler VScrolled {
1367 add { Events.AddHandler (VScrolledEvent, value); }
1368 remove { Events.RemoveHandler (VScrolledEvent, value); }
1372 [EditorBrowsable(EditorBrowsableState.Never)]
1373 public new event EventHandler BackgroundImageChanged {
1374 add { base.BackgroundImageChanged += value; }
1375 remove { base.BackgroundImageChanged -= value; }
1378 [EditorBrowsable(EditorBrowsableState.Advanced)]
1379 public new event EventHandler Click {
1380 add { base.Click += value; }
1381 remove { base.Click -= value; }
1384 // XXX should this not manipulate base.Paint?
1386 [EditorBrowsable(EditorBrowsableState.Never)]
1387 public new event PaintEventHandler Paint;
1388 #endregion // Events
1390 #region Private Methods
1391 internal Document Document {
1401 internal bool ShowSelection {
1403 if (show_selection || !hide_selection) {
1411 if (show_selection == value)
1414 show_selection = value;
1415 // Currently InvalidateSelectionArea is commented out so do a full invalidate
1416 document.InvalidateSelectionArea();
1420 internal Graphics CreateGraphicsInternal() {
1421 if (IsHandleCreated) {
1422 return base.CreateGraphics();
1425 return Graphics.FromImage(bmp);
1432 internal override void OnPaintInternal (PaintEventArgs pevent) {
1434 if (backcolor_set || (Enabled && !read_only)) {
1435 pevent.Graphics.FillRectangle(ThemeEngine.Current.ResPool.GetSolidBrush(BackColor), pevent.ClipRectangle);
1437 pevent.Graphics.FillRectangle(ThemeEngine.Current.ResPool.GetSolidBrush(ThemeEngine.Current.ColorControl), pevent.ClipRectangle);
1440 // Draw the viewable document
1441 document.Draw(pevent.Graphics, pevent.ClipRectangle);
1444 // OnPaint does not get raised on MS (see bug #80639)
1446 pevent.Handled = true;
1449 private bool IsDoubleClick (MouseEventArgs e)
1451 TimeSpan interval = DateTime.Now - click_last;
1452 if (interval.TotalMilliseconds > SystemInformation.DoubleClickTime)
1454 Size dcs = SystemInformation.DoubleClickSize;
1455 if (e.X < click_point_x - dcs.Width / 2 || e.X > click_point_x + dcs.Width / 2)
1457 if (e.Y < click_point_y - dcs.Height / 2 || e.Y > click_point_y + dcs.Height / 2)
1462 private void TextBoxBase_MouseDown (object sender, MouseEventArgs e)
1464 if (e.Button == MouseButtons.Left) {
1466 document.PositionCaret(e.X + document.ViewPortX, e.Y + document.ViewPortY);
1468 if (IsDoubleClick (e)) {
1469 switch (click_mode) {
1470 case CaretSelection.Position:
1472 click_mode = CaretSelection.Word;
1474 case CaretSelection.Word:
1476 if (this is TextBox) {
1477 document.SetSelectionToCaret (true);
1478 click_mode = CaretSelection.Position;
1482 document.ExpandSelection (CaretSelection.Line, false);
1483 click_mode = CaretSelection.Line;
1485 case CaretSelection.Line:
1487 // Gotta do this first because Exanding to a word
1488 // from a line doesn't really work
1489 document.SetSelectionToCaret (true);
1492 click_mode = CaretSelection.Word;
1496 document.SetSelectionToCaret (true);
1497 click_mode = CaretSelection.Position;
1500 click_point_x = e.X;
1501 click_point_y = e.Y;
1502 click_last = DateTime.Now;
1505 if ((e.Button == MouseButtons.Middle) && (((int)Environment.OSVersion.Platform == 4) || ((int)Environment.OSVersion.Platform == 128))) {
1506 Document.Marker marker;
1508 marker.tag = document.FindCursor(e.X + document.ViewPortX, e.Y + document.ViewPortY, out marker.pos);
1509 marker.line = marker.tag.line;
1510 marker.height = marker.tag.height;
1512 document.SetSelection(marker.line, marker.pos, marker.line, marker.pos);
1513 Paste (Clipboard.GetDataObject (true), null, true);
1518 private void TextBoxBase_MouseUp(object sender, MouseEventArgs e) {
1519 if (e.Button == MouseButtons.Left) {
1520 if (click_mode == CaretSelection.Position) {
1521 document.SetSelectionToCaret(false);
1522 document.DisplayCaret();
1525 if (scroll_timer != null) {
1526 scroll_timer.Enabled = false;
1532 private void PositionControls ()
1534 if (hscroll.Visible) {
1535 //vscroll.Maximum += hscroll.Height;
1536 canvas_height = ClientSize.Height - hscroll.Height;
1538 canvas_height = ClientSize.Height;
1541 if (vscroll.Visible) {
1542 //hscroll.Maximum += vscroll.Width;
1543 canvas_width = ClientSize.Width - vscroll.Width;
1545 canvas_width = ClientSize.Width;
1549 document.ViewPortWidth = canvas_width;
1550 document.ViewPortHeight = canvas_height;
1552 if (canvas_height < 1 || canvas_width < 1)
1555 // We always move them, they just might not be displayed
1556 hscroll.Bounds = new Rectangle (ClientRectangle.Left,
1557 Math.Max (0, ClientRectangle.Height - hscroll.Height),
1558 Math.Max (0, ClientSize.Width - (vscroll.Visible ? vscroll.Width : 0)),
1561 vscroll.Bounds = new Rectangle (Math.Max (0, ClientRectangle.Right - vscroll.Width),
1562 ClientRectangle.Top, vscroll.Width,
1563 Math.Max (0, ClientSize.Height - (hscroll.Visible ? hscroll.Height : 0)));
1567 private void TextBoxBase_SizeChanged(object sender, EventArgs e) {
1568 if (IsHandleCreated)
1569 CalculateDocument ();
1572 private void TextBoxBase_MouseWheel(object sender, MouseEventArgs e) {
1574 if (!vscroll.Enabled) {
1579 vscroll.Value = Math.Min (vscroll.Value + SystemInformation.MouseWheelScrollLines,
1580 Math.Max (0, vscroll.Maximum - document.ViewPortHeight + 1));
1582 vscroll.Value = Math.Max (0, vscroll.Value - SystemInformation.MouseWheelScrollLines);
1585 internal virtual void SelectWord ()
1587 StringBuilder s = document.caret.line.text;
1588 int start = document.caret.pos;
1589 int end = document.caret.pos;
1592 if (document.caret.line.line_no >= document.Lines)
1594 Line line = document.GetLine (document.caret.line.line_no + 1);
1595 document.PositionCaret (line, 0);
1604 // skip whitespace until we hit a word
1605 while (start > 0 && s [start] == ' ')
1608 while (start > 0 && (s [start] != ' '))
1610 if (s [start] == ' ')
1614 if (s [end] == ' ') {
1615 while (end < s.Length && s [end] == ' ')
1618 while (end < s.Length && s [end] != ' ')
1620 while (end < s.Length && s [end] == ' ')
1624 document.SetSelection (document.caret.line, start, document.caret.line, end);
1625 document.PositionCaret (document.selection_end.line, document.selection_end.pos);
1626 document.DisplayCaret();
1629 internal void CalculateDocument() {
1631 document.RecalculateDocument(CreateGraphicsInternal());
1632 CalculateScrollBars();
1634 if (document.caret.line != null && document.caret.line.Y < document.ViewPortHeight) {
1635 // The window has probably been resized, making the entire thing visible, so
1636 // we need to set the scroll position back to zero.
1643 internal void CalculateScrollBars () {
1644 // FIXME - need separate calculations for center and right alignment
1646 if (!document.multiline) {
1647 PositionControls ();
1651 if (document.Width >= document.ViewPortWidth) {
1652 hscroll.SetValues (0, Math.Max (1, document.Width), -1,
1653 document.ViewPortWidth < 0 ? 0 : document.ViewPortWidth);
1654 hscroll.Enabled = true;
1656 hscroll.Enabled = false;
1657 hscroll.Maximum = document.ViewPortWidth;
1660 if (document.Height >= document.ViewPortHeight) {
1661 vscroll.SetValues (0, Math.Max (1, document.Height), -1,
1662 document.ViewPortHeight < 0 ? 0 : document.ViewPortHeight);
1663 vscroll.Enabled = true;
1665 vscroll.Enabled = false;
1666 vscroll.Maximum = document.ViewPortHeight;
1671 if ((scrollbars & RichTextBoxScrollBars.Horizontal) != 0) {
1672 if (((scrollbars & RichTextBoxScrollBars.ForcedHorizontal) != 0) || hscroll.Enabled) {
1673 hscroll.Visible = true;
1675 hscroll.Visible = false;
1678 hscroll.Visible = false;
1682 if ((scrollbars & RichTextBoxScrollBars.Vertical) != 0) {
1683 if (((scrollbars & RichTextBoxScrollBars.ForcedVertical) != 0) || vscroll.Enabled) {
1684 vscroll.Visible = true;
1686 vscroll.Visible = false;
1689 vscroll.Visible = false;
1692 PositionControls ();
1695 private void document_WidthChanged(object sender, EventArgs e) {
1696 CalculateScrollBars();
1699 private void document_HeightChanged(object sender, EventArgs e) {
1700 CalculateScrollBars();
1703 private void hscroll_ValueChanged(object sender, EventArgs e) {
1706 old_viewport_x = document.ViewPortX;
1707 document.ViewPortX = this.hscroll.Value;
1710 // Before scrolling we want to destroy the caret, then draw a new one after the scroll
1711 // the reason for this is that scrolling changes the coordinates of the caret, and we
1712 // will get tracers if we don't
1715 document.CaretLostFocus ();
1717 if (vscroll.Visible) {
1718 XplatUI.ScrollWindow(this.Handle, new Rectangle(0, 0, ClientSize.Width - vscroll.Width, ClientSize.Height), old_viewport_x - this.hscroll.Value, 0, false);
1720 XplatUI.ScrollWindow(this.Handle, ClientRectangle, old_viewport_x - this.hscroll.Value, 0, false);
1724 document.CaretHasFocus ();
1726 EventHandler eh = (EventHandler)(Events [HScrolledEvent]);
1728 eh (this, EventArgs.Empty);
1731 private void vscroll_ValueChanged(object sender, EventArgs e) {
1734 old_viewport_y = document.ViewPortY;
1735 document.ViewPortY = this.vscroll.Value;
1738 // Before scrolling we want to destroy the caret, then draw a new one after the scroll
1739 // the reason for this is that scrolling changes the coordinates of the caret, and we
1740 // will get tracers if we don't
1743 document.CaretLostFocus ();
1745 if (hscroll.Visible) {
1746 XplatUI.ScrollWindow(this.Handle, new Rectangle(0, 0, ClientSize.Width, ClientSize.Height - hscroll.Height), 0, old_viewport_y - this.vscroll.Value, false);
1748 XplatUI.ScrollWindow(this.Handle, ClientRectangle, 0, old_viewport_y - this.vscroll.Value, false);
1752 document.CaretHasFocus ();
1754 EventHandler eh = (EventHandler)(Events [VScrolledEvent]);
1756 eh (this, EventArgs.Empty);
1759 private void TextBoxBase_MouseMove(object sender, MouseEventArgs e) {
1760 // FIXME - handle auto-scrolling if mouse is to the right/left of the window
1761 if (e.Button == MouseButtons.Left && Capture) {
1762 if (!ClientRectangle.Contains (e.X, e.Y)) {
1763 if (scroll_timer == null) {
1764 scroll_timer = new Timer ();
1765 scroll_timer.Interval = 100;
1766 scroll_timer.Tick += new EventHandler (ScrollTimerTickHandler);
1769 if (!scroll_timer.Enabled) {
1770 scroll_timer.Start ();
1772 // Force the first tick
1773 ScrollTimerTickHandler (null, EventArgs.Empty);
1777 document.PositionCaret(e.X + document.ViewPortX, e.Y + document.ViewPortY);
1778 if (click_mode == CaretSelection.Position) {
1779 document.SetSelectionToCaret(false);
1780 document.DisplayCaret();
1785 private void TextBoxBase_FontOrColorChanged(object sender, EventArgs e) {
1789 document.SuspendRecalc ();
1790 // Font changes apply to the whole document
1791 for (int i = 1; i <= document.Lines; i++) {
1792 line = document.GetLine(i);
1793 LineTag.FormatText(line, 1, line.text.Length, Font,
1794 ThemeEngine.Current.ResPool.GetSolidBrush(ForeColor),
1795 null, FormatSpecified.Font | FormatSpecified.Color);
1797 document.ResumeRecalc (false);
1799 // Make sure the caret height is matching the new font height
1800 document.AlignCaret();
1804 private void ScrollTimerTickHandler (object sender, EventArgs e)
1806 Point pt = Cursor.Position;
1808 pt = PointToClient (pt);
1810 if (pt.X < ClientRectangle.Left) {
1811 document.MoveCaret(CaretDirection.CharBackNoWrap);
1812 document.SetSelectionToCaret(false);
1814 CaretMoved(this, null);
1815 } else if (pt.X > ClientRectangle.Right) {
1816 document.MoveCaret(CaretDirection.CharForwardNoWrap);
1817 document.SetSelectionToCaret(false);
1819 CaretMoved(this, null);
1820 } else if (pt.Y > ClientRectangle.Bottom) {
1821 document.MoveCaret(CaretDirection.LineDown);
1822 document.SetSelectionToCaret(false);
1824 CaretMoved(this, null);
1825 } else if (pt.Y < ClientRectangle.Top) {
1826 document.MoveCaret(CaretDirection.LineUp);
1827 document.SetSelectionToCaret(false);
1829 CaretMoved(this, null);
1833 /// <summary>Ensure the caret is always visible</summary>
1834 internal void CaretMoved(object sender, EventArgs e) {
1838 if (canvas_width < 1 || canvas_height < 1)
1841 document.MoveCaretToTextTag ();
1842 pos = document.Caret;
1844 //Console.WriteLine("Caret now at {0} (Thumb: {1}x{2}, Canvas: {3}x{4}, Document {5}x{6})", pos, hscroll.Value, vscroll.Value, canvas_width, canvas_height, document.Width, document.Height);
1847 // Horizontal scrolling:
1848 // If the caret moves to the left outside the visible area, we jump the document into view, not just one
1849 // character, but 1/3 of the width of the document
1850 // If the caret moves to the right outside the visible area, we scroll just enough to keep the caret visible
1852 // Handle horizontal scrolling
1853 if (document.CaretLine.alignment == HorizontalAlignment.Left) {
1854 // Check if we moved out of view to the left
1855 if (pos.X < (document.ViewPortX)) {
1857 if ((hscroll.Value - document.ViewPortWidth / 3) >= hscroll.Minimum) {
1858 hscroll.Value -= document.ViewPortWidth / 3;
1860 hscroll.Value = hscroll.Minimum;
1862 } while (hscroll.Value > pos.X);
1865 // Check if we moved out of view to the right
1866 if ((pos.X >= (document.ViewPortWidth + document.ViewPortX)) && (hscroll.Value != hscroll.Maximum)) {
1867 if ((pos.X - document.ViewPortWidth + 1) <= hscroll.Maximum) {
1868 if (pos.X - document.ViewPortWidth >= 0) {
1869 hscroll.Value = pos.X - document.ViewPortWidth + 1;
1874 hscroll.Value = hscroll.Maximum;
1877 } else if (document.CaretLine.alignment == HorizontalAlignment.Right) {
1878 // hscroll.Value = pos.X;
1880 // if ((pos.X > (this.canvas_width + document.ViewPortX)) && (hscroll.Enabled && (hscroll.Value != hscroll.Maximum))) {
1881 // hscroll.Value = hscroll.Maximum;
1884 // FIXME - implement center cursor alignment
1887 if (!document.multiline) {
1891 // Handle vertical scrolling
1892 height = document.CaretLine.Height + 1;
1894 if (pos.Y < document.ViewPortY) {
1895 vscroll.Value = pos.Y;
1898 if ((pos.Y + height) > (document.ViewPortY + canvas_height)) {
1899 vscroll.Value = Math.Max (0, pos.Y - canvas_height + height);
1903 internal bool Paste(IDataObject clip, DataFormats.Format format, bool obey_length) {
1909 if (format == null) {
1910 if ((this is RichTextBox) && clip.GetDataPresent(DataFormats.Rtf)) {
1911 format = DataFormats.GetFormat(DataFormats.Rtf);
1912 } else if ((this is RichTextBox) && clip.GetDataPresent (DataFormats.Bitmap)) {
1913 format = DataFormats.GetFormat (DataFormats.Bitmap);
1914 } else if (clip.GetDataPresent(DataFormats.UnicodeText)) {
1915 format = DataFormats.GetFormat(DataFormats.UnicodeText);
1916 } else if (clip.GetDataPresent(DataFormats.Text)) {
1917 format = DataFormats.GetFormat(DataFormats.Text);
1922 if ((format.Name == DataFormats.Rtf) && !(this is RichTextBox)) {
1926 if (!clip.GetDataPresent(format.Name)) {
1931 if (format.Name == DataFormats.Rtf) {
1932 document.undo.BeginUserAction (Locale.GetText ("Paste"));
1933 ((RichTextBox)this).SelectedRtf = (string)clip.GetData(DataFormats.Rtf);
1934 document.undo.EndUserAction ();
1936 } else if (format.Name == DataFormats.Bitmap) {
1937 document.undo.BeginUserAction (Locale.GetText ("Paste"));
1938 // document.InsertImage (document.caret.line, document.caret.pos, (Image) clip.GetData (DataFormats.Bitmap));
1939 document.MoveCaret (CaretDirection.CharForward);
1940 document.undo.EndUserAction ();
1942 } else if (format.Name == DataFormats.UnicodeText) {
1943 s = (string)clip.GetData(DataFormats.UnicodeText);
1944 } else if (format.Name == DataFormats.Text) {
1945 s = (string)clip.GetData(DataFormats.Text);
1951 document.undo.BeginUserAction (Locale.GetText ("Paste"));
1952 this.SelectedText = s;
1953 document.undo.EndUserAction ();
1955 if ((s.Length + document.Length) < max_length) {
1956 document.undo.BeginUserAction (Locale.GetText ("Paste"));
1957 this.SelectedText = s;
1958 document.undo.EndUserAction ();
1959 } else if (document.Length < max_length) {
1960 document.undo.BeginUserAction (Locale.GetText ("Paste"));
1961 this.SelectedText = s.Substring (0, max_length - document.Length);
1962 document.undo.EndUserAction ();
1968 #endregion // Private Methods
1971 // This is called just before OnTextChanged is called.
1972 internal virtual void OnTextUpdate ()
1976 protected override void OnTextChanged (EventArgs e)
1978 base.OnTextChanged (e);
1981 public virtual int GetLineFromCharIndex (int index)
1987 document.CharIndexToLineTag (index, out line_out, out tag_out, out pos);
1989 return line_out.LineNo;
1992 protected override void OnMouseUp (MouseEventArgs e)