* ImageList.cs: When the image stream is set pull all the images
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / TextBoxBase.cs
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:
8 //
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 //
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.
19 //
20 // Copyright (c) 2004-2005 Novell, Inc. (http://www.novell.com)
21 //
22 // Authors:
23 //      Peter Bartok    pbartok@novell.com
24 //
25 //
26
27 // NOT COMPLETE
28 #define Debug
29
30 using System.ComponentModel;
31 using System.ComponentModel.Design;
32 using System.Drawing;
33 using System.Drawing.Text;
34 using System.Text;
35 using System.Runtime.InteropServices;
36
37 namespace System.Windows.Forms {
38         [DefaultEvent("TextChanged")]
39         [Designer("System.Windows.Forms.Design.TextBoxBaseDesigner, " + Consts.AssemblySystem_Design)]
40         public abstract class TextBoxBase : Control {
41                 #region Local Variables
42                 internal HorizontalAlignment    alignment;
43                 internal bool                   accepts_tab;
44                 internal bool                   accepts_return;
45                 internal bool                   auto_size;
46                 internal CharacterCasing        character_casing;
47                 internal bool                   undo;
48                 internal bool                   hide_selection;
49                 internal int                    max_length;
50                 internal bool                   modified;
51                 internal bool                   multiline;
52                 internal bool                   read_only;
53                 internal bool                   word_wrap;
54                 internal Document               document;
55                 internal LineTag                caret_tag;              // tag our cursor is in
56                 internal int                    caret_pos;              // position on the line our cursor is in (can be 0 = beginning of line)
57                 internal int                    viewport_x;             // left visible pixel
58                 internal int                    viewport_y;             // top visible pixel
59                 internal HScrollBar             hscroll;
60                 internal VScrollBar             vscroll;
61                 internal ScrollBars             scrollbars;
62                 internal bool                   grabbed;
63                 internal bool                   richtext;
64                 internal int                    requested_height;
65
66                 #if Debug
67                 internal static bool    draw_lines = false;
68                 #endif
69
70                 #endregion      // Local Variables
71
72                 #region Internal Constructor
73                 // Constructor will go when complete, only for testing - pdb
74                 internal TextBoxBase() {
75                         alignment = HorizontalAlignment.Left;
76                         accepts_return = false;
77                         accepts_tab = false;
78                         auto_size = true;
79                         border_style = BorderStyle.Fixed3D;
80                         character_casing = CharacterCasing.Normal;
81                         undo = false;
82                         hide_selection = true;
83                         max_length = 32767;
84                         modified = false;
85                         multiline = false;
86                         read_only = false;
87                         word_wrap = true;
88                         richtext = false;
89                         document = new Document(this);
90                         requested_height = -1;
91
92                         MouseDown += new MouseEventHandler(TextBoxBase_MouseDown);
93                         MouseUp += new MouseEventHandler(TextBoxBase_MouseUp);
94                         MouseMove += new MouseEventHandler(TextBoxBase_MouseMove);
95                         SizeChanged += new EventHandler(TextBoxBase_SizeChanged);
96                         FontChanged += new EventHandler(TextBoxBase_FontOrColorChanged);
97                         ForeColorChanged += new EventHandler(TextBoxBase_FontOrColorChanged);
98                         
99                         scrollbars = ScrollBars.None;
100
101                         hscroll = new HScrollBar();
102                         hscroll.ValueChanged +=new EventHandler(hscroll_ValueChanged);
103                         hscroll.Enabled = true;
104                         hscroll.Visible = false;
105
106                         vscroll = new VScrollBar();
107                         vscroll.Visible = false;
108
109                         this.Controls.Add(hscroll);
110                         this.Controls.Add(vscroll);
111
112                         //SetStyle(ControlStyles.ResizeRedraw, true);
113                         SetStyle(ControlStyles.AllPaintingInWmPaint, true);
114                         SetStyle(ControlStyles.UserPaint, true);
115                 }
116                 #endregion      // Internal Constructor
117
118                 #region Private and Internal Methods
119                 internal string CaseAdjust(string s) {
120                         if (character_casing == CharacterCasing.Normal) {
121                                 return s;
122                         }
123                         if (character_casing == CharacterCasing.Lower) {
124                                 return s.ToLower();
125                         } else {
126                                 return s.ToUpper();
127                         }
128                 }
129                 #endregion      // Private and Internal Methods
130
131                 #region Public Instance Properties
132                 [DefaultValue(false)]
133                 public bool AcceptsTab {
134                         get {
135                                 return accepts_tab;
136                         }
137
138                         set {
139                                 if (value != accepts_tab) {
140                                         accepts_tab = value;
141                                         OnAcceptsTabChanged(EventArgs.Empty);
142                                 }
143                         }
144                 }
145
146                 [DefaultValue(true)]
147                 [Localizable(true)]
148                 [RefreshProperties(RefreshProperties.Repaint)]
149                 public virtual bool AutoSize {
150                         get {
151                                 return auto_size;
152                         }
153
154                         set {
155                                 if (value != auto_size) {
156                                         auto_size = value;
157                                         if (auto_size) {
158                                                 if (PreferredHeight != Height) {
159                                                         Height = PreferredHeight;
160                                                 }
161                                         }
162                                         OnAutoSizeChanged(EventArgs.Empty);
163                                 }
164                         }
165                 }
166
167                 [DispId(-501)]
168                 public override System.Drawing.Color BackColor {
169                         get {
170                                 return base.BackColor;
171                         }
172                         set {
173                                 base.BackColor = value;
174                         }
175                 }
176
177                 [Browsable(false)]
178                 [EditorBrowsable(EditorBrowsableState.Never)]
179                 public override System.Drawing.Image BackgroundImage {
180                         get {
181                                 return base.BackgroundImage;
182                         }
183                         set {
184                                 base.BackgroundImage = value;
185                         }
186                 }
187
188                 [DefaultValue(BorderStyle.Fixed3D)]
189                 [DispId(-504)]
190                 public BorderStyle BorderStyle {
191                         get {
192                                 return border_style;
193                         }
194
195                         set {
196                                 if (value != border_style) {
197                                         border_style = value;
198                                         OnBorderStyleChanged(EventArgs.Empty);
199                                 }
200                         }
201                 }
202
203                 [Browsable(false)]
204                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
205                 public bool CanUndo {
206                         get {
207                                 return undo;
208                         }
209                 }
210
211                 [DispId(-513)]
212                 public override System.Drawing.Color ForeColor {
213                         get {
214                                 return base.ForeColor;
215                         }
216                         set {
217                                 base.ForeColor = value;
218                         }
219                 }
220
221                 [DefaultValue(true)]
222                 public bool HideSelection {
223                         get {
224                                 return hide_selection;
225                         }
226
227                         set {
228                                 if (value != hide_selection) {
229                                         hide_selection = value;
230                                         OnHideSelectionChanged(EventArgs.Empty);
231                                 }
232                                 if (hide_selection) {
233                                         document.selection_visible = false;
234                                 } else {
235                                         document.selection_visible = true;
236                                 }
237                                 document.InvalidateSelectionArea();
238
239                         }
240                 }
241
242                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
243                 [Editor("System.Windows.Forms.Design.StringArrayEditor, " + Consts.AssemblySystem_Design, typeof(System.Drawing.Design.UITypeEditor))]
244                 [Localizable(true)]
245                 public string[] Lines {
246                         get {
247                                 string[]        lines;
248                                 int             i;
249                                 int             l;
250
251                                 l = document.Lines;
252                                 lines = new string[l];
253
254                                 for (i = 1; i <= l; i++) {
255                                         lines[i - 1] = document.GetLine(i).text.ToString();
256                                 }
257
258                                 return lines;
259                         }
260
261                         set {
262                                 int     i;
263                                 int     l;
264                                 Brush   brush;
265
266                                 document.Empty();
267
268                                 l = value.Length;
269                                 brush = ThemeEngine.Current.ResPool.GetSolidBrush(this.ForeColor);
270
271                                 for (i = 0; i < l; i++) {
272                                         document.Add(i+1, CaseAdjust(value[i]), alignment, Font, brush);
273                                 }
274                                 document.RecalculateDocument(CreateGraphics());
275                                 OnTextChanged(EventArgs.Empty);
276                         }
277                 }
278
279                 [DefaultValue(32767)]
280                 [Localizable(true)]
281                 public virtual int MaxLength {
282                         get {
283                                 return max_length;
284                         }
285
286                         set {
287                                 if (value != max_length) {
288                                         max_length = value;
289                                 }
290                         }
291                 }
292
293                 [Browsable(false)]
294                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
295                 public bool Modified {
296                         get {
297                                 return modified;
298                         }
299
300                         set {
301                                 if (value != modified) {
302                                         modified = value;
303                                         OnModifiedChanged(EventArgs.Empty);
304                                 }
305                         }
306                 }
307
308                 [DefaultValue(false)]
309                 [Localizable(true)]
310                 [RefreshProperties(RefreshProperties.All)]
311                 public virtual bool Multiline {
312                         get {
313                                 return multiline;
314                         }
315
316                         set {
317                                 if (value != multiline) {
318                                         multiline = value;
319
320                                         // Make sure we update our size; the user may have already set the size before going to multiline
321                                         if (multiline && requested_height != -1) {
322                                                 Height = requested_height;
323                                                 requested_height = -1;
324                                         }
325
326                                         OnMultilineChanged(EventArgs.Empty);
327                                 }
328
329                                 document.multiline = multiline;
330                         }
331                 }
332
333                 [Browsable(false)]
334                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
335                 [EditorBrowsable(EditorBrowsableState.Advanced)]
336                 public int PreferredHeight {
337                         get {
338                                 return this.Font.Height + 7;    // FIXME - consider border style as well
339                         }
340                 }
341
342                 [DefaultValue(false)]
343                 public bool ReadOnly {
344                         get {
345                                 return read_only;
346                         }
347
348                         set {
349                                 if (value != read_only) {
350                                         read_only = value;
351                                         OnReadOnlyChanged(EventArgs.Empty);
352                                 }
353                         }
354                 }
355
356                 [Browsable(false)]
357                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
358                 public virtual string SelectedText {
359                         get {
360                                 return document.GetSelection();
361                         }
362
363                         set {
364                                 document.ReplaceSelection(CaseAdjust(value));
365                                 OnTextChanged(EventArgs.Empty);
366                         }
367                 }
368
369                 [Browsable(false)]
370                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
371                 public virtual int SelectionLength {
372                         get {
373                                 return document.SelectionLength();
374                         }
375
376                         set {
377                                 if (value != 0) {
378                                         int     start;
379                                         Line    line;
380                                         LineTag tag;
381                                         int     pos;
382
383                                         start = document.LineTagToCharIndex(document.selection_start.line, document.selection_start.pos);
384
385                                         document.CharIndexToLineTag(start + value, out line, out tag, out pos);
386                                         document.SetSelectionEnd(line, pos);
387                                         document.PositionCaret(line, pos);
388                                 } else {
389                                         document.SetSelectionEnd(document.selection_start.line, document.selection_start.pos);
390                                         document.PositionCaret(document.selection_start.line, document.selection_start.pos);
391                                 }
392                         }
393                 }
394
395                 [Browsable(false)]
396                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
397                 public int SelectionStart {
398                         get {
399                                 int index;
400
401                                 index = document.LineTagToCharIndex(document.selection_start.line, document.selection_start.pos);
402
403                                 return index;
404                         }
405
406                         set {
407                                 Line    line;
408                                 LineTag tag;
409                                 int     pos;
410
411                                 document.CharIndexToLineTag(value, out line, out tag, out pos);
412                                 document.SetSelectionStart(line, pos);
413                         }
414                 }
415
416                 [Localizable(true)]
417                 public override string Text {
418                         get {
419                                 if (document == null || document.Root == null || document.Root.text == null) {
420                                         return string.Empty;
421                                 }
422
423                                 if (!multiline) {
424                                         return document.Root.text.ToString();
425                                 } else {
426                                         StringBuilder   sb;
427                                         int             i;
428
429                                         sb = new StringBuilder();
430
431                                         for (i = 1; i < document.Lines; i++) {
432                                                 sb.Append(document.GetLine(i).text.ToString() + Environment.NewLine);
433                                         }
434
435                                         return sb.ToString();
436                                 }
437                         }
438
439                         set {
440                                 Line    line;
441
442                                 if (multiline) {
443                                         string[]        lines;
444
445                                         lines = value.Split(new char[] {'\n'});
446                                         for (int i = 0; i < lines.Length; i++) {
447                                                 if (lines[i].EndsWith("\r")) {
448                                                         lines[i] = lines[i].Substring(0, lines[i].Length - 1);
449                                                 }
450                                         }
451                                         this.Lines = lines;
452
453                                         line = document.GetLine(1);
454                                         document.SetSelectionStart(line, 0);
455
456                                         line = document.GetLine(document.Lines);
457                                         document.SetSelectionEnd(line, line.text.Length);
458                                         document.PositionCaret(line, line.text.Length);
459                                 } else {
460                                         document.Clear();
461                                         document.Add(1, CaseAdjust(value), alignment, Font, ThemeEngine.Current.ResPool.GetSolidBrush(ForeColor));
462                                         document.RecalculateDocument(CreateGraphics());
463                                         line = document.GetLine(1);
464                                         document.SetSelectionStart(line, 0);
465                                         document.SetSelectionEnd(line, value.Length);
466                                         document.PositionCaret(line, value.Length);
467                                 }
468                                 base.Text = value;
469                                 OnTextChanged(EventArgs.Empty);
470                         }
471                 }
472
473                 [Browsable(false)]
474                 public virtual int TextLength {
475                         get {
476                                 if (document == null || document.Root == null || document.Root.text == null) {
477                                         return 0;
478                                 }
479
480                                 if (!multiline) {
481                                         return document.Root.text.Length;
482                                 } else {
483                                         int     total;
484                                         int     i;
485
486                                         total = 0;
487                                         for (i = 1; i < document.Lines; i++) {
488                                                 total += document.GetLine(i).text.Length + Environment.NewLine.Length;
489                                         }
490
491                                         return total;
492                                 }
493                         }
494                 }
495
496                 [DefaultValue(true)]
497                 [Localizable(true)]
498                 public bool WordWrap {
499                         get {
500                                 return word_wrap;
501                         }
502
503                         set {
504                                 if (value != word_wrap) {
505                                         word_wrap = value;
506                                 }
507                         }
508                 }
509                 #endregion      // Public Instance Properties
510
511                 #region Protected Instance Properties
512                 protected override CreateParams CreateParams {
513                         get {
514                                 return base.CreateParams;
515                         }
516                 }
517
518                 protected override System.Drawing.Size DefaultSize {
519                         get {
520                                 return base.DefaultSize;
521                         }
522                 }
523                 #endregion      // Protected Instance Properties
524
525                 #region Public Instance Methods
526                 public void AppendText(string text) {
527
528                         if (multiline) {
529                                 string[]        lines;
530                                 int             linecount;
531
532                                 // Break the string into separate lines
533                                 lines = text.Split(new char[] {'\n'});
534                                 linecount = lines.Length;
535                                 for (int i = 0; i < linecount; i++) {
536                                         if (lines[i].EndsWith("\r")) {
537                                                 lines[i] = lines[i].Substring(0, lines[i].Length - 1);
538                                         }
539                                 }
540
541                                 // Grab the formatting for the last element
542                                 document.MoveCaret(CaretDirection.CtrlEnd);
543
544                                 // Insert the first line
545                                 document.InsertString(document.CaretLine, document.CaretPosition, lines[0]);
546
547                                 for (int i = 1; i < linecount; i++) {
548                                         document.Add(document.CaretLine.LineNo+i, CaseAdjust(lines[i]), alignment, document.CaretTag.font, document.CaretTag.color);
549                                 }
550
551                                 document.RecalculateDocument(CreateGraphics());
552                                 document.MoveCaret(CaretDirection.CtrlEnd);
553                                 Invalidate();
554                         } else {
555                                 document.MoveCaret(CaretDirection.CtrlEnd);
556                                 document.InsertStringAtCaret(text, true);
557                                 Invalidate();
558                         }
559                         OnTextChanged(EventArgs.Empty);
560                 }
561
562                 public void Clear() {
563                         // FIXME
564                         throw new NotImplementedException();
565                 }
566
567                 public void ClearUndo() {
568                         // FIXME
569                         throw new NotImplementedException();
570                 }
571
572                 public void Copy() {
573                         // FIXME
574                         throw new NotImplementedException();
575                 }
576
577                 public void Cut() {
578                         // FIXME
579                         throw new NotImplementedException();
580                 }
581
582                 public void Paste() {
583                         // FIXME
584                         throw new NotImplementedException();
585                 }
586
587                 public void ScrollToCaret() {
588                         // FIXME
589                         throw new NotImplementedException();
590                 }
591
592                 public void Select(int start, int length) {
593                         SelectionStart = start;
594                         SelectionLength = length;
595                 }
596
597
598                 public void SelectAll() {
599                         Line    last;
600
601                         last = document.GetLine(document.Lines);
602                         document.SetSelectionStart(document.GetLine(1), 0);
603                         document.SetSelectionEnd(last, last.text.Length);
604                 }
605
606                 public override string ToString() {
607                         StringBuilder   sb;
608                         int             i;
609                         int             end;
610
611                         if (document == null) {
612                                 return String.Empty;
613                         }
614
615                         sb = new StringBuilder();
616
617                         end = document.Lines;
618
619                         for (i = 1; i < end; i++) {
620                                 sb.Append(document.GetLine(i).text.ToString() + "\n");
621                         }
622
623                         return sb.ToString();
624                 }
625
626                 public void Undo() {
627                         return;
628                 }
629                 #endregion      // Public Instance Methods
630
631                 #region Protected Instance Methods
632                 protected override void CreateHandle() {
633                         base.CreateHandle ();
634                 }
635
636                 protected override bool IsInputKey(Keys keyData) {
637                         switch (keyData) {
638                                 case Keys.Enter: {
639                                         if (multiline && (accepts_return || ((keyData & Keys.Control) != 0))) {
640                                                 return true;
641                                         }
642                                         return false;
643                                 }
644
645                                 case Keys.Tab: {
646                                         if (accepts_tab) {
647                                                 return true;
648                                         }
649                                         return false;
650                                 }
651                         }
652                         return false;
653                 }
654
655
656                 protected virtual void OnAcceptsTabChanged(EventArgs e) {
657                         if (AcceptsTabChanged != null) {
658                                 AcceptsTabChanged(this, e);
659                         }
660                 }
661
662                 protected virtual void OnAutoSizeChanged(EventArgs e) {
663                         if (AutoSizeChanged != null) {
664                                 AutoSizeChanged(this, e);
665                         }
666                 }
667
668                 protected virtual void OnBorderStyleChanged(EventArgs e) {
669                         if (BorderStyleChanged != null) {
670                                 BorderStyleChanged(this, e);
671                         }
672                 }
673
674                 protected override void OnFontChanged(EventArgs e) {
675                         base.OnFontChanged (e);
676
677                         if (auto_size) {
678                                 if (PreferredHeight != Height) {
679                                         Height = PreferredHeight;
680                                 }
681                         }
682                 }
683
684                 protected override void OnHandleCreated(EventArgs e) {
685                         base.OnHandleCreated (e);
686                 }
687
688                 protected override void OnHandleDestroyed(EventArgs e) {
689                         base.OnHandleDestroyed (e);
690                 }
691
692                 protected virtual void OnHideSelectionChanged(EventArgs e) {
693                         if (HideSelectionChanged != null) {
694                                 HideSelectionChanged(this, e);
695                         }
696                 }
697
698                 protected virtual void OnModifiedChanged(EventArgs e) {
699                         if (ModifiedChanged != null) {
700                                 ModifiedChanged(this, e);
701                         }
702                 }
703
704                 protected virtual void OnMultilineChanged(EventArgs e) {
705                         if (MultilineChanged != null) {
706                                 MultilineChanged(this, e);
707                         }
708                 }
709
710                 protected virtual void OnReadOnlyChanged(EventArgs e) {
711                         if (ReadOnlyChanged != null) {
712                                 ReadOnlyChanged(this, e);
713                         }
714                 }
715
716                 protected override bool ProcessDialogKey(Keys keyData) {
717                         switch (keyData & Keys.KeyCode) {
718                                 case Keys.Left: {
719                                         document.SetSelectionToCaret(true);
720
721                                         if ((Control.ModifierKeys & Keys.Control) != 0) {
722                                                 document.MoveCaret(CaretDirection.WordBack);
723                                         } else {
724                                                 document.MoveCaret(CaretDirection.CharBack);
725                                         }
726                                         return true;
727                                 }
728
729                                 case Keys.Right: {
730                                         document.SetSelectionToCaret(true);
731
732                                         if ((Control.ModifierKeys & Keys.Control) != 0) {
733                                                 document.MoveCaret(CaretDirection.WordForward);
734                                         } else {
735                                                 document.MoveCaret(CaretDirection.CharForward);
736                                         }
737                                         return true;
738                                 }
739
740                                 case Keys.Up: {
741                                         document.SetSelectionToCaret(true);
742                                         document.MoveCaret(CaretDirection.LineUp);
743                                         return true;
744                                 }
745
746                                 case Keys.Down: {
747                                         document.SetSelectionToCaret(true);
748                                         document.MoveCaret(CaretDirection.LineDown);
749                                         return true;
750                                 }
751
752                                 case Keys.Home: {
753                                         document.SetSelectionToCaret(true);
754
755                                         if ((Control.ModifierKeys & Keys.Control) != 0) {
756                                                 document.MoveCaret(CaretDirection.CtrlHome);
757                                         } else {
758                                                 document.MoveCaret(CaretDirection.Home);
759                                         }
760                                         return true;
761                                 }
762
763                                 case Keys.End: {
764                                         document.SetSelectionToCaret(true);
765
766                                         if ((Control.ModifierKeys & Keys.Control) != 0) {
767                                                 document.MoveCaret(CaretDirection.CtrlEnd);
768                                         } else {
769                                                 document.MoveCaret(CaretDirection.End);
770                                         }
771                                         return true;
772                                 }
773
774                                 case Keys.Enter: {
775                                         if (multiline && (accepts_return || ((Control.ModifierKeys & Keys.Control) != 0))) {
776                                                 if (document.selection_visible) {
777                                                         document.ReplaceSelection("");
778                                                 }
779                                                 document.SetSelectionToCaret(true);
780
781                                                 document.Split(document.CaretLine, document.CaretTag, document.CaretPosition);
782                                                 OnTextChanged(EventArgs.Empty);
783                                                 document.UpdateView(document.CaretLine, 2, 0);
784                                                 document.MoveCaret(CaretDirection.CharForward);
785                                                 return true;
786                                         }
787                                         break;
788                                 }
789
790                                 case Keys.Tab: {
791                                         if (accepts_tab) {
792                                                 document.InsertChar(document.CaretLine, document.CaretPosition, '\t');
793                                                 if (document.selection_visible) {
794                                                         document.ReplaceSelection("");
795                                                 }
796                                                 document.SetSelectionToCaret(true);
797
798                                                 OnTextChanged(EventArgs.Empty);
799                                                 return true;
800                                         }
801                                         break;
802                                 }
803
804
805                                 case Keys.Back: {
806                                         // delete only deletes on the line, doesn't do the combine
807                                         if (document.selection_visible) {
808                                                 document.ReplaceSelection("");
809                                         }
810                                         document.SetSelectionToCaret(true);
811                                         if (document.CaretPosition == 0) {
812                                                 if (document.CaretLine.LineNo > 1) {
813                                                         Line    line;
814                                                         int     new_caret_pos;
815
816                                                         line = document.GetLine(document.CaretLine.LineNo - 1);
817                                                         new_caret_pos = line.text.Length;
818
819                                                         document.Combine(line, document.CaretLine);
820                                                         document.UpdateView(line, 1, 0);
821                                                         document.PositionCaret(line, new_caret_pos);
822                                                         document.UpdateCaret();
823                                                         OnTextChanged(EventArgs.Empty);
824                                                 }
825                                         } else {
826                                                 document.DeleteChar(document.CaretTag, document.CaretPosition, false);
827                                                 document.MoveCaret(CaretDirection.CharBack);
828                                                 OnTextChanged(EventArgs.Empty);
829                                         }
830                                         return true;
831                                 }
832
833                                 case Keys.Delete: {
834                                         // delete only deletes on the line, doesn't do the combine
835                                         if (document.CaretPosition == document.CaretLine.text.Length) {
836                                                 if (document.CaretLine.LineNo < document.Lines) {
837                                                         Line    line;
838
839                                                         line = document.GetLine(document.CaretLine.LineNo + 1);
840                                                         document.Combine(document.CaretLine, line);
841                                                         document.UpdateView(document.CaretLine, 2, 0);
842                                                         OnTextChanged(EventArgs.Empty);
843
844 #if Debug
845                                                         Line    check_first;
846                                                         Line    check_second;
847
848                                                         check_first = document.GetLine(document.CaretLine.LineNo);
849                                                         check_second = document.GetLine(check_first.line_no + 1);
850
851                                                         Console.WriteLine("Post-UpdateView: Y of first line: {0}, second line: {1}", check_first.Y, check_second.Y);
852 #endif
853
854                                                         // Caret doesn't move
855                                                 }
856                                         } else {
857                                                 document.DeleteChar(document.CaretTag, document.CaretPosition, true);
858                                                 OnTextChanged(EventArgs.Empty);
859                                         }
860                                         return true;
861                                 }
862                         }
863                         return base.ProcessDialogKey (keyData);
864                 }
865
866                 protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified) {
867                         // Make sure we don't get sized bigger than we want to be
868                         if (!richtext) {
869                                 if (!multiline) {
870                                         if (height > PreferredHeight) {
871                                                 requested_height = height;
872                                                 height = PreferredHeight;
873                                                 specified |= BoundsSpecified.Height;
874                                         }
875                                 }
876                         }
877
878                         base.SetBoundsCore (x, y, width, height, specified);
879                 }
880
881                 protected override void WndProc(ref Message m) {
882                         switch ((Msg)m.Msg) {
883                                 case Msg.WM_PAINT: {
884                                         PaintEventArgs  paint_event;
885
886                                         paint_event = XplatUI.PaintEventStart(Handle);
887                                         
888                                         PaintControl(paint_event);
889                                         XplatUI.PaintEventEnd(Handle);
890                                         DefWndProc(ref m);
891                                         return;
892                                 }
893
894                                 case Msg.WM_SETFOCUS: {
895                                         // Set caret
896                                         document.CaretHasFocus();
897 Console.WriteLine("Creating caret");
898                                         base.WndProc(ref m);
899                                         return;
900                                 }
901
902                                 case Msg.WM_KILLFOCUS: {
903                                         // Kill caret
904                                         document.CaretLostFocus();
905 Console.WriteLine("Destroying caret");
906                                         base.WndProc(ref m);
907                                         return;
908                                 }
909
910                                 case Msg.WM_CHAR: {
911                                         if (ProcessKeyEventArgs(ref m)) {
912                                                 return;
913                                         }
914
915                                         if (PreProcessMessage(ref m)) {
916                                                 return;
917                                         }
918
919                                         if (ProcessKeyMessage(ref m)) {
920                                                 return;
921                                         }
922
923                                         if (m.WParam.ToInt32() >= 32) { // FIXME, tabs should probably go through
924                                                 if (document.selection_visible) {
925                                                         document.ReplaceSelection("");
926                                                 }
927
928                                                 switch (character_casing) {
929                                                         case CharacterCasing.Normal: {
930                                                                 document.InsertCharAtCaret((char)m.WParam, true);
931                                                                 OnTextChanged(EventArgs.Empty);
932                                                                 return;
933                                                         }
934
935                                                         case CharacterCasing.Lower: {
936                                                                 document.InsertCharAtCaret(Char.ToLower((char)m.WParam), true);
937                                                                 OnTextChanged(EventArgs.Empty);
938                                                                 return;
939                                                         }
940
941                                                         case CharacterCasing.Upper: {
942                                                                 document.InsertCharAtCaret(Char.ToUpper((char)m.WParam), true);
943                                                                 OnTextChanged(EventArgs.Empty);
944                                                                 return;
945                                                         }
946                                                 }
947                                         }
948                                         DefWndProc(ref m);
949                                         return;
950                                 }
951
952                                 default: {
953                                         base.WndProc(ref m);
954                                         return;
955                                 }
956                         }
957                 }
958
959                 #endregion      // Protected Instance Methods
960
961                 #region Events
962                 public event EventHandler       AcceptsTabChanged;
963                 public event EventHandler       AutoSizeChanged;
964                 [Browsable(false)]
965                 [EditorBrowsable(EditorBrowsableState.Never)]
966                 public new event EventHandler BackgroundImageChanged {
967                         add { base.BackgroundImageChanged += value; }
968                         remove { base.BackgroundImageChanged -= value; }
969                 }
970                 public event EventHandler       BorderStyleChanged;
971                 [Browsable(false)]
972                 [EditorBrowsable(EditorBrowsableState.Advanced)]
973                 public event EventHandler       Click;
974                 public event EventHandler       HideSelectionChanged;
975                 public event EventHandler       ModifiedChanged;
976                 public event EventHandler       MultilineChanged;
977                 [Browsable(false)]
978                 [EditorBrowsable(EditorBrowsableState.Never)]
979                 public event PaintEventHandler  Paint;
980                 public event EventHandler       ReadOnlyChanged;
981                 #endregion      // Events
982
983                 #region Private Methods
984                 internal Document Document {
985                         get {
986                                 return document;
987                         }
988
989                         set {
990                                 document = value;
991                         }
992                 }
993
994 static int current;
995
996                 private void PaintControl(PaintEventArgs pevent) {
997                         // Fill background
998                         pevent.Graphics.FillRectangle(ThemeEngine.Current.ResPool.GetSolidBrush(BackColor), pevent.ClipRectangle);
999                         //pevent.Graphics.TextRenderingHint=TextRenderingHint.AntiAlias;
1000
1001                         // Draw the viewable document
1002                         document.Draw(pevent.Graphics, pevent.ClipRectangle);
1003
1004                         Rectangle       rect = ClientRectangle;
1005                         rect.Width--;
1006                         rect.Height--;
1007                         pevent.Graphics.DrawRectangle(ThemeEngine.Current.ResPool.GetPen(ThemeEngine.Current.ColorButtonShadow), rect);
1008
1009                         // Set the scrollbar
1010                         switch (scrollbars) {
1011                                 case ScrollBars.Both: {
1012                                         break;
1013                                 }
1014                                 case ScrollBars.Vertical: {
1015                                         break;
1016                                 }
1017                                 case ScrollBars.Horizontal: {
1018                                         hscroll.Minimum = 0;
1019                                         hscroll.Maximum = document.Width - this.Width;
1020                                         break;
1021                                 }
1022                         }
1023
1024                         #if Debug
1025                                 int             start;
1026                                 int             end;
1027                                 Line            line;
1028                                 int             line_no;
1029                                 Pen             p;
1030
1031                                 p = new Pen(Color.Red, 1);
1032
1033                                 // First, figure out from what line to what line we need to draw
1034                                 start = document.GetLineByPixel(pevent.ClipRectangle.Top - viewport_y, false).line_no;
1035                                 end = document.GetLineByPixel(pevent.ClipRectangle.Bottom - viewport_y, false).line_no;
1036
1037                                 //Console.WriteLine("Starting drawing on line '{0}'", document.GetLine(start));
1038                                 //Console.WriteLine("Ending drawing on line '{0}'", document.GetLine(end));
1039
1040                                 line_no = start;
1041                                 while (line_no <= end) {
1042                                         line = document.GetLine(line_no);
1043
1044                                         if (draw_lines) {
1045                                                 for (int i = 0; i < line.text.Length; i++) {
1046                                                         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);
1047                                                 }
1048                                         }
1049
1050                                         line_no++;
1051                                 }
1052                         #endif
1053                 }
1054
1055                 private void TextBoxBase_MouseDown(object sender, MouseEventArgs e) {
1056                         LineTag tag;
1057                         Line    line;
1058                         int     pos;
1059
1060                         if (e.Button == MouseButtons.Left) {
1061                                 document.PositionCaret(e.X, e.Y);
1062                                 document.SetSelectionToCaret(true);
1063                                 this.grabbed = true;
1064                                 this.Capture = true;
1065                                 return;
1066                         }
1067
1068                         #if Debug
1069                                 if (e.Button == MouseButtons.Right) {
1070                                         draw_lines = !draw_lines;
1071                                         this.Invalidate();
1072                                         Console.WriteLine("SelectedText: {0}, length {1}", this.SelectedText, this.SelectionLength);
1073                                         Console.WriteLine("Selection start: {0}", this.SelectionStart);
1074
1075                                         this.SelectionStart = 10;
1076                                         this.SelectionLength = 5;
1077
1078                                         return;
1079                                 }
1080
1081                                 tag = document.FindTag(e.X, e.Y, out pos, false);
1082
1083                                 Console.WriteLine("Click found tag {0}, character {1}", tag, pos);
1084                                 line = tag.line;
1085                                 switch(current) {
1086                                         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;
1087                                         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;
1088                                         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;
1089                                         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;
1090                                         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;
1091                                         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;
1092                                 }
1093                                 current++;
1094                                 if (current==6) {
1095                                         current=0;
1096                                 }
1097
1098                                 // Update/Recalculate what we see
1099                                 document.UpdateView(line, 0);
1100
1101                                 // Make sure our caret is properly positioned and sized
1102                                 document.AlignCaret();
1103                         #endif
1104                 }
1105
1106                 private void TextBoxBase_MouseUp(object sender, MouseEventArgs e) {
1107                         this.Capture = false;
1108                         this.grabbed = false;
1109                         if (e.Button == MouseButtons.Left) {
1110                                 document.PositionCaret(e.X + viewport_x, e.Y + viewport_y);
1111                                 document.SetSelectionToCaret(false);
1112                                 document.DisplayCaret();
1113                                 return;
1114                         }
1115                 }
1116                 #endregion      // Private Methods
1117
1118
1119                 private void TextBoxBase_SizeChanged(object sender, EventArgs e) {
1120
1121                         // First, check which scrollbars we need
1122                         
1123                         hscroll.Bounds = new Rectangle (ClientRectangle.Left, ClientRectangle.Bottom - hscroll.Height, Width, hscroll.Height);
1124                         
1125                 }
1126
1127                 private void hscroll_ValueChanged(object sender, EventArgs e) {
1128                         XplatUI.ScrollWindow(this.Handle, document.ViewPortX-this.hscroll.Value, 0, false);
1129                         document.ViewPortX = this.hscroll.Value;
1130                         document.UpdateCaret();
1131                         Console.WriteLine("Dude scrolled");
1132                 }
1133
1134                 private void TextBoxBase_MouseMove(object sender, MouseEventArgs e) {
1135                         // FIXME - handle auto-scrolling if mouse is to the right/left of the window
1136                         if (grabbed) {
1137                                 document.PositionCaret(e.X + viewport_x, e.Y + viewport_y);
1138                                 document.SetSelectionToCaret(false);
1139                                 document.DisplayCaret();
1140                         }
1141                 }
1142                                                                               
1143                 private void TextBoxBase_FontOrColorChanged(object sender, EventArgs e) {
1144                         if (!richtext) {
1145                                 Line    line;
1146
1147                                 // Font changes apply to the whole document
1148                                 for (int i = 1; i <= document.Lines; i++) {
1149                                         line = document.GetLine(i);
1150                                         LineTag.FormatText(line, 1, line.text.Length, Font, ThemeEngine.Current.ResPool.GetSolidBrush(ForeColor));
1151                                         document.UpdateView(line, 0);
1152                                 }
1153                                 // Make sure the caret height is matching the new font height
1154                                 document.AlignCaret();
1155                         }
1156                 }
1157         }
1158 }