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
;
79 internal static bool draw_lines
= false;
82 #endregion // Local Variables
84 #region Internal Constructor
85 // Constructor will go when complete, only for testing - pdb
86 internal TextBoxBase() {
87 alignment
= HorizontalAlignment
.Left
;
88 accepts_return
= false;
91 border_style
= BorderStyle
.Fixed3D
;
92 actual_border_style
= BorderStyle
.Fixed3D
;
93 character_casing
= CharacterCasing
.Normal
;
94 hide_selection
= true;
101 show_selection
= false;
102 show_caret_w_selection
= (this is TextBox
);
103 document
= new Document(this);
104 document
.WidthChanged
+= new EventHandler(document_WidthChanged
);
105 document
.HeightChanged
+= new EventHandler(document_HeightChanged
);
106 //document.CaretMoved += new EventHandler(CaretMoved);
107 document
.Wrap
= false;
108 requested_height
= -1;
109 click_last
= DateTime
.Now
;
110 click_mode
= CaretSelection
.Position
;
111 bmp
= new Bitmap(1, 1, System
.Drawing
.Imaging
.PixelFormat
.Format32bppArgb
);
113 MouseDown
+= new MouseEventHandler(TextBoxBase_MouseDown
);
114 MouseUp
+= new MouseEventHandler(TextBoxBase_MouseUp
);
115 MouseMove
+= new MouseEventHandler(TextBoxBase_MouseMove
);
116 SizeChanged
+= new EventHandler(TextBoxBase_SizeChanged
);
117 FontChanged
+= new EventHandler(TextBoxBase_FontOrColorChanged
);
118 ForeColorChanged
+= new EventHandler(TextBoxBase_FontOrColorChanged
);
119 MouseWheel
+= new MouseEventHandler(TextBoxBase_MouseWheel
);
121 scrollbars
= RichTextBoxScrollBars
.None
;
123 hscroll
= new ImplicitHScrollBar();
124 hscroll
.ValueChanged
+= new EventHandler(hscroll_ValueChanged
);
125 hscroll
.SetStyle (ControlStyles
.Selectable
, false);
126 hscroll
.Enabled
= false;
127 hscroll
.Visible
= false;
128 hscroll
.Maximum
= Int32
.MaxValue
;
130 vscroll
= new ImplicitVScrollBar();
131 vscroll
.ValueChanged
+= new EventHandler(vscroll_ValueChanged
);
132 vscroll
.SetStyle (ControlStyles
.Selectable
, false);
133 vscroll
.Enabled
= false;
134 vscroll
.Visible
= false;
135 vscroll
.Maximum
= Int32
.MaxValue
;
138 this.Controls
.AddImplicit (hscroll
);
139 this.Controls
.AddImplicit (vscroll
);
142 SetStyle(ControlStyles
.UserPaint
| ControlStyles
.StandardClick
, false);
144 SetStyle(ControlStyles
.UseTextForAccessibility
, false);
147 canvas_width
= ClientSize
.Width
;
148 canvas_height
= ClientSize
.Height
;
149 document
.ViewPortWidth
= canvas_width
;
150 document
.ViewPortHeight
= canvas_height
;
152 Cursor
= Cursors
.IBeam
;
154 CalculateScrollBars();
156 #endregion // Internal Constructor
158 #region Private and Internal Methods
159 internal string CaseAdjust(string s
) {
160 if (character_casing
== CharacterCasing
.Normal
) {
163 if (character_casing
== CharacterCasing
.Lower
) {
170 internal override void HandleClick(int clicks
, MouseEventArgs me
) {
171 // MS seems to fire the click event in spite of the styles they set
172 bool click_set
= GetStyle (ControlStyles
.StandardClick
);
173 bool doubleclick_set
= GetStyle (ControlStyles
.StandardDoubleClick
);
175 // so explicitly set them to true first
176 SetStyle (ControlStyles
.StandardClick
| ControlStyles
.StandardDoubleClick
, true);
178 base.HandleClick (clicks
, me
);
180 // then revert to our previous state
182 SetStyle (ControlStyles
.StandardClick
, false);
183 if (!doubleclick_set
)
184 SetStyle (ControlStyles
.StandardDoubleClick
, false);
187 #endregion // Private and Internal Methods
189 #region Public Instance Properties
190 [DefaultValue(false)]
191 [MWFCategory("Behavior")]
192 public bool AcceptsTab
{
198 if (value != accepts_tab
) {
200 OnAcceptsTabChanged(EventArgs
.Empty
);
207 [RefreshProperties(RefreshProperties
.Repaint
)]
208 [MWFCategory("Behavior")]
221 if (value != auto_size
) {
224 if (PreferredHeight
!= ClientSize
.Height
) {
225 ClientSize
= new Size(ClientSize
.Width
, PreferredHeight
);
228 OnAutoSizeChanged(EventArgs
.Empty
);
234 public override System
.Drawing
.Color BackColor
{
236 return base.BackColor
;
239 backcolor_set
= true;
240 base.BackColor
= value;
245 [EditorBrowsable(EditorBrowsableState
.Never
)]
246 public override System
.Drawing
.Image BackgroundImage
{
248 return base.BackgroundImage
;
251 base.BackgroundImage
= value;
255 [DefaultValue(BorderStyle
.Fixed3D
)]
257 [MWFCategory("Appearance")]
258 public BorderStyle BorderStyle
{
259 get { return actual_border_style; }
261 if (value == actual_border_style
)
264 if (actual_border_style
!= BorderStyle
.Fixed3D
|| value != BorderStyle
.Fixed3D
)
267 actual_border_style
= value;
268 if (value != BorderStyle
.Fixed3D
)
269 value = BorderStyle
.None
;
271 InternalBorderStyle
= value;
272 OnBorderStyleChanged(EventArgs
.Empty
);
277 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
278 public bool CanUndo
{
280 return document
.undo
.CanUndo
;
285 public override System
.Drawing
.Color ForeColor
{
287 return base.ForeColor
;
290 base.ForeColor
= value;
295 [MWFCategory("Behavior")]
296 public bool HideSelection
{
298 return hide_selection
;
302 if (value != hide_selection
) {
303 hide_selection
= value;
304 OnHideSelectionChanged(EventArgs
.Empty
);
306 if (hide_selection
) {
307 document
.selection_visible
= false;
309 document
.selection_visible
= true;
311 document
.InvalidateSelectionArea();
316 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
317 [Editor("System.Windows.Forms.Design.StringArrayEditor, " + Consts
.AssemblySystem_Design
, typeof(System
.Drawing
.Design
.UITypeEditor
))]
319 [MWFCategory("Appearance")]
320 public string[] Lines
{
325 count
= document
.Lines
;
327 // Handle empty document
328 if ((count
== 1) && (document
.GetLine (1).text
.Length
== 0)) {
329 return new string [0];
332 lines
= new ArrayList ();
337 StringBuilder lt
= new StringBuilder ();
340 line
= document
.GetLine (i
++);
341 lt
.Append (line
.text
.ToString ());
342 } while (line
.soft_break
&& i
<= count
);
344 lines
.Add (lt
.ToString ());
347 return (string []) lines
.ToArray (typeof (string));
358 brush
= ThemeEngine
.Current
.ResPool
.GetSolidBrush(this.ForeColor
);
360 document
.SuspendRecalc ();
361 for (i
= 0; i
< l
; i
++) {
363 // Don't add the last line if it is just an empty line feed
364 // the line feed is reflected in the previous line's soft_break = false
365 if (i
== l
- 1 && value [i
].Length
== 0)
368 bool carriage_return
= false;
369 if (value [i
].EndsWith ("\r")) {
370 value [i
] = value [i
].Substring (0, value [i
].Length
- 1);
371 carriage_return
= true;
374 document
.Add(i
+1, CaseAdjust(value[i
]), alignment
, Font
, brush
);
375 if (carriage_return
) {
376 Line line
= document
.GetLine (i
+ 1);
377 line
.carriage_return
= true;
381 document
.ResumeRecalc (true);
383 // CalculateDocument();
384 OnTextChanged(EventArgs
.Empty
);
388 [DefaultValue(32767)]
390 [MWFCategory("Behavior")]
391 public virtual int MaxLength
{
393 if (max_length
== 2147483646) { // We don't distinguish between single and multi-line limits
400 if (value != max_length
) {
407 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
408 public bool Modified
{
414 if (value != modified
) {
416 OnModifiedChanged(EventArgs
.Empty
);
421 [DefaultValue(false)]
423 [RefreshProperties(RefreshProperties
.All
)]
424 [MWFCategory("Behavior")]
425 public virtual bool Multiline
{
427 return document
.multiline
;
431 if (value != document
.multiline
) {
432 document
.multiline
= value;
433 // Make sure we update our size; the user may have already set the size before going to multiline
434 if (document
.multiline
&& requested_height
!= -1) {
435 Height
= requested_height
;
436 requested_height
= -1;
440 Parent
.PerformLayout ();
442 OnMultilineChanged(EventArgs
.Empty
);
445 if (document
.multiline
) {
446 document
.Wrap
= word_wrap
;
447 document
.PasswordChar
= "";
450 document
.Wrap
= false;
451 if (this.password_char
!= '\0') {
452 document
.PasswordChar
= password_char
.ToString();
454 document
.PasswordChar
= "";
459 CalculateDocument ();
464 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
465 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
466 public int PreferredHeight
{
468 return Font
.Height
+ (BorderStyle
!= BorderStyle
.Fixed3D
? 0 : 7);
472 [DefaultValue(false)]
473 [MWFCategory("Behavior")]
474 public bool ReadOnly
{
480 if (value != read_only
) {
483 if (!backcolor_set
) {
485 background_color
= SystemColors
.Control
;
487 background_color
= SystemColors
.Window
;
490 OnReadOnlyChanged(EventArgs
.Empty
);
497 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
498 public virtual string SelectedText
{
500 return document
.GetSelection();
504 document
.ReplaceSelection(CaseAdjust(value), false);
507 OnTextChanged(EventArgs
.Empty
);
512 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
513 public virtual int SelectionLength
{
515 int res
= document
.SelectionLength ();
523 throw new ArgumentException(String
.Format("{0} is not a valid value", value), "value");
532 selection_length
= value;
534 start
= document
.LineTagToCharIndex(document
.selection_start
.line
, document
.selection_start
.pos
);
536 document
.CharIndexToLineTag(start
+ value, out line
, out tag
, out pos
);
537 document
.SetSelectionEnd(line
, pos
);
538 document
.PositionCaret(line
, pos
);
540 selection_length
= -1;
542 document
.SetSelectionEnd(document
.selection_start
.line
, document
.selection_start
.pos
);
543 document
.PositionCaret(document
.selection_start
.line
, document
.selection_start
.pos
);
549 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
550 public int SelectionStart
{
554 index
= document
.LineTagToCharIndex(document
.selection_start
.line
, document
.selection_start
.pos
);
560 document
.SetSelectionStart(value);
561 if (selection_length
> -1 ) {
562 document
.SetSelectionEnd(value + selection_length
);
564 document
.SetSelectionEnd(value);
566 document
.PositionCaret(document
.selection_start
.line
, document
.selection_start
.pos
);
572 public override string Text
{
574 if (document
== null || document
.Root
== null || document
.Root
.text
== null) {
578 StringBuilder sb
= new StringBuilder();
581 for (int i
= 1; i
<= document
.Lines
; i
++) {
582 if (line
!= null && line
.carriage_return
)
584 if (line
!= null && !line
.soft_break
)
585 sb
.Append (Environment
.NewLine
);
586 line
= document
.GetLine (i
);
587 sb
.Append(line
.text
.ToString());
590 return sb
.ToString();
597 if ((value != null) && (value != "")) {
601 document
.Insert (document
.GetLine (1), 0, false, value);
603 document
.PositionCaret (document
.GetLine (1), 0);
604 document
.SetSelectionToCaret (true);
610 CalculateDocument ();
613 // set the var so OnModifiedChanged is not raised
615 OnTextChanged(EventArgs
.Empty
);
620 public virtual int TextLength
{
622 if (document
== null || document
.Root
== null || document
.Root
.text
== null) {
631 [MWFCategory("Behavior")]
632 public bool WordWrap
{
638 if (value != word_wrap
) {
639 if (document
.multiline
) {
641 document
.Wrap
= value;
646 #endregion // Public Instance Properties
648 #region Protected Instance Properties
649 protected override CreateParams CreateParams
{
651 return base.CreateParams
;
655 protected override System
.Drawing
.Size DefaultSize
{
657 return new Size(100, 20);
660 #endregion // Protected Instance Properties
662 #region Public Instance Methods
663 public void AppendText(string text
) {
664 document
.MoveCaret (CaretDirection
.CtrlEnd
);
665 document
.Insert (document
.caret
.line
, document
.caret
.pos
, false, text
);
666 document
.MoveCaret (CaretDirection
.CtrlEnd
);
667 document
.SetSelectionToCaret (true);
669 OnTextChanged(EventArgs
.Empty
);
672 public void Clear() {
676 public void ClearUndo() {
677 document
.undo
.Clear();
683 o
= new DataObject(DataFormats
.Text
, SelectedText
);
684 if (this is RichTextBox
) {
685 o
.SetData(DataFormats
.Rtf
, ((RichTextBox
)this).SelectedRtf
);
687 Clipboard
.SetDataObject(o
);
693 o
= new DataObject(DataFormats
.Text
, SelectedText
);
694 if (this is RichTextBox
) {
695 o
.SetData(DataFormats
.Rtf
, ((RichTextBox
)this).SelectedRtf
);
697 Clipboard
.SetDataObject (o
);
699 document
.undo
.BeginUserAction (Locale
.GetText ("Cut"));
700 document
.ReplaceSelection (String
.Empty
, false);
701 document
.undo
.EndUserAction ();
704 public void Paste() {
705 Paste(Clipboard
.GetDataObject(), null, false);
708 public void ScrollToCaret() {
709 if (IsHandleCreated
) {
710 CaretMoved(this, EventArgs
.Empty
);
714 public void Select(int start
, int length
) {
715 SelectionStart
= start
;
716 SelectionLength
= length
;
720 public void SelectAll() {
723 last
= document
.GetLine(document
.Lines
);
724 document
.SetSelectionStart(document
.GetLine(1), 0);
725 document
.SetSelectionEnd(last
, last
.text
.Length
);
726 document
.PositionCaret (document
.selection_end
.line
, document
.selection_end
.pos
);
727 selection_length
= -1;
730 public override string ToString() {
731 return String
.Concat (base.ToString (), ", Text: ", Text
);
735 document
.undo
.Undo();
737 #endregion // Public Instance Methods
739 #region Protected Instance Methods
740 protected override void CreateHandle() {
741 CalculateDocument ();
742 base.CreateHandle ();
743 document
.AlignCaret();
747 protected override bool IsInputKey(Keys keyData
) {
748 if ((keyData
& Keys
.Alt
) != 0) {
749 return base.IsInputKey(keyData
);
752 switch (keyData
& Keys
.KeyCode
) {
754 if (accepts_return
) {
761 if (accepts_tab
&& document
.multiline
) {
762 if ((keyData
& Keys
.Control
) == 0) {
784 protected virtual void OnAcceptsTabChanged(EventArgs e
) {
785 EventHandler eh
= (EventHandler
)(Events
[AcceptsTabChangedEvent
]);
790 protected virtual void OnAutoSizeChanged(EventArgs e
) {
791 EventHandler eh
= (EventHandler
)(Events
[AutoSizeChangedEvent
]);
796 protected virtual void OnBorderStyleChanged(EventArgs e
) {
797 EventHandler eh
= (EventHandler
)(Events
[BorderStyleChangedEvent
]);
802 protected override void OnFontChanged(EventArgs e
) {
803 base.OnFontChanged (e
);
805 if (auto_size
&& !document
.multiline
) {
806 if (PreferredHeight
!= ClientSize
.Height
) {
807 Height
= PreferredHeight
;
812 protected override void OnHandleCreated(EventArgs e
) {
813 base.OnHandleCreated (e
);
816 protected override void OnHandleDestroyed(EventArgs e
) {
817 base.OnHandleDestroyed (e
);
820 protected virtual void OnHideSelectionChanged(EventArgs e
) {
821 EventHandler eh
= (EventHandler
)(Events
[HideSelectionChangedEvent
]);
826 protected virtual void OnModifiedChanged(EventArgs e
) {
827 EventHandler eh
= (EventHandler
)(Events
[ModifiedChangedEvent
]);
832 protected virtual void OnMultilineChanged(EventArgs e
) {
833 EventHandler eh
= (EventHandler
)(Events
[MultilineChangedEvent
]);
838 protected virtual void OnReadOnlyChanged(EventArgs e
) {
839 EventHandler eh
= (EventHandler
)(Events
[ReadOnlyChangedEvent
]);
844 protected override bool ProcessDialogKey(Keys keyData
) {
845 return base.ProcessDialogKey(keyData
);
848 private bool ProcessKey(Keys keyData
) {
852 control
= (Control
.ModifierKeys
& Keys
.Control
) != 0;
853 shift
= (Control
.ModifierKeys
& Keys
.Shift
) != 0;
855 switch (keyData
& Keys
.KeyCode
) {
856 case Keys
.X
: { // Cut (Ctrl-X)
864 case Keys
.C
: { // Copy (Ctrl-C)
872 case Keys
.V
: { // Paste (Ctrl-V)
874 return Paste(Clipboard
.GetDataObject(), null, true);
879 case Keys
.Z
: { // Undo (Ctrl-Z)
887 case Keys
.A
: { // Select All (Ctrl-A)
897 document
.MoveCaret(CaretDirection
.WordBack
);
899 if (!document
.selection_visible
|| shift
) {
900 document
.MoveCaret(CaretDirection
.CharBack
);
902 document
.MoveCaret(CaretDirection
.SelectionStart
);
907 document
.SetSelectionToCaret(true);
909 document
.SetSelectionToCaret(false);
912 CaretMoved(this, null);
918 document
.MoveCaret(CaretDirection
.WordForward
);
920 if (!document
.selection_visible
|| shift
) {
921 document
.MoveCaret(CaretDirection
.CharForward
);
923 document
.MoveCaret(CaretDirection
.SelectionEnd
);
927 document
.SetSelectionToCaret(true);
929 document
.SetSelectionToCaret(false);
932 CaretMoved(this, null);
938 if (document
.CaretPosition
== 0) {
939 document
.MoveCaret(CaretDirection
.LineUp
);
941 document
.MoveCaret(CaretDirection
.Home
);
944 document
.MoveCaret(CaretDirection
.LineUp
);
947 if ((Control
.ModifierKeys
& Keys
.Shift
) == 0) {
948 document
.SetSelectionToCaret(true);
950 document
.SetSelectionToCaret(false);
953 CaretMoved(this, null);
959 if (document
.CaretPosition
== document
.CaretLine
.Text
.Length
) {
960 document
.MoveCaret(CaretDirection
.LineDown
);
962 document
.MoveCaret(CaretDirection
.End
);
965 document
.MoveCaret(CaretDirection
.LineDown
);
968 if ((Control
.ModifierKeys
& Keys
.Shift
) == 0) {
969 document
.SetSelectionToCaret(true);
971 document
.SetSelectionToCaret(false);
974 CaretMoved(this, null);
979 if ((Control
.ModifierKeys
& Keys
.Control
) != 0) {
980 document
.MoveCaret(CaretDirection
.CtrlHome
);
982 document
.MoveCaret(CaretDirection
.Home
);
985 if ((Control
.ModifierKeys
& Keys
.Shift
) == 0) {
986 document
.SetSelectionToCaret(true);
988 document
.SetSelectionToCaret(false);
991 CaretMoved(this, null);
996 if ((Control
.ModifierKeys
& Keys
.Control
) != 0) {
997 document
.MoveCaret(CaretDirection
.CtrlEnd
);
999 document
.MoveCaret(CaretDirection
.End
);
1002 if ((Control
.ModifierKeys
& Keys
.Shift
) == 0) {
1003 document
.SetSelectionToCaret(true);
1005 document
.SetSelectionToCaret(false);
1008 CaretMoved(this, null);
1013 // ignoring accepts_return, fixes bug #76355
1014 if (!read_only
&& (accepts_return
|| (FindForm() != null && FindForm().AcceptButton
== null) || ((Control
.ModifierKeys
& Keys
.Control
) != 0))) {
1017 if (document
.selection_visible
) {
1018 document
.ReplaceSelection("", false);
1021 line
= document
.CaretLine
;
1023 document
.Split (document
.CaretLine
, document
.CaretTag
, document
.CaretPosition
, line
.soft_break
);
1024 line
.soft_break
= false;
1025 OnTextChanged(EventArgs
.Empty
);
1026 document
.UpdateView(line
, 2, 0);
1028 CaretMoved(this, null);
1035 if (!read_only
&& accepts_tab
&& document
.multiline
) {
1036 document
.InsertChar(document
.CaretLine
, document
.CaretPosition
, '\t');
1037 if (document
.selection_visible
) {
1038 document
.ReplaceSelection("", false);
1040 document
.SetSelectionToCaret(true);
1042 OnTextChanged(EventArgs
.Empty
);
1043 CaretMoved(this, null);
1051 Paste(Clipboard
.GetDataObject(), null, true);
1060 // FIXME - need overwrite/insert toggle?
1065 if ((Control
.ModifierKeys
& Keys
.Control
) != 0) {
1066 document
.MoveCaret(CaretDirection
.CtrlPgUp
);
1068 document
.MoveCaret(CaretDirection
.PgUp
);
1073 case Keys
.PageDown
: {
1074 if ((Control
.ModifierKeys
& Keys
.Control
) != 0) {
1075 document
.MoveCaret(CaretDirection
.CtrlPgDn
);
1077 document
.MoveCaret(CaretDirection
.PgDn
);
1092 if (document
.selection_visible
) {
1093 document
.ReplaceSelection("", false);
1095 // DeleteChar only deletes on the line, doesn't do the combine
1096 if (document
.CaretPosition
== document
.CaretLine
.Text
.Length
) {
1097 if (document
.CaretLine
.LineNo
< document
.Lines
) {
1100 line
= document
.GetLine(document
.CaretLine
.LineNo
+ 1);
1101 document
.Combine(document
.CaretLine
, line
);
1102 document
.UpdateView(document
.CaretLine
, 2, 0);
1108 check_first
= document
.GetLine(document
.CaretLine
.LineNo
);
1109 check_second
= document
.GetLine(check_first
.line_no
+ 1);
1111 Console
.WriteLine("Post-UpdateView: Y of first line: {0}, second line: {1}", check_first
.Y
, check_second
.Y
);
1114 // Caret doesn't move
1118 document
.DeleteChar(document
.CaretTag
, document
.CaretPosition
, true);
1122 end_pos
= document
.CaretPosition
;
1124 while ((end_pos
< document
.CaretLine
.Text
.Length
) && !Document
.IsWordSeparator(document
.CaretLine
.Text
[end_pos
])) {
1128 if (end_pos
< document
.CaretLine
.Text
.Length
) {
1131 document
.DeleteChars(document
.CaretTag
, document
.CaretPosition
, end_pos
- document
.CaretPosition
);
1136 OnTextChanged(EventArgs
.Empty
);
1137 document
.AlignCaret();
1138 document
.UpdateCaret();
1139 CaretMoved(this, null);
1146 private void HandleBackspace(bool control
) {
1149 fire_changed
= false;
1151 // delete only deletes on the line, doesn't do the combine
1152 if (document
.selection_visible
) {
1153 document
.undo
.BeginUserAction (Locale
.GetText ("Delete"));
1154 document
.ReplaceSelection("", false);
1155 document
.undo
.EndUserAction ();
1156 fire_changed
= true;
1158 document
.SetSelectionToCaret(true);
1160 if (document
.CaretPosition
== 0) {
1161 if (document
.CaretLine
.LineNo
> 1) {
1165 line
= document
.GetLine(document
.CaretLine
.LineNo
- 1);
1166 new_caret_pos
= line
.text
.Length
;
1168 document
.Combine(line
, document
.CaretLine
);
1169 document
.UpdateView(line
, 1, 0);
1170 document
.PositionCaret(line
, new_caret_pos
);
1171 document
.SetSelectionToCaret (true);
1172 document
.UpdateCaret();
1173 fire_changed
= true;
1176 if (!control
|| document
.CaretPosition
== 0) {
1178 // Move before we delete because the delete will change positions around
1179 // if we cross a wrap border
1180 LineTag tag
= document
.CaretTag
;
1181 int pos
= document
.CaretPosition
;
1182 document
.MoveCaret (CaretDirection
.CharBack
);
1183 document
.DeleteChar (tag
, pos
, false);
1184 document
.SetSelectionToCaret (true);
1189 start_pos
= document
.CaretPosition
- 1;
1190 while ((start_pos
> 0) && !Document
.IsWordSeparator(document
.CaretLine
.Text
[start_pos
- 1])) {
1194 document
.undo
.BeginUserAction (Locale
.GetText ("Delete"));
1195 document
.DeleteChars(document
.CaretTag
, start_pos
, document
.CaretPosition
- start_pos
);
1196 document
.undo
.EndUserAction ();
1197 document
.PositionCaret(document
.CaretLine
, start_pos
);
1198 document
.SetSelectionToCaret (true);
1200 document
.UpdateCaret();
1201 fire_changed
= true;
1205 OnTextChanged(EventArgs
.Empty
);
1207 CaretMoved(this, null);
1210 protected override void SetBoundsCore(int x
, int y
, int width
, int height
, BoundsSpecified specified
) {
1211 // Make sure we don't get sized bigger than we want to be
1213 if (!document
.multiline
) {
1214 if (height
!= PreferredHeight
) {
1215 requested_height
= height
;
1216 height
= PreferredHeight
;
1217 specified
|= BoundsSpecified
.Height
;
1222 base.SetBoundsCore (x
, y
, width
, height
, specified
);
1225 protected override void WndProc(ref Message m
) {
1226 switch ((Msg
)m
.Msg
) {
1227 case Msg
.WM_KEYDOWN
: {
1228 if (ProcessKeyMessage(ref m
) || ProcessKey((Keys
)m
.WParam
.ToInt32() | XplatUI
.State
.ModifierKeys
)) {
1229 m
.Result
= IntPtr
.Zero
;
1239 if (ProcessKeyMessage(ref m
)) {
1240 m
.Result
= IntPtr
.Zero
;
1248 m
.Result
= IntPtr
.Zero
;
1250 ch
= m
.WParam
.ToInt32();
1253 HandleBackspace(true);
1254 } else if (ch
>= 32) {
1255 if (document
.selection_visible
) {
1256 document
.ReplaceSelection("", false);
1259 char c
= (char)m
.WParam
;
1260 switch (character_casing
) {
1261 case CharacterCasing
.Upper
:
1262 c
= Char
.ToUpper((char) m
.WParam
);
1264 case CharacterCasing
.Lower
:
1265 c
= Char
.ToLower((char) m
.WParam
);
1269 if (document
.Length
< max_length
) {
1270 document
.InsertCharAtCaret(c
, true);
1274 OnTextChanged(EventArgs
.Empty
);
1275 CaretMoved(this, null);
1277 XplatUI
.AudibleAlert();
1280 } else if (ch
== 8) {
1281 HandleBackspace(false);
1287 case Msg
.WM_SETFOCUS
:
1288 base.WndProc(ref m
);
1289 document
.CaretHasFocus ();
1292 case Msg
.WM_KILLFOCUS
:
1293 base.WndProc(ref m
);
1294 document
.CaretLostFocus ();
1298 base.WndProc(ref m
);
1303 #endregion // Protected Instance Methods
1306 static object AcceptsTabChangedEvent
= new object ();
1307 static object AutoSizeChangedEvent
= new object ();
1308 static object BorderStyleChangedEvent
= new object ();
1309 static object HideSelectionChangedEvent
= new object ();
1310 static object ModifiedChangedEvent
= new object ();
1311 static object MultilineChangedEvent
= new object ();
1312 static object ReadOnlyChangedEvent
= new object ();
1313 static object HScrolledEvent
= new object ();
1314 static object VScrolledEvent
= new object ();
1316 public event EventHandler AcceptsTabChanged
{
1317 add { Events.AddHandler (AcceptsTabChangedEvent, value); }
1318 remove { Events.RemoveHandler (AcceptsTabChangedEvent, value); }
1321 public new event EventHandler AutoSizeChanged
{
1322 add { Events.AddHandler (AutoSizeChangedEvent, value); }
1323 remove { Events.RemoveHandler (AutoSizeChangedEvent, value); }
1326 public event EventHandler BorderStyleChanged
{
1327 add { Events.AddHandler (BorderStyleChangedEvent, value); }
1328 remove { Events.RemoveHandler (BorderStyleChangedEvent, value); }
1331 public event EventHandler HideSelectionChanged
{
1332 add { Events.AddHandler (HideSelectionChangedEvent, value); }
1333 remove { Events.RemoveHandler (HideSelectionChangedEvent, value); }
1336 public event EventHandler ModifiedChanged
{
1337 add { Events.AddHandler (ModifiedChangedEvent, value); }
1338 remove { Events.RemoveHandler (ModifiedChangedEvent, value); }
1341 public event EventHandler MultilineChanged
{
1342 add { Events.AddHandler (MultilineChangedEvent, value); }
1343 remove { Events.RemoveHandler (MultilineChangedEvent, value); }
1346 public event EventHandler ReadOnlyChanged
{
1347 add { Events.AddHandler (ReadOnlyChangedEvent, value); }
1348 remove { Events.RemoveHandler (ReadOnlyChangedEvent, value); }
1351 internal event EventHandler HScrolled
{
1352 add { Events.AddHandler (HScrolledEvent, value); }
1353 remove { Events.RemoveHandler (HScrolledEvent, value); }
1356 internal event EventHandler VScrolled
{
1357 add { Events.AddHandler (VScrolledEvent, value); }
1358 remove { Events.RemoveHandler (VScrolledEvent, value); }
1362 [EditorBrowsable(EditorBrowsableState
.Never
)]
1363 public new event EventHandler BackgroundImageChanged
{
1364 add { base.BackgroundImageChanged += value; }
1365 remove { base.BackgroundImageChanged -= value; }
1368 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
1369 public new event EventHandler Click
{
1370 add { base.Click += value; }
1371 remove { base.Click -= value; }
1374 // XXX should this not manipulate base.Paint?
1376 [EditorBrowsable(EditorBrowsableState
.Never
)]
1377 public new event PaintEventHandler Paint
;
1378 #endregion // Events
1380 #region Private Methods
1381 internal Document Document
{
1391 internal bool ShowSelection
{
1393 if (show_selection
|| !hide_selection
) {
1401 if (show_selection
== value)
1404 show_selection
= value;
1405 // Currently InvalidateSelectionArea is commented out so do a full invalidate
1406 document
.InvalidateSelectionArea();
1410 internal Graphics
CreateGraphicsInternal() {
1411 if (IsHandleCreated
) {
1412 return base.CreateGraphics();
1415 return Graphics
.FromImage(bmp
);
1422 internal override void OnPaintInternal (PaintEventArgs pevent
) {
1424 if (backcolor_set
|| (Enabled
&& !read_only
)) {
1425 pevent
.Graphics
.FillRectangle(ThemeEngine
.Current
.ResPool
.GetSolidBrush(BackColor
), pevent
.ClipRectangle
);
1427 pevent
.Graphics
.FillRectangle(ThemeEngine
.Current
.ResPool
.GetSolidBrush(ThemeEngine
.Current
.ColorControl
), pevent
.ClipRectangle
);
1430 // Draw the viewable document
1431 document
.Draw(pevent
.Graphics
, pevent
.ClipRectangle
);
1434 // OnPaint does not get raised on MS (see bug #80639)
1436 pevent
.Handled
= true;
1439 private bool IsDoubleClick (MouseEventArgs e
)
1441 TimeSpan interval
= DateTime
.Now
- click_last
;
1442 if (interval
.TotalMilliseconds
> SystemInformation
.DoubleClickTime
)
1444 Size dcs
= SystemInformation
.DoubleClickSize
;
1445 if (e
.X
< click_point_x
- dcs
.Width
/ 2 || e
.X
> click_point_x
+ dcs
.Width
/ 2)
1447 if (e
.Y
< click_point_y
- dcs
.Height
/ 2 || e
.Y
> click_point_y
+ dcs
.Height
/ 2)
1452 private void TextBoxBase_MouseDown (object sender
, MouseEventArgs e
)
1454 if (e
.Button
== MouseButtons
.Left
) {
1456 document
.PositionCaret(e
.X
+ document
.ViewPortX
, e
.Y
+ document
.ViewPortY
);
1458 if (IsDoubleClick (e
)) {
1459 switch (click_mode
) {
1460 case CaretSelection
.Position
:
1462 click_mode
= CaretSelection
.Word
;
1464 case CaretSelection
.Word
:
1466 if (this is TextBox
) {
1467 document
.SetSelectionToCaret (true);
1468 click_mode
= CaretSelection
.Position
;
1472 document
.ExpandSelection (CaretSelection
.Line
, false);
1473 click_mode
= CaretSelection
.Line
;
1475 case CaretSelection
.Line
:
1477 // Gotta do this first because Exanding to a word
1478 // from a line doesn't really work
1479 document
.SetSelectionToCaret (true);
1482 click_mode
= CaretSelection
.Word
;
1486 document
.SetSelectionToCaret (true);
1487 click_mode
= CaretSelection
.Position
;
1490 click_point_x
= e
.X
;
1491 click_point_y
= e
.Y
;
1492 click_last
= DateTime
.Now
;
1495 if ((e
.Button
== MouseButtons
.Middle
) && (((int)Environment
.OSVersion
.Platform
== 4) || ((int)Environment
.OSVersion
.Platform
== 128))) {
1496 Document
.Marker marker
;
1498 marker
.tag
= document
.FindCursor(e
.X
+ document
.ViewPortX
, e
.Y
+ document
.ViewPortY
, out marker
.pos
);
1499 marker
.line
= marker
.tag
.line
;
1500 marker
.height
= marker
.tag
.height
;
1502 document
.SetSelection(marker
.line
, marker
.pos
, marker
.line
, marker
.pos
);
1503 Paste (Clipboard
.GetDataObject (true), null, true);
1508 private void TextBoxBase_MouseUp(object sender
, MouseEventArgs e
) {
1509 if (e
.Button
== MouseButtons
.Left
) {
1510 if (click_mode
== CaretSelection
.Position
) {
1511 document
.SetSelectionToCaret(false);
1512 document
.DisplayCaret();
1515 if (scroll_timer
!= null) {
1516 scroll_timer
.Enabled
= false;
1522 private void PositionControls ()
1524 if (hscroll
.Visible
) {
1525 //vscroll.Maximum += hscroll.Height;
1526 canvas_height
= ClientSize
.Height
- hscroll
.Height
;
1528 canvas_height
= ClientSize
.Height
;
1531 if (vscroll
.Visible
) {
1532 //hscroll.Maximum += vscroll.Width;
1533 canvas_width
= ClientSize
.Width
- vscroll
.Width
;
1535 canvas_width
= ClientSize
.Width
;
1539 document
.ViewPortWidth
= canvas_width
;
1540 document
.ViewPortHeight
= canvas_height
;
1542 if (canvas_height
< 1 || canvas_width
< 1)
1545 // We always move them, they just might not be displayed
1546 hscroll
.Bounds
= new Rectangle (ClientRectangle
.Left
,
1547 Math
.Max (0, ClientRectangle
.Height
- hscroll
.Height
),
1548 Math
.Max (0, ClientSize
.Width
- (vscroll
.Visible
? vscroll
.Width
: 0)),
1551 vscroll
.Bounds
= new Rectangle (Math
.Max (0, ClientRectangle
.Right
- vscroll
.Width
),
1552 ClientRectangle
.Top
, vscroll
.Width
,
1553 Math
.Max (0, ClientSize
.Height
- (hscroll
.Visible
? hscroll
.Height
: 0)));
1557 private void TextBoxBase_SizeChanged(object sender
, EventArgs e
) {
1558 if (IsHandleCreated
)
1559 CalculateDocument ();
1562 private void TextBoxBase_MouseWheel(object sender
, MouseEventArgs e
) {
1564 if (!vscroll
.Enabled
) {
1569 vscroll
.Value
= Math
.Min (vscroll
.Value
+ SystemInformation
.MouseWheelScrollLines
,
1570 Math
.Max (0, vscroll
.Maximum
- document
.ViewPortHeight
+ 1));
1572 vscroll
.Value
= Math
.Max (0, vscroll
.Value
- SystemInformation
.MouseWheelScrollLines
);
1575 internal virtual void SelectWord ()
1577 StringBuilder s
= document
.caret
.line
.text
;
1578 int start
= document
.caret
.pos
;
1579 int end
= document
.caret
.pos
;
1582 if (document
.caret
.line
.line_no
>= document
.Lines
)
1584 Line line
= document
.GetLine (document
.caret
.line
.line_no
+ 1);
1585 document
.PositionCaret (line
, 0);
1594 // skip whitespace until we hit a word
1595 while (start
> 0 && s
[start
] == ' ')
1598 while (start
> 0 && (s
[start
] != ' '))
1600 if (s
[start
] == ' ')
1604 if (s
[end
] == ' ') {
1605 while (end
< s
.Length
&& s
[end
] == ' ')
1608 while (end
< s
.Length
&& s
[end
] != ' ')
1610 while (end
< s
.Length
&& s
[end
] == ' ')
1614 document
.SetSelection (document
.caret
.line
, start
, document
.caret
.line
, end
);
1615 document
.PositionCaret (document
.selection_end
.line
, document
.selection_end
.pos
);
1616 document
.DisplayCaret();
1619 internal void CalculateDocument() {
1621 document
.RecalculateDocument(CreateGraphicsInternal());
1622 CalculateScrollBars();
1624 if (document
.caret
.line
!= null && document
.caret
.line
.Y
< document
.ViewPortHeight
) {
1625 // The window has probably been resized, making the entire thing visible, so
1626 // we need to set the scroll position back to zero.
1633 internal void CalculateScrollBars () {
1634 // FIXME - need separate calculations for center and right alignment
1636 if (!document
.multiline
) {
1637 PositionControls ();
1641 if (document
.Width
>= document
.ViewPortWidth
) {
1642 hscroll
.SetValues (0, Math
.Max (1, document
.Width
), -1,
1643 document
.ViewPortWidth
< 0 ? 0 : document
.ViewPortWidth
);
1644 hscroll
.Enabled
= true;
1646 hscroll
.Enabled
= false;
1647 hscroll
.Maximum
= document
.ViewPortWidth
;
1650 if (document
.Height
>= document
.ViewPortHeight
) {
1651 vscroll
.SetValues (0, Math
.Max (1, document
.Height
), -1,
1652 document
.ViewPortHeight
< 0 ? 0 : document
.ViewPortHeight
);
1653 vscroll
.Enabled
= true;
1655 vscroll
.Enabled
= false;
1656 vscroll
.Maximum
= document
.ViewPortHeight
;
1661 if ((scrollbars
& RichTextBoxScrollBars
.Horizontal
) != 0) {
1662 if (((scrollbars
& RichTextBoxScrollBars
.ForcedHorizontal
) != 0) || hscroll
.Enabled
) {
1663 hscroll
.Visible
= true;
1665 hscroll
.Visible
= false;
1668 hscroll
.Visible
= false;
1672 if ((scrollbars
& RichTextBoxScrollBars
.Vertical
) != 0) {
1673 if (((scrollbars
& RichTextBoxScrollBars
.ForcedVertical
) != 0) || vscroll
.Enabled
) {
1674 vscroll
.Visible
= true;
1676 vscroll
.Visible
= false;
1679 vscroll
.Visible
= false;
1682 PositionControls ();
1685 private void document_WidthChanged(object sender
, EventArgs e
) {
1686 CalculateScrollBars();
1689 private void document_HeightChanged(object sender
, EventArgs e
) {
1690 CalculateScrollBars();
1693 private void hscroll_ValueChanged(object sender
, EventArgs e
) {
1696 old_viewport_x
= document
.ViewPortX
;
1697 document
.ViewPortX
= this.hscroll
.Value
;
1700 // Before scrolling we want to destroy the caret, then draw a new one after the scroll
1701 // the reason for this is that scrolling changes the coordinates of the caret, and we
1702 // will get tracers if we don't
1705 document
.CaretLostFocus ();
1707 if (vscroll
.Visible
) {
1708 XplatUI
.ScrollWindow(this.Handle
, new Rectangle(0, 0, ClientSize
.Width
- vscroll
.Width
, ClientSize
.Height
), old_viewport_x
- this.hscroll
.Value
, 0, false);
1710 XplatUI
.ScrollWindow(this.Handle
, ClientRectangle
, old_viewport_x
- this.hscroll
.Value
, 0, false);
1714 document
.CaretHasFocus ();
1716 EventHandler eh
= (EventHandler
)(Events
[HScrolledEvent
]);
1718 eh (this, EventArgs
.Empty
);
1721 private void vscroll_ValueChanged(object sender
, EventArgs e
) {
1724 old_viewport_y
= document
.ViewPortY
;
1725 document
.ViewPortY
= this.vscroll
.Value
;
1728 // Before scrolling we want to destroy the caret, then draw a new one after the scroll
1729 // the reason for this is that scrolling changes the coordinates of the caret, and we
1730 // will get tracers if we don't
1733 document
.CaretLostFocus ();
1735 if (hscroll
.Visible
) {
1736 XplatUI
.ScrollWindow(this.Handle
, new Rectangle(0, 0, ClientSize
.Width
, ClientSize
.Height
- hscroll
.Height
), 0, old_viewport_y
- this.vscroll
.Value
, false);
1738 XplatUI
.ScrollWindow(this.Handle
, ClientRectangle
, 0, old_viewport_y
- this.vscroll
.Value
, false);
1742 document
.CaretHasFocus ();
1744 EventHandler eh
= (EventHandler
)(Events
[VScrolledEvent
]);
1746 eh (this, EventArgs
.Empty
);
1749 private void TextBoxBase_MouseMove(object sender
, MouseEventArgs e
) {
1750 // FIXME - handle auto-scrolling if mouse is to the right/left of the window
1751 if (e
.Button
== MouseButtons
.Left
&& Capture
) {
1752 if (!ClientRectangle
.Contains (e
.X
, e
.Y
)) {
1753 if (scroll_timer
== null) {
1754 scroll_timer
= new Timer ();
1755 scroll_timer
.Interval
= 100;
1756 scroll_timer
.Tick
+= new EventHandler (ScrollTimerTickHandler
);
1759 if (!scroll_timer
.Enabled
) {
1760 scroll_timer
.Start ();
1762 // Force the first tick
1763 ScrollTimerTickHandler (null, EventArgs
.Empty
);
1767 document
.PositionCaret(e
.X
+ document
.ViewPortX
, e
.Y
+ document
.ViewPortY
);
1768 if (click_mode
== CaretSelection
.Position
) {
1769 document
.SetSelectionToCaret(false);
1770 document
.DisplayCaret();
1775 private void TextBoxBase_FontOrColorChanged(object sender
, EventArgs e
) {
1779 document
.SuspendRecalc ();
1780 // Font changes apply to the whole document
1781 for (int i
= 1; i
<= document
.Lines
; i
++) {
1782 line
= document
.GetLine(i
);
1783 LineTag
.FormatText(line
, 1, line
.text
.Length
, Font
,
1784 ThemeEngine
.Current
.ResPool
.GetSolidBrush(ForeColor
),
1785 null, FormatSpecified
.Font
| FormatSpecified
.Color
);
1787 document
.ResumeRecalc (false);
1789 // Make sure the caret height is matching the new font height
1790 document
.AlignCaret();
1794 private void ScrollTimerTickHandler (object sender
, EventArgs e
)
1796 Point pt
= Cursor
.Position
;
1798 pt
= PointToClient (pt
);
1800 if (pt
.X
< ClientRectangle
.Left
) {
1801 document
.MoveCaret(CaretDirection
.CharBackNoWrap
);
1802 document
.SetSelectionToCaret(false);
1804 CaretMoved(this, null);
1805 } else if (pt
.X
> ClientRectangle
.Right
) {
1806 document
.MoveCaret(CaretDirection
.CharForwardNoWrap
);
1807 document
.SetSelectionToCaret(false);
1809 CaretMoved(this, null);
1810 } else if (pt
.Y
> ClientRectangle
.Bottom
) {
1811 document
.MoveCaret(CaretDirection
.LineDown
);
1812 document
.SetSelectionToCaret(false);
1814 CaretMoved(this, null);
1815 } else if (pt
.Y
< ClientRectangle
.Top
) {
1816 document
.MoveCaret(CaretDirection
.LineUp
);
1817 document
.SetSelectionToCaret(false);
1819 CaretMoved(this, null);
1823 /// <summary>Ensure the caret is always visible</summary>
1824 internal void CaretMoved(object sender
, EventArgs e
) {
1828 if (canvas_width
< 1 || canvas_height
< 1)
1831 document
.MoveCaretToTextTag ();
1832 pos
= document
.Caret
;
1834 //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);
1837 // Horizontal scrolling:
1838 // If the caret moves to the left outside the visible area, we jump the document into view, not just one
1839 // character, but 1/3 of the width of the document
1840 // If the caret moves to the right outside the visible area, we scroll just enough to keep the caret visible
1842 // Handle horizontal scrolling
1843 if (document
.CaretLine
.alignment
== HorizontalAlignment
.Left
) {
1844 // Check if we moved out of view to the left
1845 if (pos
.X
< (document
.ViewPortX
)) {
1847 if ((hscroll
.Value
- document
.ViewPortWidth
/ 3) >= hscroll
.Minimum
) {
1848 hscroll
.Value
-= document
.ViewPortWidth
/ 3;
1850 hscroll
.Value
= hscroll
.Minimum
;
1852 } while (hscroll
.Value
> pos
.X
);
1855 // Check if we moved out of view to the right
1856 if ((pos
.X
>= (document
.ViewPortWidth
+ document
.ViewPortX
)) && (hscroll
.Value
!= hscroll
.Maximum
)) {
1857 if ((pos
.X
- document
.ViewPortWidth
+ 1) <= hscroll
.Maximum
) {
1858 if (pos
.X
- document
.ViewPortWidth
>= 0) {
1859 hscroll
.Value
= pos
.X
- document
.ViewPortWidth
+ 1;
1864 hscroll
.Value
= hscroll
.Maximum
;
1867 } else if (document
.CaretLine
.alignment
== HorizontalAlignment
.Right
) {
1868 // hscroll.Value = pos.X;
1870 // if ((pos.X > (this.canvas_width + document.ViewPortX)) && (hscroll.Enabled && (hscroll.Value != hscroll.Maximum))) {
1871 // hscroll.Value = hscroll.Maximum;
1874 // FIXME - implement center cursor alignment
1877 if (!document
.multiline
) {
1881 // Handle vertical scrolling
1882 height
= document
.CaretLine
.Height
+ 1;
1884 if (pos
.Y
< document
.ViewPortY
) {
1885 vscroll
.Value
= pos
.Y
;
1888 if ((pos
.Y
+ height
) > (document
.ViewPortY
+ canvas_height
)) {
1889 vscroll
.Value
= Math
.Max (0, pos
.Y
- canvas_height
+ height
);
1893 internal bool Paste(IDataObject clip
, DataFormats
.Format format
, bool obey_length
) {
1899 if (format
== null) {
1900 if ((this is RichTextBox
) && clip
.GetDataPresent(DataFormats
.Rtf
)) {
1901 format
= DataFormats
.GetFormat(DataFormats
.Rtf
);
1902 } else if ((this is RichTextBox
) && clip
.GetDataPresent (DataFormats
.Bitmap
)) {
1903 format
= DataFormats
.GetFormat (DataFormats
.Bitmap
);
1904 } else if (clip
.GetDataPresent(DataFormats
.UnicodeText
)) {
1905 format
= DataFormats
.GetFormat(DataFormats
.UnicodeText
);
1906 } else if (clip
.GetDataPresent(DataFormats
.Text
)) {
1907 format
= DataFormats
.GetFormat(DataFormats
.Text
);
1912 if ((format
.Name
== DataFormats
.Rtf
) && !(this is RichTextBox
)) {
1916 if (!clip
.GetDataPresent(format
.Name
)) {
1921 if (format
.Name
== DataFormats
.Rtf
) {
1922 document
.undo
.BeginUserAction (Locale
.GetText ("Paste"));
1923 ((RichTextBox
)this).SelectedRtf
= (string)clip
.GetData(DataFormats
.Rtf
);
1924 document
.undo
.EndUserAction ();
1926 } else if (format
.Name
== DataFormats
.Bitmap
) {
1927 document
.undo
.BeginUserAction (Locale
.GetText ("Paste"));
1928 // document.InsertImage (document.caret.line, document.caret.pos, (Image) clip.GetData (DataFormats.Bitmap));
1929 document
.MoveCaret (CaretDirection
.CharForward
);
1930 document
.undo
.EndUserAction ();
1932 } else if (format
.Name
== DataFormats
.UnicodeText
) {
1933 s
= (string)clip
.GetData(DataFormats
.UnicodeText
);
1934 } else if (format
.Name
== DataFormats
.Text
) {
1935 s
= (string)clip
.GetData(DataFormats
.Text
);
1941 document
.undo
.BeginUserAction (Locale
.GetText ("Paste"));
1942 this.SelectedText
= s
;
1943 document
.undo
.EndUserAction ();
1945 if ((s
.Length
+ document
.Length
) < max_length
) {
1946 document
.undo
.BeginUserAction (Locale
.GetText ("Paste"));
1947 this.SelectedText
= s
;
1948 document
.undo
.EndUserAction ();
1949 } else if (document
.Length
< max_length
) {
1950 document
.undo
.BeginUserAction (Locale
.GetText ("Paste"));
1951 this.SelectedText
= s
.Substring (0, max_length
- document
.Length
);
1952 document
.undo
.EndUserAction ();
1958 #endregion // Private Methods
1961 // This is called just before OnTextChanged is called.
1962 internal virtual void OnTextUpdate ()
1966 protected override void OnTextChanged (EventArgs e
)
1968 base.OnTextChanged (e
);
1971 public virtual int GetLineFromCharIndex (int index
)
1977 document
.CharIndexToLineTag (index
, out line_out
, out tag_out
, out pos
);
1979 return line_out
.LineNo
;
1982 protected override void OnMouseUp (MouseEventArgs e
)