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
;
38 namespace System
.Windows
.Forms
{
39 [DefaultEvent("TextChanged")]
40 [Designer("System.Windows.Forms.Design.TextBoxBaseDesigner, " + Consts
.AssemblySystem_Design
)]
41 public abstract class TextBoxBase
: Control
{
42 #region Local Variables
43 internal HorizontalAlignment alignment
;
44 internal bool accepts_tab
;
45 internal bool accepts_return
;
46 internal bool auto_size
;
47 internal bool backcolor_set
;
48 internal CharacterCasing character_casing
;
50 internal bool hide_selection
;
51 internal int max_length
;
52 internal bool modified
;
53 internal bool multiline
;
54 internal char password_char
;
55 internal bool read_only
;
56 internal bool word_wrap
;
57 internal Document document
;
58 internal LineTag caret_tag
; // tag our cursor is in
59 internal int caret_pos
; // position on the line our cursor is in (can be 0 = beginning of line)
60 internal ImplicitHScrollBar hscroll
;
61 internal ImplicitVScrollBar vscroll
;
62 internal RichTextBoxScrollBars scrollbars
;
63 internal Timer scroll_timer
;
64 internal bool richtext
;
65 internal bool show_selection
; // set to true to always show selection, even if no focus is set
66 internal int selection_length
; // set to the user-specified selection length, or -1 if none
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 CaretSelection click_mode
;
76 internal static bool draw_lines
= false;
79 #endregion // Local Variables
81 #region Internal Constructor
82 // Constructor will go when complete, only for testing - pdb
83 internal TextBoxBase() {
84 alignment
= HorizontalAlignment
.Left
;
85 accepts_return
= false;
88 border_style
= BorderStyle
.Fixed3D
;
89 character_casing
= CharacterCasing
.Normal
;
91 hide_selection
= true;
99 show_selection
= false;
100 document
= new Document(this);
101 document
.WidthChanged
+= new EventHandler(document_WidthChanged
);
102 document
.HeightChanged
+= new EventHandler(document_HeightChanged
);
103 //document.CaretMoved += new EventHandler(CaretMoved);
104 document
.Wrap
= false;
105 requested_height
= -1;
106 click_last
= DateTime
.Now
;
107 click_mode
= CaretSelection
.Position
;
108 bmp
= new Bitmap(1, 1, System
.Drawing
.Imaging
.PixelFormat
.Format32bppArgb
);
110 MouseDown
+= new MouseEventHandler(TextBoxBase_MouseDown
);
111 MouseUp
+= new MouseEventHandler(TextBoxBase_MouseUp
);
112 MouseMove
+= new MouseEventHandler(TextBoxBase_MouseMove
);
113 SizeChanged
+= new EventHandler(TextBoxBase_SizeChanged
);
114 FontChanged
+= new EventHandler(TextBoxBase_FontOrColorChanged
);
115 ForeColorChanged
+= new EventHandler(TextBoxBase_FontOrColorChanged
);
116 MouseWheel
+= new MouseEventHandler(TextBoxBase_MouseWheel
);
118 scrollbars
= RichTextBoxScrollBars
.None
;
120 hscroll
= new ImplicitHScrollBar();
121 hscroll
.ValueChanged
+= new EventHandler(hscroll_ValueChanged
);
122 hscroll
.control_style
&= ~ControlStyles
.Selectable
;
123 hscroll
.Enabled
= false;
124 hscroll
.Visible
= false;
125 hscroll
.Maximum
= Int32
.MaxValue
;
127 vscroll
= new ImplicitVScrollBar();
128 vscroll
.ValueChanged
+= new EventHandler(vscroll_ValueChanged
);
129 vscroll
.control_style
&= ~ControlStyles
.Selectable
;
130 vscroll
.Enabled
= false;
131 vscroll
.Visible
= false;
132 vscroll
.Maximum
= Int32
.MaxValue
;
135 this.Controls
.AddImplicit (hscroll
);
136 this.Controls
.AddImplicit (vscroll
);
139 SetStyle(ControlStyles
.UserPaint
| ControlStyles
.StandardClick
, false);
141 SetStyle(ControlStyles
.UseTextForAccessibility
, false);
144 canvas_width
= ClientSize
.Width
;
145 canvas_height
= ClientSize
.Height
;
146 document
.ViewPortWidth
= canvas_width
;
147 document
.ViewPortHeight
= canvas_height
;
149 Cursor
= Cursors
.IBeam
;
151 CalculateScrollBars();
153 #endregion // Internal Constructor
155 #region Private and Internal Methods
156 internal string CaseAdjust(string s
) {
157 if (character_casing
== CharacterCasing
.Normal
) {
160 if (character_casing
== CharacterCasing
.Lower
) {
167 internal override void HandleClick(int clicks
, MouseEventArgs me
) {
168 // MS seems to fire the click event in spite of the styles they set
169 control_style
|= ControlStyles
.StandardClick
| ControlStyles
.StandardDoubleClick
;
170 base.HandleClick (clicks
, me
);
171 control_style ^
= ControlStyles
.StandardClick
| ControlStyles
.StandardDoubleClick
;
174 #endregion // Private and Internal Methods
176 #region Public Instance Properties
177 [DefaultValue(false)]
178 [MWFCategory("Behavior")]
179 public bool AcceptsTab
{
185 if (value != accepts_tab
) {
187 OnAcceptsTabChanged(EventArgs
.Empty
);
194 [RefreshProperties(RefreshProperties
.Repaint
)]
195 [MWFCategory("Behavior")]
196 public virtual bool AutoSize
{
202 if (value != auto_size
) {
205 if (PreferredHeight
!= ClientSize
.Height
) {
206 ClientSize
= new Size(ClientSize
.Width
, PreferredHeight
);
209 OnAutoSizeChanged(EventArgs
.Empty
);
215 public override System
.Drawing
.Color BackColor
{
217 return base.BackColor
;
220 if (value != ThemeEngine
.Current
.ColorWindow
) {
221 backcolor_set
= true;
223 backcolor_set
= false;
225 base.BackColor
= value;
230 [EditorBrowsable(EditorBrowsableState
.Never
)]
231 public override System
.Drawing
.Image BackgroundImage
{
233 return base.BackgroundImage
;
236 base.BackgroundImage
= value;
240 [DefaultValue(BorderStyle
.Fixed3D
)]
242 [MWFCategory("Appearance")]
243 public BorderStyle BorderStyle
{
244 get { return InternalBorderStyle; }
246 InternalBorderStyle
= value;
247 OnBorderStyleChanged(EventArgs
.Empty
);
252 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
253 public bool CanUndo
{
260 public override System
.Drawing
.Color ForeColor
{
262 return base.ForeColor
;
265 base.ForeColor
= value;
270 [MWFCategory("Behavior")]
271 public bool HideSelection
{
273 return hide_selection
;
277 if (value != hide_selection
) {
278 hide_selection
= value;
279 OnHideSelectionChanged(EventArgs
.Empty
);
281 if (hide_selection
) {
282 document
.selection_visible
= false;
284 document
.selection_visible
= true;
286 document
.InvalidateSelectionArea();
291 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
292 [Editor("System.Windows.Forms.Design.StringArrayEditor, " + Consts
.AssemblySystem_Design
, typeof(System
.Drawing
.Design
.UITypeEditor
))]
294 [MWFCategory("Appearance")]
295 public string[] Lines
{
303 // Handle empty document
304 if ((l
== 1) && (document
.GetLine(1).text
.Length
== 0)) {
305 return new string[0];
308 lines
= new string[l
];
310 for (i
= 1; i
<= l
; i
++) {
311 lines
[i
- 1] = document
.GetLine(i
).text
.ToString();
325 brush
= ThemeEngine
.Current
.ResPool
.GetSolidBrush(this.ForeColor
);
327 for (i
= 0; i
< l
; i
++) {
328 document
.Add(i
+1, CaseAdjust(value[i
]), alignment
, Font
, brush
);
331 OnTextChanged(EventArgs
.Empty
);
335 [DefaultValue(32767)]
337 [MWFCategory("Behavior")]
338 public virtual int MaxLength
{
340 if (max_length
== 2147483646) { // We don't distinguish between single and multi-line limits
347 if (value != max_length
) {
354 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
355 public bool Modified
{
361 if (value != modified
) {
363 OnModifiedChanged(EventArgs
.Empty
);
368 [DefaultValue(false)]
370 [RefreshProperties(RefreshProperties
.All
)]
371 [MWFCategory("Behavior")]
372 public virtual bool Multiline
{
378 if (value != multiline
) {
380 // Make sure we update our size; the user may have already set the size before going to multiline
381 if (multiline
&& requested_height
!= -1) {
382 Height
= requested_height
;
383 requested_height
= -1;
386 OnMultilineChanged(EventArgs
.Empty
);
389 document
.multiline
= multiline
;
392 document
.Wrap
= word_wrap
;
393 document
.PasswordChar
= "";
396 document
.Wrap
= false;
397 if (this.password_char
!= '\0') {
398 document
.PasswordChar
= password_char
.ToString();
400 document
.PasswordChar
= "";
407 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
408 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
409 public int PreferredHeight
{
411 return this.Font
.Height
+ 7; // FIXME - consider border style as well
415 [DefaultValue(false)]
416 [MWFCategory("Behavior")]
417 public bool ReadOnly
{
423 if (value != read_only
) {
425 OnReadOnlyChanged(EventArgs
.Empty
);
431 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
432 public virtual string SelectedText
{
434 return document
.GetSelection();
439 document
.ReplaceSelection(CaseAdjust(value), false);
440 // document.PositionCaret (document.selection_end.line, document.selection_end.pos);
442 OnTextChanged(EventArgs
.Empty
);
448 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
449 public virtual int SelectionLength
{
451 return document
.SelectionLength();
456 throw new ArgumentException(String
.Format("{0} is not a valid value", value), "value");
465 selection_length
= value;
467 start
= document
.LineTagToCharIndex(document
.selection_start
.line
, document
.selection_start
.pos
);
469 document
.CharIndexToLineTag(start
+ value, out line
, out tag
, out pos
);
470 document
.SetSelectionEnd(line
, pos
);
471 document
.PositionCaret(line
, pos
);
473 selection_length
= -1;
475 document
.SetSelectionEnd(document
.selection_start
.line
, document
.selection_start
.pos
);
476 document
.PositionCaret(document
.selection_start
.line
, document
.selection_start
.pos
);
482 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
483 public int SelectionStart
{
487 index
= document
.LineTagToCharIndex(document
.selection_start
.line
, document
.selection_start
.pos
);
493 document
.SetSelectionStart(value);
494 if (selection_length
> -1 ) {
495 document
.SetSelectionEnd(value + selection_length
);
497 document
.SetSelectionEnd(value);
499 document
.PositionCaret(document
.selection_start
.line
, document
.selection_start
.pos
);
505 public override string Text
{
507 if (document
== null || document
.Root
== null || document
.Root
.text
== null) {
512 return document
.Root
.text
.ToString();
517 sb
= new StringBuilder();
520 for (i
= 1; i
< document
.Lines
; i
++) {
521 if (line
!= null && !line
.soft_break
)
522 sb
.Append (Environment
.NewLine
);
523 line
= document
.GetLine (i
);
524 sb
.Append(line
.text
.ToString());
526 sb
.Append(document
.GetLine(document
.Lines
).text
.ToString());
527 return sb
.ToString();
535 if ((value != null) && (value != "")) {
541 lines
= value.Split(new char[] {'\n'}
);
543 for (int i
= 0; i
< lines
.Length
; i
++) {
544 if (lines
[i
].EndsWith("\r")) {
545 lines
[i
] = lines
[i
].Substring(0, lines
[i
].Length
- 1);
550 document
.PositionCaret (document
.GetLine (1), 0);
551 document
.SetSelectionToCaret (true);
556 document
.Add(1, CaseAdjust(value), alignment
, Font
, ThemeEngine
.Current
.ResPool
.GetSolidBrush(ForeColor
));
559 document
.PositionCaret (document
.GetLine (1), 0);
560 document
.SetSelectionToCaret (true);
569 OnTextChanged(EventArgs
.Empty
);
574 public virtual int TextLength
{
576 if (document
== null || document
.Root
== null || document
.Root
.text
== null) {
581 return document
.Root
.text
.Length
;
587 for (i
= 1; i
< document
.Lines
; i
++) {
588 total
+= document
.GetLine(i
).text
.Length
+ Environment
.NewLine
.Length
;
590 total
+= document
.GetLine(i
).text
.Length
;
599 [MWFCategory("Behavior")]
600 public bool WordWrap
{
606 if (value != word_wrap
) {
609 document
.Wrap
= value;
614 #endregion // Public Instance Properties
616 #region Protected Instance Properties
617 protected override CreateParams CreateParams
{
619 return base.CreateParams
;
623 protected override System
.Drawing
.Size DefaultSize
{
625 return new Size(100, 20);
628 #endregion // Protected Instance Properties
630 #region Public Instance Methods
631 public void AppendText(string text
) {
633 // Grab the formatting for the last element
634 document
.MoveCaret(CaretDirection
.CtrlEnd
);
636 if (document
.CaretTag
.next
!= null) {
637 document
.CaretTag
= document
.CaretTag
.next
;
639 document
.Insert(document
.CaretLine
, document
.CaretTag
, document
.CaretPosition
, false, text
);
643 document
.MoveCaret(CaretDirection
.CtrlEnd
);
644 document
.InsertStringAtCaret(text
, true);
649 document
.MoveCaret(CaretDirection
.CtrlEnd
);
650 document
.SetSelectionStart(document
.CaretLine
, document
.CaretPosition
);
651 document
.SetSelectionEnd(document
.CaretLine
, document
.CaretPosition
);
652 selection_length
= -1;
654 OnTextChanged(EventArgs
.Empty
);
657 public void Clear() {
661 public void ClearUndo() {
662 document
.undo
.Clear();
668 o
= new DataObject(DataFormats
.Text
, SelectedText
);
669 if (this is RichTextBox
) {
670 o
.SetData(DataFormats
.Rtf
, ((RichTextBox
)this).SelectedRtf
);
672 Clipboard
.SetDataObject(o
);
678 o
= new DataObject(DataFormats
.Text
, SelectedText
);
679 if (this is RichTextBox
) {
680 o
.SetData(DataFormats
.Rtf
, ((RichTextBox
)this).SelectedRtf
);
682 Clipboard
.SetDataObject(o
);
683 document
.ReplaceSelection("", false);
686 public void Paste() {
687 Paste(Clipboard
.GetDataObject(), null, false);
690 public void ScrollToCaret() {
691 if (IsHandleCreated
) {
692 CaretMoved(this, EventArgs
.Empty
);
696 public void Select(int start
, int length
) {
697 SelectionStart
= start
;
698 SelectionLength
= length
;
702 public void SelectAll() {
705 last
= document
.GetLine(document
.Lines
);
706 document
.SetSelectionStart(document
.GetLine(1), 0);
707 document
.SetSelectionEnd(last
, last
.text
.Length
);
708 selection_length
= -1;
711 public override string ToString() {
712 return String
.Concat (base.ToString (), ", Text: ", Text
);
716 document
.undo
.Undo();
718 #endregion // Public Instance Methods
720 #region Protected Instance Methods
721 protected override void CreateHandle() {
722 base.CreateHandle ();
723 document
.AlignCaret();
727 protected override bool IsInputKey(Keys keyData
) {
728 if ((keyData
& Keys
.Alt
) != 0) {
729 return base.IsInputKey(keyData
);
732 switch (keyData
& Keys
.KeyCode
) {
734 if (multiline
&& accepts_return
) {
741 if (accepts_tab
&& multiline
) {
742 if ((keyData
& Keys
.Control
) == 0) {
764 protected virtual void OnAcceptsTabChanged(EventArgs e
) {
765 if (AcceptsTabChanged
!= null) {
766 AcceptsTabChanged(this, e
);
770 protected virtual void OnAutoSizeChanged(EventArgs e
) {
771 if (AutoSizeChanged
!= null) {
772 AutoSizeChanged(this, e
);
776 protected virtual void OnBorderStyleChanged(EventArgs e
) {
777 if (BorderStyleChanged
!= null) {
778 BorderStyleChanged(this, e
);
782 protected override void OnFontChanged(EventArgs e
) {
783 base.OnFontChanged (e
);
785 if (auto_size
&& !multiline
) {
786 if (PreferredHeight
!= ClientSize
.Height
) {
787 Height
= PreferredHeight
;
792 protected override void OnHandleCreated(EventArgs e
) {
793 base.OnHandleCreated (e
);
796 protected override void OnHandleDestroyed(EventArgs e
) {
797 base.OnHandleDestroyed (e
);
800 protected virtual void OnHideSelectionChanged(EventArgs e
) {
801 if (HideSelectionChanged
!= null) {
802 HideSelectionChanged(this, e
);
806 protected virtual void OnModifiedChanged(EventArgs e
) {
807 if (ModifiedChanged
!= null) {
808 ModifiedChanged(this, e
);
812 protected virtual void OnMultilineChanged(EventArgs e
) {
813 if (MultilineChanged
!= null) {
814 MultilineChanged(this, e
);
818 protected virtual void OnReadOnlyChanged(EventArgs e
) {
819 if (ReadOnlyChanged
!= null) {
820 ReadOnlyChanged(this, e
);
824 protected override bool ProcessDialogKey(Keys keyData
) {
825 return base.ProcessDialogKey(keyData
);
828 private bool ProcessKey(Keys keyData
) {
832 control
= (Control
.ModifierKeys
& Keys
.Control
) != 0;
833 shift
= (Control
.ModifierKeys
& Keys
.Shift
) != 0;
835 switch (keyData
& Keys
.KeyCode
) {
836 case Keys
.X
: { // Cut (Ctrl-X)
844 case Keys
.C
: { // Copy (Ctrl-C)
852 case Keys
.V
: { // Paste (Ctrl-V)
854 return Paste(Clipboard
.GetDataObject(), null, true);
859 case Keys
.Z
: { // Undo (Ctrl-Z)
867 case Keys
.A
: { // Select All (Ctrl-A)
877 document
.MoveCaret(CaretDirection
.WordBack
);
879 if (!document
.selection_visible
|| shift
) {
880 document
.MoveCaret(CaretDirection
.CharBack
);
882 document
.MoveCaret(CaretDirection
.SelectionStart
);
887 document
.SetSelectionToCaret(true);
889 document
.SetSelectionToCaret(false);
892 CaretMoved(this, null);
898 document
.MoveCaret(CaretDirection
.WordForward
);
900 if (!document
.selection_visible
|| shift
) {
901 document
.MoveCaret(CaretDirection
.CharForward
);
903 document
.MoveCaret(CaretDirection
.SelectionEnd
);
907 document
.SetSelectionToCaret(true);
909 document
.SetSelectionToCaret(false);
912 CaretMoved(this, null);
918 if (document
.CaretPosition
== 0) {
919 document
.MoveCaret(CaretDirection
.LineUp
);
921 document
.MoveCaret(CaretDirection
.Home
);
924 document
.MoveCaret(CaretDirection
.LineUp
);
927 if ((Control
.ModifierKeys
& Keys
.Shift
) == 0) {
928 document
.SetSelectionToCaret(true);
930 document
.SetSelectionToCaret(false);
933 CaretMoved(this, null);
939 if (document
.CaretPosition
== document
.CaretLine
.Text
.Length
) {
940 document
.MoveCaret(CaretDirection
.LineDown
);
942 document
.MoveCaret(CaretDirection
.End
);
945 document
.MoveCaret(CaretDirection
.LineDown
);
948 if ((Control
.ModifierKeys
& Keys
.Shift
) == 0) {
949 document
.SetSelectionToCaret(true);
951 document
.SetSelectionToCaret(false);
954 CaretMoved(this, null);
959 if ((Control
.ModifierKeys
& Keys
.Control
) != 0) {
960 document
.MoveCaret(CaretDirection
.CtrlHome
);
962 document
.MoveCaret(CaretDirection
.Home
);
965 if ((Control
.ModifierKeys
& Keys
.Shift
) == 0) {
966 document
.SetSelectionToCaret(true);
968 document
.SetSelectionToCaret(false);
971 CaretMoved(this, null);
976 if ((Control
.ModifierKeys
& Keys
.Control
) != 0) {
977 document
.MoveCaret(CaretDirection
.CtrlEnd
);
979 document
.MoveCaret(CaretDirection
.End
);
982 if ((Control
.ModifierKeys
& Keys
.Shift
) == 0) {
983 document
.SetSelectionToCaret(true);
985 document
.SetSelectionToCaret(false);
988 CaretMoved(this, null);
993 // ignoring accepts_return, fixes bug #76355
994 if (!read_only
&& multiline
&& (accepts_return
|| (FindForm() != null && FindForm().AcceptButton
== null) || ((Control
.ModifierKeys
& Keys
.Control
) != 0))) {
997 if (document
.selection_visible
) {
998 document
.ReplaceSelection("", false);
1001 line
= document
.CaretLine
;
1003 document
.Split(document
.CaretLine
, document
.CaretTag
, document
.CaretPosition
, false);
1004 OnTextChanged(EventArgs
.Empty
);
1005 document
.UpdateView(line
, 2, 0);
1006 document
.MoveCaret(CaretDirection
.CharForward
);
1007 document
.SetSelectionToCaret(true);
1008 CaretMoved(this, null);
1015 if (!read_only
&& accepts_tab
&& multiline
) {
1016 document
.InsertChar(document
.CaretLine
, document
.CaretPosition
, '\t');
1017 if (document
.selection_visible
) {
1018 document
.ReplaceSelection("", false);
1020 document
.SetSelectionToCaret(true);
1022 OnTextChanged(EventArgs
.Empty
);
1023 CaretMoved(this, null);
1031 Paste(Clipboard
.GetDataObject(), null, true);
1040 // FIXME - need overwrite/insert toggle?
1045 if ((Control
.ModifierKeys
& Keys
.Control
) != 0) {
1046 document
.MoveCaret(CaretDirection
.CtrlPgUp
);
1048 document
.MoveCaret(CaretDirection
.PgUp
);
1053 case Keys
.PageDown
: {
1054 if ((Control
.ModifierKeys
& Keys
.Control
) != 0) {
1055 document
.MoveCaret(CaretDirection
.CtrlPgDn
);
1057 document
.MoveCaret(CaretDirection
.PgDn
);
1072 if (document
.selection_visible
) {
1073 document
.ReplaceSelection("", false);
1075 // DeleteChar only deletes on the line, doesn't do the combine
1076 if (document
.CaretPosition
== document
.CaretLine
.Text
.Length
) {
1077 if (document
.CaretLine
.LineNo
< document
.Lines
) {
1080 line
= document
.GetLine(document
.CaretLine
.LineNo
+ 1);
1081 document
.Combine(document
.CaretLine
, line
);
1082 document
.UpdateView(document
.CaretLine
, 2, 0);
1088 check_first
= document
.GetLine(document
.CaretLine
.LineNo
);
1089 check_second
= document
.GetLine(check_first
.line_no
+ 1);
1091 Console
.WriteLine("Post-UpdateView: Y of first line: {0}, second line: {1}", check_first
.Y
, check_second
.Y
);
1094 // Caret doesn't move
1098 document
.DeleteChar(document
.CaretTag
, document
.CaretPosition
, true);
1102 end_pos
= document
.CaretPosition
;
1104 while ((end_pos
< document
.CaretLine
.Text
.Length
) && !Document
.IsWordSeparator(document
.CaretLine
.Text
[end_pos
])) {
1108 if (end_pos
< document
.CaretLine
.Text
.Length
) {
1111 document
.DeleteChars(document
.CaretTag
, document
.CaretPosition
, end_pos
- document
.CaretPosition
);
1116 OnTextChanged(EventArgs
.Empty
);
1117 document
.AlignCaret();
1118 document
.UpdateCaret();
1119 CaretMoved(this, null);
1126 private void HandleBackspace(bool control
) {
1129 fire_changed
= false;
1131 // delete only deletes on the line, doesn't do the combine
1132 if (document
.selection_visible
) {
1133 document
.ReplaceSelection("", false);
1134 fire_changed
= true;
1136 document
.SetSelectionToCaret(true);
1138 if (document
.CaretPosition
== 0) {
1139 if (document
.CaretLine
.LineNo
> 1) {
1143 line
= document
.GetLine(document
.CaretLine
.LineNo
- 1);
1144 new_caret_pos
= line
.text
.Length
;
1146 document
.Combine(line
, document
.CaretLine
);
1147 document
.UpdateView(line
, 1, 0);
1148 document
.PositionCaret(line
, new_caret_pos
);
1149 //document.MoveCaret(CaretDirection.CharForward);
1150 document
.UpdateCaret();
1151 fire_changed
= true;
1154 if (!control
|| document
.CaretPosition
== 0) {
1155 document
.DeleteChar(document
.CaretTag
, document
.CaretPosition
, false);
1156 document
.MoveCaret(CaretDirection
.CharBack
);
1160 start_pos
= document
.CaretPosition
- 1;
1162 while ((start_pos
> 0) && !Document
.IsWordSeparator(document
.CaretLine
.Text
[start_pos
- 1])) {
1165 document
.DeleteChars(document
.CaretTag
, start_pos
, document
.CaretPosition
- start_pos
);
1166 document
.PositionCaret(document
.CaretLine
, start_pos
);
1168 document
.UpdateCaret();
1169 fire_changed
= true;
1172 OnTextChanged(EventArgs
.Empty
);
1174 CaretMoved(this, null);
1177 protected override void SetBoundsCore(int x
, int y
, int width
, int height
, BoundsSpecified specified
) {
1178 // Make sure we don't get sized bigger than we want to be
1181 if (height
!= PreferredHeight
) {
1182 requested_height
= height
;
1183 height
= PreferredHeight
;
1184 specified
|= BoundsSpecified
.Height
;
1189 base.SetBoundsCore (x
, y
, width
, height
, specified
);
1192 protected override void WndProc(ref Message m
) {
1193 switch ((Msg
)m
.Msg
) {
1194 case Msg
.WM_KEYDOWN
: {
1195 if (ProcessKeyMessage(ref m
) || ProcessKey((Keys
)m
.WParam
.ToInt32() | XplatUI
.State
.ModifierKeys
)) {
1196 m
.Result
= IntPtr
.Zero
;
1206 if (ProcessKeyMessage(ref m
)) {
1207 m
.Result
= IntPtr
.Zero
;
1215 m
.Result
= IntPtr
.Zero
;
1217 ch
= m
.WParam
.ToInt32();
1220 HandleBackspace(true);
1221 } else if (ch
>= 32) {
1222 if (document
.selection_visible
) {
1223 document
.ReplaceSelection("", false);
1226 char c
= (char)m
.WParam
;
1227 switch (character_casing
) {
1228 case CharacterCasing
.Upper
:
1229 c
= Char
.ToUpper((char) m
.WParam
);
1231 case CharacterCasing
.Lower
:
1232 c
= Char
.ToLower((char) m
.WParam
);
1236 if (document
.Length
< max_length
) {
1237 document
.InsertCharAtCaret(c
, true);
1238 OnTextChanged(EventArgs
.Empty
);
1239 CaretMoved(this, null);
1241 XplatUI
.AudibleAlert();
1244 } else if (ch
== 8) {
1245 HandleBackspace(false);
1252 base.WndProc(ref m
);
1258 #endregion // Protected Instance Methods
1261 public event EventHandler AcceptsTabChanged
;
1262 public event EventHandler AutoSizeChanged
;
1264 [EditorBrowsable(EditorBrowsableState
.Never
)]
1265 public new event EventHandler BackgroundImageChanged
{
1266 add { base.BackgroundImageChanged += value; }
1267 remove { base.BackgroundImageChanged -= value; }
1269 public event EventHandler BorderStyleChanged
;
1271 [EditorBrowsable(EditorBrowsableState
.Advanced
)]
1272 public event EventHandler Click
{
1273 add { base.Click += value; }
1274 remove { base.Click -= value; }
1277 public event EventHandler HideSelectionChanged
;
1278 public event EventHandler ModifiedChanged
;
1279 public event EventHandler MultilineChanged
;
1281 [EditorBrowsable(EditorBrowsableState
.Never
)]
1282 public event PaintEventHandler Paint
;
1283 public event EventHandler ReadOnlyChanged
;
1285 internal event EventHandler HScrolled
;
1286 internal event EventHandler VScrolled
;
1287 #endregion // Events
1289 #region Private Methods
1290 internal Document Document
{
1300 internal bool ShowSelection
{
1302 if (show_selection
) {
1310 if (show_selection
== value)
1313 show_selection
= value;
1314 // Currently InvalidateSelectionArea is commented out so do a full invalidate
1315 document
.InvalidateSelectionArea();
1319 internal Graphics
CreateGraphicsInternal() {
1320 if (IsHandleCreated
) {
1321 return base.CreateGraphics();
1324 return Graphics
.FromImage(bmp
);
1331 internal override void OnPaintInternal (PaintEventArgs pevent
) {
1333 if (backcolor_set
|| (Enabled
&& !read_only
)) {
1334 pevent
.Graphics
.FillRectangle(ThemeEngine
.Current
.ResPool
.GetSolidBrush(BackColor
), pevent
.ClipRectangle
);
1336 pevent
.Graphics
.FillRectangle(ThemeEngine
.Current
.ResPool
.GetSolidBrush(ThemeEngine
.Current
.ColorControl
), pevent
.ClipRectangle
);
1338 pevent
.Graphics
.TextRenderingHint
=TextRenderingHint
.AntiAlias
;
1340 // Draw the viewable document
1341 document
.Draw(pevent
.Graphics
, pevent
.ClipRectangle
);
1343 Rectangle rect
= ClientRectangle
;
1346 //pevent.Graphics.DrawRectangle(ThemeEngine.Current.ResPool.GetPen(ThemeEngine.Current.ColorControlDark), rect);
1355 p
= new Pen(Color
.Red
, 1);
1357 // First, figure out from what line to what line we need to draw
1358 start
= document
.GetLineByPixel(pevent
.ClipRectangle
.Top
- document
.ViewPortY
, false).line_no
;
1359 end
= document
.GetLineByPixel(pevent
.ClipRectangle
.Bottom
- document
.ViewPortY
, false).line_no
;
1361 //Console.WriteLine("Starting drawing on line '{0}'", document.GetLine(start));
1362 //Console.WriteLine("Ending drawing on line '{0}'", document.GetLine(end));
1365 while (line_no
<= end
) {
1366 line
= document
.GetLine(line_no
);
1369 for (int i
= 0; i
< line
.text
.Length
; i
++) {
1370 pevent
.Graphics
.DrawLine(p
, (int)line
.widths
[i
] - document
.ViewPortX
, line
.Y
- document
.ViewPortY
, (int)line
.widths
[i
] - document
.ViewPortX
, line
.Y
+ line
.height
- document
.ViewPortY
);
1379 internal override void OnGotFocusInternal (EventArgs e
)
1381 document
.CaretHasFocus ();
1382 base.OnGotFocusInternal (e
);
1385 internal override void OnLostFocusInternal (EventArgs e
)
1387 document
.CaretLostFocus ();
1388 base.OnLostFocusInternal (e
);
1391 private void TextBoxBase_MouseDown(object sender
, MouseEventArgs e
) {
1392 if (e
.Button
== MouseButtons
.Left
) {
1395 interval
= DateTime
.Now
- click_last
;
1396 document
.PositionCaret(e
.X
+ document
.ViewPortX
, e
.Y
+ document
.ViewPortY
);
1398 // Handle place caret/select word/select line behaviour
1399 if (e
.Clicks
== 1) {
1400 if (SystemInformation
.DoubleClickTime
< interval
.TotalMilliseconds
) {
1402 Console
.WriteLine("Single Click Invalidating from char {0} to char {1} ({2})", document
.selection_start
.pos
, document
.selection_end
.pos
, document
.selection_start
.line
.text
.ToString(document
.selection_start
.pos
, document
.selection_end
.pos
- document
.selection_start
.pos
));
1404 document
.SetSelectionToCaret(true);
1405 click_mode
= CaretSelection
.Position
;
1406 } else if (this is RichTextBox
) {
1408 Console
.WriteLine("Tripple Click Selecting line");
1410 document
.ExpandSelection(CaretSelection
.Line
, false);
1411 click_mode
= CaretSelection
.Line
;
1413 document
.SetSelectionToCaret(true);
1416 // We select the line if the word is already selected, and vice versa
1417 if (click_mode
!= CaretSelection
.Word
) {
1418 if (click_mode
== CaretSelection
.Line
) {
1419 document
.Invalidate(document
.selection_start
.line
, 0, document
.selection_start
.line
, document
.selection_start
.line
.text
.Length
);
1421 click_mode
= CaretSelection
.Word
;
1424 } else if (this is RichTextBox
) {
1425 click_mode
= CaretSelection
.Line
;
1426 document
.ExpandSelection(CaretSelection
.Line
, false); // Setting initial selection
1431 click_last
= DateTime
.Now
;
1435 if ((e
.Button
== MouseButtons
.Middle
) && (((int)Environment
.OSVersion
.Platform
== 4) || ((int)Environment
.OSVersion
.Platform
== 128))) {
1436 Document
.Marker marker
;
1438 marker
.tag
= document
.FindCursor(e
.X
+ document
.ViewPortX
, e
.Y
+ document
.ViewPortY
, out marker
.pos
);
1439 marker
.line
= marker
.tag
.line
;
1440 marker
.height
= marker
.tag
.height
;
1442 document
.SetSelection(marker
.line
, marker
.pos
, marker
.line
, marker
.pos
);
1443 Paste (Clipboard
.GetDataObject (true), null, true);
1452 if (e
.Button
== MouseButtons
.Right
) {
1453 draw_lines
= !draw_lines
;
1455 Console
.WriteLine("SelectedText: {0}, length {1}", this.SelectedText
, this.SelectionLength
);
1456 Console
.WriteLine("Selection start: {0}", this.SelectionStart
);
1458 this.SelectionStart
= 10;
1459 this.SelectionLength
= 5;
1464 tag
= document
.FindTag(e
.X
+ document
.ViewPortX
, e
.Y
+ document
.ViewPortY
, out pos
, false);
1466 Console
.WriteLine("Click found tag {0}, character {1}", tag
, pos
);
1469 case 4: LineTag
.FormatText(tag
.line
, pos
, (pos
+10)<line
.Text
.Length
? 10 : line
.Text
.Length
- pos
+1, new Font("impact", 20, FontStyle
.Bold
, GraphicsUnit
.Pixel
), ThemeEngine
.Current
.ResPool
.GetSolidBrush(Color
.Red
)); break;
1470 case 1: LineTag
.FormatText(tag
.line
, pos
, (pos
+10)<line
.Text
.Length
? 10 : line
.Text
.Length
- pos
+1, new Font("arial unicode ms", 24, FontStyle
.Italic
, GraphicsUnit
.Pixel
), ThemeEngine
.Current
.ResPool
.GetSolidBrush(Color
.DarkGoldenrod
)); break;
1471 case 2: LineTag
.FormatText(tag
.line
, pos
, (pos
+10)<line
.Text
.Length
? 10 : line
.Text
.Length
- pos
+1, new Font("arial", 10, FontStyle
.Regular
, GraphicsUnit
.Pixel
), ThemeEngine
.Current
.ResPool
.GetSolidBrush(Color
.Aquamarine
)); break;
1472 case 3: LineTag
.FormatText(tag
.line
, pos
, (pos
+10)<line
.Text
.Length
? 10 : line
.Text
.Length
- pos
+1, new Font("times roman", 16, FontStyle
.Underline
, GraphicsUnit
.Pixel
), ThemeEngine
.Current
.ResPool
.GetSolidBrush(Color
.Turquoise
)); break;
1473 case 0: LineTag
.FormatText(tag
.line
, pos
, (pos
+10)<line
.Text
.Length
? 10 : line
.Text
.Length
- pos
+1, new Font("times roman", 64, FontStyle
.Italic
| FontStyle
.Bold
, GraphicsUnit
.Pixel
), ThemeEngine
.Current
.ResPool
.GetSolidBrush(Color
.LightSeaGreen
)); break;
1474 case 5: LineTag
.FormatText(tag
.line
, pos
, (pos
+10)<line
.Text
.Length
? 10 : line
.Text
.Length
- pos
+1, ((TextBoxBase
)sender
).Font
, ThemeEngine
.Current
.ResPool
.GetSolidBrush(ForeColor
)); break;
1481 // Update/Recalculate what we see
1482 document
.UpdateView(line
, 0);
1484 // Make sure our caret is properly positioned and sized
1485 document
.AlignCaret();
1489 private void TextBoxBase_MouseUp(object sender
, MouseEventArgs e
) {
1490 if (e
.Button
== MouseButtons
.Left
) {
1491 if (click_mode
== CaretSelection
.Position
) {
1492 document
.SetSelectionToCaret(false);
1493 document
.DisplayCaret();
1496 if (scroll_timer
!= null) {
1497 scroll_timer
.Enabled
= false;
1503 private void PositionControls ()
1505 if (hscroll
.Visible
) {
1506 //vscroll.Maximum += hscroll.Height;
1507 canvas_height
= ClientSize
.Height
- hscroll
.Height
;
1509 canvas_height
= ClientSize
.Height
;
1512 if (vscroll
.Visible
) {
1513 //hscroll.Maximum += vscroll.Width;
1514 canvas_width
= ClientSize
.Width
- vscroll
.Width
;
1516 canvas_width
= ClientSize
.Width
;
1520 document
.ViewPortWidth
= canvas_width
;
1521 document
.ViewPortHeight
= canvas_height
;
1523 // We always move them, they just might not be displayed
1524 hscroll
.Bounds
= new Rectangle (ClientRectangle
.Left
, ClientRectangle
.Height
- hscroll
.Height
, ClientSize
.Width
- (vscroll
.Visible
? vscroll
.Width
: 0), hscroll
.Height
);
1525 vscroll
.Bounds
= new Rectangle (ClientRectangle
.Right
- vscroll
.Width
, ClientRectangle
.Top
, vscroll
.Width
, ClientSize
.Height
- (hscroll
.Visible
? hscroll
.Height
: 0));
1529 private void TextBoxBase_SizeChanged(object sender
, EventArgs e
) {
1530 CalculateDocument();
1533 private void TextBoxBase_MouseWheel(object sender
, MouseEventArgs e
) {
1537 if (!vscroll
.Enabled
) {
1542 vscroll
.Value
= Math
.Min (vscroll
.Value
+ SystemInformation
.MouseWheelScrollLines
, vscroll
.Maximum
- document
.ViewPortHeight
+ 1);
1544 vscroll
.Value
= Math
.Max (0, vscroll
.Value
- SystemInformation
.MouseWheelScrollLines
);
1547 internal virtual void SelectWord ()
1549 StringBuilder s
= document
.caret
.line
.text
;
1550 int start
= document
.caret
.pos
;
1551 int end
= document
.caret
.pos
;
1554 if (document
.caret
.line
.line_no
>= document
.Lines
)
1556 Line line
= document
.GetLine (document
.caret
.line
.line_no
+ 1);
1557 document
.PositionCaret (line
, 0);
1566 // skip whitespace until we hit a word
1567 while (start
> 0 && s
[start
] == ' ')
1570 while (start
> 0 && (s
[start
] != ' '))
1572 if (s
[start
] == ' ')
1576 if (s
[end
] == ' ') {
1577 while (end
< s
.Length
&& s
[end
] == ' ')
1580 while (end
< s
.Length
&& s
[end
] != ' ')
1582 while (end
< s
.Length
&& s
[end
] == ' ')
1586 document
.SetSelection (document
.caret
.line
, start
, document
.caret
.line
, end
);
1589 internal void CalculateDocument() {
1590 if (!IsHandleCreated
) {
1593 document
.RecalculateDocument(CreateGraphicsInternal());
1594 CalculateScrollBars();
1598 internal void CalculateScrollBars() {
1599 // FIXME - need separate calculations for center and right alignment
1602 PositionControls ();
1606 if (document
.Width
>= document
.ViewPortWidth
) {
1607 hscroll
.Enabled
= true;
1608 hscroll
.Minimum
= 0;
1609 hscroll
.LargeChange
= document
.ViewPortWidth
< 0 ? 0 : document
.ViewPortWidth
;
1610 hscroll
.Maximum
= document
.Width
;
1612 hscroll
.Maximum
= document
.ViewPortWidth
;
1613 hscroll
.Enabled
= false;
1616 if (document
.Height
>= document
.ViewPortHeight
) {
1617 vscroll
.Enabled
= true;
1618 vscroll
.Minimum
= 0;
1619 vscroll
.LargeChange
= document
.ViewPortHeight
< 0 ? 0 : document
.ViewPortHeight
;
1620 vscroll
.Maximum
= document
.Height
;
1622 vscroll
.Maximum
= document
.ViewPortHeight
;
1623 vscroll
.Enabled
= false;
1628 if ((scrollbars
& RichTextBoxScrollBars
.Horizontal
) != 0) {
1629 if (((scrollbars
& RichTextBoxScrollBars
.ForcedHorizontal
) != 0) || hscroll
.Enabled
) {
1630 hscroll
.Visible
= true;
1632 hscroll
.Visible
= false;
1635 hscroll
.Visible
= false;
1639 if ((scrollbars
& RichTextBoxScrollBars
.Vertical
) != 0) {
1640 if (((scrollbars
& RichTextBoxScrollBars
.ForcedVertical
) != 0) || vscroll
.Enabled
) {
1641 vscroll
.Visible
= true;
1643 vscroll
.Visible
= false;
1646 vscroll
.Visible
= false;
1649 PositionControls ();
1652 private void document_WidthChanged(object sender
, EventArgs e
) {
1653 CalculateScrollBars();
1656 private void document_HeightChanged(object sender
, EventArgs e
) {
1657 CalculateScrollBars();
1660 private void hscroll_ValueChanged(object sender
, EventArgs e
) {
1663 old_viewport_x
= document
.ViewPortX
;
1664 document
.ViewPortX
= this.hscroll
.Value
;
1666 if (vscroll
.Visible
) {
1667 XplatUI
.ScrollWindow(this.Handle
, new Rectangle(0, 0, ClientSize
.Width
- vscroll
.Width
, ClientSize
.Height
), old_viewport_x
- this.hscroll
.Value
, 0, false);
1669 XplatUI
.ScrollWindow(this.Handle
, ClientRectangle
, old_viewport_x
- this.hscroll
.Value
, 0, false);
1671 document
.UpdateCaret();
1673 if (HScrolled
!= null) {
1674 HScrolled(this, EventArgs
.Empty
);
1678 private void vscroll_ValueChanged(object sender
, EventArgs e
) {
1681 old_viewport_y
= document
.ViewPortY
;
1682 document
.ViewPortY
= this.vscroll
.Value
;
1684 if (hscroll
.Visible
) {
1685 XplatUI
.ScrollWindow(this.Handle
, new Rectangle(0, 0, ClientSize
.Width
, ClientSize
.Height
- hscroll
.Height
), 0, old_viewport_y
- this.vscroll
.Value
, false);
1687 XplatUI
.ScrollWindow(this.Handle
, ClientRectangle
, 0, old_viewport_y
- this.vscroll
.Value
, false);
1689 document
.UpdateCaret();
1691 if (VScrolled
!= null) {
1692 VScrolled(this, EventArgs
.Empty
);
1696 private void TextBoxBase_MouseMove(object sender
, MouseEventArgs e
) {
1697 // FIXME - handle auto-scrolling if mouse is to the right/left of the window
1699 if (!ClientRectangle
.Contains (e
.X
, e
.Y
)) {
1700 if (scroll_timer
== null) {
1701 scroll_timer
= new Timer ();
1702 scroll_timer
.Interval
= 100;
1703 scroll_timer
.Tick
+= new EventHandler (ScrollTimerTickHandler
);
1706 if (!scroll_timer
.Enabled
) {
1707 scroll_timer
.Start ();
1709 // Force the first tick
1710 ScrollTimerTickHandler (null, EventArgs
.Empty
);
1716 document
.PositionCaret(e
.X
+ document
.ViewPortX
, e
.Y
+ document
.ViewPortY
);
1717 if (click_mode
== CaretSelection
.Position
) {
1718 document
.SetSelectionToCaret(false);
1719 document
.DisplayCaret();
1724 private void TextBoxBase_FontOrColorChanged(object sender
, EventArgs e
) {
1728 // Font changes apply to the whole document
1729 for (int i
= 1; i
<= document
.Lines
; i
++) {
1730 line
= document
.GetLine(i
);
1731 LineTag
.FormatText(line
, 1, line
.text
.Length
, Font
, ThemeEngine
.Current
.ResPool
.GetSolidBrush(ForeColor
));
1732 document
.UpdateView(line
, 0);
1734 // Make sure the caret height is matching the new font height
1735 document
.AlignCaret();
1739 private void ScrollTimerTickHandler (object sender
, EventArgs e
)
1741 Point pt
= Cursor
.Position
;
1743 pt
= PointToClient (pt
);
1745 if (pt
.X
< ClientRectangle
.Left
) {
1746 document
.MoveCaret(CaretDirection
.CharBackNoWrap
);
1747 document
.SetSelectionToCaret(false);
1749 CaretMoved(this, null);
1750 } else if (pt
.X
> ClientRectangle
.Right
) {
1751 document
.MoveCaret(CaretDirection
.CharForwardNoWrap
);
1752 document
.SetSelectionToCaret(false);
1754 CaretMoved(this, null);
1755 } else if (pt
.Y
> ClientRectangle
.Bottom
) {
1756 document
.MoveCaret(CaretDirection
.LineDown
);
1757 document
.SetSelectionToCaret(false);
1759 CaretMoved(this, null);
1760 } else if (pt
.Y
< ClientRectangle
.Top
) {
1761 document
.MoveCaret(CaretDirection
.LineUp
);
1762 document
.SetSelectionToCaret(false);
1764 CaretMoved(this, null);
1768 /// <summary>Ensure the caret is always visible</summary>
1769 internal void CaretMoved(object sender
, EventArgs e
) {
1773 pos
= document
.Caret
;
1774 //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);
1777 // Horizontal scrolling:
1778 // If the caret moves to the left outside the visible area, we jump the document into view, not just one
1779 // character, but 1/3 of the width of the document
1780 // If the caret moves to the right outside the visible area, we scroll just enough to keep the caret visible
1782 // Handle horizontal scrolling
1783 if (document
.CaretLine
.alignment
== HorizontalAlignment
.Left
) {
1784 // Check if we moved out of view to the left
1785 if (pos
.X
< (document
.ViewPortX
)) {
1787 if ((hscroll
.Value
- document
.ViewPortWidth
/ 3) >= hscroll
.Minimum
) {
1788 hscroll
.Value
-= document
.ViewPortWidth
/ 3;
1790 hscroll
.Value
= hscroll
.Minimum
;
1792 } while (hscroll
.Value
> pos
.X
);
1795 // Check if we moved out of view to the right
1796 if ((pos
.X
>= (document
.ViewPortWidth
+ document
.ViewPortX
)) && (hscroll
.Value
!= hscroll
.Maximum
)) {
1797 if ((pos
.X
- document
.ViewPortWidth
+ 1) <= hscroll
.Maximum
) {
1798 if (pos
.X
- document
.ViewPortWidth
>= 0) {
1799 hscroll
.Value
= pos
.X
- document
.ViewPortWidth
+ 1;
1804 hscroll
.Value
= hscroll
.Maximum
;
1807 } else if (document
.CaretLine
.alignment
== HorizontalAlignment
.Right
) {
1808 // hscroll.Value = pos.X;
1810 // if ((pos.X > (this.canvas_width + document.ViewPortX)) && (hscroll.Enabled && (hscroll.Value != hscroll.Maximum))) {
1811 // hscroll.Value = hscroll.Maximum;
1814 // FIXME - implement center cursor alignment
1821 // Handle vertical scrolling
1822 height
= document
.CaretLine
.Height
+ 1;
1824 if (pos
.Y
< document
.ViewPortY
) {
1825 vscroll
.Value
= pos
.Y
;
1828 if ((pos
.Y
+ height
) > (document
.ViewPortY
+ canvas_height
)) {
1829 vscroll
.Value
= pos
.Y
- canvas_height
+ height
;
1833 internal bool Paste(IDataObject clip
, DataFormats
.Format format
, bool obey_length
) {
1839 if (format
== null) {
1840 if ((this is RichTextBox
) && clip
.GetDataPresent(DataFormats
.Rtf
)) {
1841 format
= DataFormats
.GetFormat(DataFormats
.Rtf
);
1842 } else if (clip
.GetDataPresent(DataFormats
.UnicodeText
)) {
1843 format
= DataFormats
.GetFormat(DataFormats
.UnicodeText
);
1844 } else if (clip
.GetDataPresent(DataFormats
.Text
)) {
1845 format
= DataFormats
.GetFormat(DataFormats
.Text
);
1850 if ((format
.Name
== DataFormats
.Rtf
) && !(this is RichTextBox
)) {
1854 if (!clip
.GetDataPresent(format
.Name
)) {
1859 if (format
.Name
== DataFormats
.Rtf
) {
1860 ((RichTextBox
)this).SelectedRtf
= (string)clip
.GetData(DataFormats
.Rtf
);
1862 } else if (format
.Name
== DataFormats
.UnicodeText
) {
1863 s
= (string)clip
.GetData(DataFormats
.UnicodeText
);
1864 } else if (format
.Name
== DataFormats
.Text
) {
1865 s
= (string)clip
.GetData(DataFormats
.Text
);
1871 this.SelectedText
= s
;
1873 if ((s
.Length
+ document
.Length
) < max_length
) {
1874 this.SelectedText
= s
;
1875 } else if (document
.Length
< max_length
) {
1876 this.SelectedText
= s
.Substring(0, max_length
- document
.Length
);
1882 #endregion // Private Methods