2009-09-01 Carlos Alberto Cortez <calberto.cortez@gmail.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / RichTextBox.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) 2005-2006 Novell, Inc. (http://www.novell.com)
21 //
22 // Authors:
23 //      Peter Bartok    <pbartok@novell.com>
24 //
25 //
26
27 // #define DEBUG
28
29 using System;
30 using System.Collections;
31 using System.ComponentModel;
32 using System.Drawing;
33 using System.Drawing.Imaging;
34 using System.IO;
35 using System.Text;
36 using System.Runtime.InteropServices;
37 using RTF=System.Windows.Forms.RTF;
38
39 namespace System.Windows.Forms {
40 #if NET_2_0
41         [ClassInterface (ClassInterfaceType.AutoDispatch)]
42         [Docking (DockingBehavior.Ask)]
43         [ComVisible (true)]
44         [Designer ("System.Windows.Forms.Design.RichTextBoxDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
45 #endif
46         public class RichTextBox : TextBoxBase {
47                 #region Local Variables
48                 internal bool           auto_word_select;
49                 internal int            bullet_indent;
50                 internal bool           detect_urls;
51                 internal int            margin_right;
52                 internal float          zoom;
53                 private StringBuilder   rtf_line;
54
55                 private RtfSectionStyle rtf_style;      // Replaces individual style
56                                                         // properties so we can revert
57                 private Stack           rtf_section_stack;
58
59                 private RTF.TextMap rtf_text_map;
60                 private int rtf_skip_count;
61                 private int             rtf_cursor_x;
62                 private int             rtf_cursor_y;
63                 private int             rtf_chars;
64
65 #if NET_2_0
66                 private bool            enable_auto_drag_drop;
67                 private RichTextBoxLanguageOptions language_option;
68                 private bool            rich_text_shortcuts_enabled;
69                 private Color           selection_back_color;
70 #endif
71                 #endregion      // Local Variables
72
73                 #region Public Constructors
74                 public RichTextBox() {
75                         accepts_return = true;
76                         auto_size = false;
77                         auto_word_select = false;
78                         bullet_indent = 0;
79                         base.MaxLength = Int32.MaxValue;
80                         margin_right = 0;
81                         zoom = 1;
82                         base.Multiline = true;
83                         document.CRLFSize = 1;
84                         shortcuts_enabled = true;
85                         base.EnableLinks = true;
86                         richtext = true;
87                         
88                         rtf_style = new RtfSectionStyle ();
89                         rtf_section_stack = null;
90
91                         scrollbars = RichTextBoxScrollBars.Both;
92                         alignment = HorizontalAlignment.Left;
93                         LostFocus += new EventHandler(RichTextBox_LostFocus);
94                         GotFocus += new EventHandler(RichTextBox_GotFocus);
95                         BackColor = ThemeEngine.Current.ColorWindow;
96 #if NET_2_0
97                         backcolor_set = false;
98                         language_option = RichTextBoxLanguageOptions.AutoFontSizeAdjust;
99                         rich_text_shortcuts_enabled = true;
100                         selection_back_color = DefaultBackColor;
101 #endif
102                         ForeColor = ThemeEngine.Current.ColorWindowText;
103
104                         base.HScrolled += new EventHandler(RichTextBox_HScrolled);
105                         base.VScrolled += new EventHandler(RichTextBox_VScrolled);
106
107 #if NET_2_0
108                         SetStyle (ControlStyles.StandardDoubleClick, false);
109 #endif
110                 }
111                 #endregion      // Public Constructors
112
113                 #region Private & Internal Methods
114
115                 internal override void HandleLinkClicked (LinkRectangle link)
116                 {
117                         OnLinkClicked (new LinkClickedEventArgs (link.LinkTag.LinkText));
118                 }
119
120                 internal override Color ChangeBackColor (Color backColor)
121                 {
122                         if (backColor == Color.Empty) {
123 #if NET_2_0
124                                 backcolor_set = false;
125                                 if (!ReadOnly) {
126                                         backColor = SystemColors.Window;
127                                 }
128 #else
129                                 backColor = SystemColors.Window;
130 #endif
131                         }
132                         return backColor;
133                 }
134
135                 internal override void RaiseSelectionChanged()
136                 {
137                         OnSelectionChanged (EventArgs.Empty);
138                 }
139                 
140                 private void RichTextBox_LostFocus(object sender, EventArgs e) {
141                         Invalidate();
142                 }
143
144                 private void RichTextBox_GotFocus(object sender, EventArgs e) {
145                         Invalidate();
146                 }
147                 #endregion      // Private & Internal Methods
148
149                 #region Public Instance Properties
150 #if NET_2_0
151                 [Browsable (false)]
152 #endif
153                 public override bool AllowDrop {
154                         get {
155                                 return base.AllowDrop;
156                         }
157
158                         set {
159                                 base.AllowDrop = value;
160                         }
161                 }
162
163                 [DefaultValue(false)]
164 #if NET_2_0
165                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Visible)]
166                 [RefreshProperties (RefreshProperties.Repaint)]
167                 [EditorBrowsable (EditorBrowsableState.Never)]
168                 [Browsable (false)]
169 #else
170                 [Localizable(true)]
171 #endif
172                 public override bool AutoSize {
173                         get {
174                                 return auto_size;
175                         }
176
177                         set {
178                                 base.AutoSize = value;
179                         }
180                 }
181
182                 [MonoTODO ("Value not respected, always true")]
183                 [DefaultValue(false)]
184                 public bool AutoWordSelection {
185                         get { return auto_word_select; }
186                         set { auto_word_select = value; }
187                 }
188
189                 [Browsable(false)]
190                 [EditorBrowsable(EditorBrowsableState.Never)]
191                 public override System.Drawing.Image BackgroundImage {
192                         get { return base.BackgroundImage; }
193                         set { base.BackgroundImage = value; }
194                 }
195
196 #if NET_2_0
197                 [Browsable (false)]
198                 [EditorBrowsable (EditorBrowsableState.Never)]
199                 public override ImageLayout BackgroundImageLayout {
200                         get { return base.BackgroundImageLayout; }
201                         set { base.BackgroundImageLayout = value; }
202                 }
203 #endif
204
205                 [DefaultValue(0)]
206                 [Localizable(true)]
207                 public int BulletIndent {
208                         get {
209                                 return bullet_indent;
210                         }
211
212                         set {
213                                 bullet_indent = value;
214                         }
215                 }
216
217                 [Browsable(false)]
218                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
219                 public bool CanRedo {
220                         get {
221                                 return document.undo.CanRedo;
222                         }
223                 }
224
225                 [DefaultValue(true)]
226                 public bool DetectUrls {
227                         get { return base.EnableLinks; }
228                         set { base.EnableLinks = value; }
229                 }
230
231 #if NET_2_0
232                 [MonoTODO ("Stub, does nothing")]
233                 [DefaultValue (false)]
234                 public bool EnableAutoDragDrop {
235                         get { return enable_auto_drag_drop; }
236                         set { enable_auto_drag_drop = value; }
237                 }
238 #endif
239
240                 public override Font Font {
241                         get {
242                                 return base.Font;
243                         }
244
245                         set {
246                                 if (font != value) {
247                                         Line    start;
248                                         Line    end;
249
250                                         if (auto_size) {
251                                                 if (PreferredHeight != Height) {
252                                                         Height = PreferredHeight;
253                                                 }
254                                         }
255
256                                         base.Font = value;
257
258                                         // Font changes always set the whole doc to that font
259                                         start = document.GetLine(1);
260                                         end = document.GetLine(document.Lines);
261                                         document.FormatText(start, 1, end, end.text.Length + 1, base.Font, Color.Empty, Color.Empty, FormatSpecified.Font);
262                                 }
263                         }
264                 }
265
266                 public override Color ForeColor {
267                         get {
268                                 return base.ForeColor;
269                         }
270
271                         set {
272                                 base.ForeColor = value;
273                         }
274                 }
275
276 #if NET_2_0
277                 [MonoTODO ("Stub, does nothing")]
278                 [Browsable (false)]
279                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
280                 public RichTextBoxLanguageOptions LanguageOption {
281                         get { return language_option; }
282                         set { language_option = value; }
283                 }
284 #endif
285
286                 [DefaultValue(Int32.MaxValue)]
287                 public override int MaxLength {
288                         get { return base.MaxLength; }
289                         set { base.MaxLength = value; }
290                 }
291
292                 [DefaultValue(true)]
293                 public override bool Multiline {
294                         get {
295                                 return base.Multiline;
296                         }
297
298                         set {
299                                 base.Multiline = value;
300                         }
301                 }
302
303                 [Browsable(false)]
304                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
305                 public string RedoActionName {
306                         get {
307                                 return document.undo.RedoActionName;
308                         }
309                 }
310
311 #if NET_2_0
312                 [MonoTODO ("Stub, does nothing")]
313                 [Browsable (false)]
314                 [DefaultValue (true)]
315                 [EditorBrowsable (EditorBrowsableState.Never)]
316                 public bool RichTextShortcutsEnabled {
317                         get { return rich_text_shortcuts_enabled; }
318                         set { rich_text_shortcuts_enabled = value; }
319                 }
320 #endif
321
322                 [DefaultValue(0)]
323                 [Localizable(true)]
324                 [MonoTODO ("Stub, does nothing")]
325                 [MonoInternalNote ("Teach TextControl.RecalculateLine to consider the right margin as well")]
326                 public int RightMargin {
327                         get {
328                                 return margin_right;
329                         }
330
331                         set {
332                                 margin_right = value;
333                         }
334                 }
335
336                 [Browsable(false)]
337                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
338 #if NET_2_0
339                 [RefreshProperties (RefreshProperties.All)]
340 #else
341                 [DefaultValue("")]
342 #endif
343                 public string Rtf {
344                         get {
345                                 Line            start_line;
346                                 Line            end_line;
347
348                                 start_line = document.GetLine(1);
349                                 end_line = document.GetLine(document.Lines);
350                                 return GenerateRTF(start_line, 0, end_line, end_line.text.Length).ToString();
351                         }
352
353                         set {
354                                 MemoryStream    data;
355
356                                 document.Empty();
357                                 data = new MemoryStream(Encoding.ASCII.GetBytes(value), false);
358
359                                 InsertRTFFromStream(data, 0, 1);
360
361                                 data.Close();
362
363                                 Invalidate();
364                         }
365                 }
366
367                 [DefaultValue(RichTextBoxScrollBars.Both)]
368                 [Localizable(true)]
369                 public RichTextBoxScrollBars ScrollBars {
370                         get {
371                                 return scrollbars;
372                         }
373
374                         set {
375                                 if (!Enum.IsDefined (typeof (RichTextBoxScrollBars), value))
376                                         throw new InvalidEnumArgumentException ("value", (int) value,
377                                                 typeof (RichTextBoxScrollBars));
378
379                                 if (value != scrollbars) {
380                                         scrollbars = value;
381                                         CalculateDocument ();
382                                 }
383                         }
384                 }
385
386                 [Browsable(false)]
387                 [DefaultValue("")]
388                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
389                 public string SelectedRtf {
390                         get {
391                                 return GenerateRTF(document.selection_start.line, document.selection_start.pos, document.selection_end.line, document.selection_end.pos).ToString();
392                         }
393
394                         set {                           
395                                 MemoryStream    data;
396                                 int             x;
397                                 int             y;
398                                 int             sel_start;
399                                 int             chars;
400                                 Line            line;
401                                 LineTag         tag;
402
403                                 if (document.selection_visible) {
404                                         document.ReplaceSelection("", false);
405                                 }
406
407                                 sel_start = document.LineTagToCharIndex(document.selection_start.line, document.selection_start.pos);
408
409                                 data = new MemoryStream(Encoding.ASCII.GetBytes(value), false);
410                                 InsertRTFFromStream(data, document.selection_start.pos, document.selection_start.line.line_no, out x, out y, out chars);
411                                 data.Close();
412
413                                 document.CharIndexToLineTag(sel_start + chars + (y - document.selection_start.line.line_no) * 2, out line, out tag, out sel_start);
414                                 document.SetSelection(line, sel_start);
415                                 document.PositionCaret(line, sel_start);
416                                 document.DisplayCaret();
417                                 ScrollToCaret();
418                                 OnTextChanged(EventArgs.Empty);
419                         }
420                 }
421
422                 [Browsable(false)]
423                 [DefaultValue("")]
424                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
425                 public override string SelectedText {
426                         get {
427                                 return base.SelectedText;
428                         }
429
430                         set {
431                                 base.SelectedText = value;
432                         }
433                 }
434
435                 [Browsable(false)]
436                 [DefaultValue(HorizontalAlignment.Left)]
437                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
438                 public HorizontalAlignment SelectionAlignment {
439                         get {
440                                 HorizontalAlignment     align;
441                                 Line                    start;
442                                 Line                    end;
443                                 Line                    line;
444
445                                 start = document.ParagraphStart(document.selection_start.line);
446                                 align = start.alignment;
447
448                                 end = document.ParagraphEnd(document.selection_end.line);
449
450                                 line = start;
451
452                                 while (true) {
453                                         if (line.alignment != align) {
454                                                 return HorizontalAlignment.Left;
455                                         }
456
457                                         if (line == end) {
458                                                 break;
459                                         }
460                                         line = document.GetLine(line.line_no + 1);
461                                 }
462
463                                 return align;
464                         }
465
466                         set {
467                                 Line                    start;
468                                 Line                    end;
469                                 Line                    line;
470
471                                 start = document.ParagraphStart(document.selection_start.line);
472
473                                 end = document.ParagraphEnd(document.selection_end.line);
474
475                                 line = start;
476
477                                 while (true) {
478                                         line.alignment = value;
479
480                                         if (line == end) {
481                                                 break;
482                                         }
483                                         line = document.GetLine(line.line_no + 1);
484                                 }
485                                 this.CalculateDocument();
486                         }
487                 }
488
489 #if NET_2_0
490                 [MonoTODO ("Stub, does nothing")]
491                 [Browsable (false)]
492                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
493                 public Color SelectionBackColor {
494                         get { return selection_back_color; }
495                         set { selection_back_color = value; }
496                 }
497 #endif
498
499                 [Browsable(false)]
500                 [DefaultValue(false)]
501                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
502                 [MonoTODO ("Stub, does nothing")]
503                 public bool SelectionBullet {
504                         get {
505                                 return false;
506                         }
507
508                         set {
509                         }
510                 }
511
512                 [Browsable(false)]
513                 [DefaultValue(0)]
514                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
515                 [MonoTODO ("Stub, does nothing")]
516                 public int SelectionCharOffset {
517                         get {
518                                 return 0;
519                         }
520
521                         set {
522                         }
523                 }
524
525                 [Browsable(false)]
526                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
527                 public Color SelectionColor {
528                         get {
529                                 Color   color;
530                                 LineTag start;
531                                 LineTag end;
532                                 LineTag tag;
533
534                                 if (selection_length > 0) {
535                                         start = document.selection_start.line.FindTag (document.selection_start.pos + 1);
536                                         end = document.selection_start.line.FindTag (document.selection_end.pos);
537                                 } else {
538                                         start = document.selection_start.line.FindTag (document.selection_start.pos);
539                                         end = start;
540                                 }
541
542                                 color = start.Color;
543
544                                 tag = start;
545                                 while (tag != null) {
546
547                                         if (!color.Equals (tag.Color))
548                                                 return Color.Empty;
549
550                                         if (tag == end)
551                                                 break;
552
553                                         tag = document.NextTag (tag);
554                                 }
555
556                                 return color;
557                         }
558
559                         set {
560                                 if (value == Color.Empty)
561                                         value = DefaultForeColor;
562                                         
563                                 int sel_start;
564                                 int sel_end;
565
566                                 sel_start = document.LineTagToCharIndex(document.selection_start.line, document.selection_start.pos);
567                                 sel_end = document.LineTagToCharIndex(document.selection_end.line, document.selection_end.pos);
568
569                                 document.FormatText (document.selection_start.line, document.selection_start.pos + 1,
570                                                 document.selection_end.line, document.selection_end.pos + 1, null,
571                                                 value, Color.Empty, FormatSpecified.Color);
572
573                                 document.CharIndexToLineTag(sel_start, out document.selection_start.line, out document.selection_start.tag, out document.selection_start.pos);
574                                 document.CharIndexToLineTag(sel_end, out document.selection_end.line, out document.selection_end.tag, out document.selection_end.pos);
575
576                                 document.UpdateView(document.selection_start.line, 0);
577
578                                 //Re-Align the caret in case its changed size or position
579                                 //probably not necessary here
580                                 document.AlignCaret(false);
581                         }
582                 }
583
584                 [Browsable(false)]
585                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
586                 public Font SelectionFont {
587                         get {
588                                 Font    font;
589                                 LineTag start;
590                                 LineTag end;
591                                 LineTag tag;
592
593                                 if (selection_length > 0) {
594                                         start = document.selection_start.line.FindTag (document.selection_start.pos + 1);
595                                         end = document.selection_start.line.FindTag (document.selection_end.pos);
596                                 } else {
597                                         start = document.selection_start.line.FindTag (document.selection_start.pos);
598                                         end = start;
599                                 }
600
601                                 font = start.Font;
602
603                                 if (selection_length > 1) {
604                                         tag = start;
605                                         while (tag != null) {
606
607                                                 if (!font.Equals(tag.Font))
608                                                         return null;
609
610                                                 if (tag == end)
611                                                         break;
612
613                                                 tag = document.NextTag (tag);
614                                         }
615                                 }
616
617                                 return font;
618                         }
619
620                         set {
621                                 int             sel_start;
622                                 int             sel_end;
623
624                                 sel_start = document.LineTagToCharIndex(document.selection_start.line, document.selection_start.pos);
625                                 sel_end = document.LineTagToCharIndex(document.selection_end.line, document.selection_end.pos);
626
627                                 document.FormatText (document.selection_start.line, document.selection_start.pos + 1,
628                                                 document.selection_end.line, document.selection_end.pos + 1, value,
629                                                 Color.Empty, Color.Empty, FormatSpecified.Font);
630
631                                 document.CharIndexToLineTag(sel_start, out document.selection_start.line, out document.selection_start.tag, out document.selection_start.pos);
632                                 document.CharIndexToLineTag(sel_end, out document.selection_end.line, out document.selection_end.tag, out document.selection_end.pos);
633
634                                 document.UpdateView(document.selection_start.line, 0);
635                                 //Re-Align the caret in case its changed size or position
636                                 Document.AlignCaret (false);
637
638                         }
639                 }
640
641                 [Browsable(false)]
642                 [DefaultValue(0)]
643                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
644                 [MonoTODO ("Stub, does nothing")]
645                 public int SelectionHangingIndent {
646                         get {
647                                 return 0;
648                         }
649
650                         set {
651                         }
652                 }
653
654                 [Browsable(false)]
655                 [DefaultValue(0)]
656                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
657                 [MonoTODO ("Stub, does nothing")]
658                 public int SelectionIndent {
659                         get {
660                                 return 0;
661                         }
662
663                         set {
664                         }
665                 }
666
667                 [Browsable(false)]
668                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
669                 public override int SelectionLength {
670                         get {
671                                 return base.SelectionLength;
672                         }
673
674                         set {
675                                 base.SelectionLength = value;
676                         }
677                 }
678
679                 [Browsable(false)]
680                 [DefaultValue(false)]
681                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
682                 [MonoTODO ("Stub, does nothing")]
683                 public bool SelectionProtected {
684                         get {
685                                 return false;
686                         }
687
688                         set {
689                         }
690                 }
691
692                 [Browsable(false)]
693                 [DefaultValue(0)]
694                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
695                 [MonoTODO ("Stub, does nothing")]
696                 public int SelectionRightIndent {
697                         get {
698                                 return 0;
699                         }
700
701                         set {
702                         }
703                 }
704
705                 [Browsable(false)]
706                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
707                 [MonoTODO ("Stub, does nothing")]
708                 public int[] SelectionTabs {
709                         get {
710                                 return new int[0];
711                         }
712
713                         set {
714                         }
715                 }
716
717                 [Browsable(false)]
718                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
719                 public RichTextBoxSelectionTypes SelectionType {
720                         get {
721                                 if (document.selection_start == document.selection_end) {
722                                         return RichTextBoxSelectionTypes.Empty;
723                                 }
724
725                                 // Lazy, but works
726                                 if (SelectedText.Length > 1) {
727                                         return RichTextBoxSelectionTypes.MultiChar | RichTextBoxSelectionTypes.Text;
728                                 }
729
730                                 return RichTextBoxSelectionTypes.Text;
731                         }
732                 }
733
734                 [DefaultValue(false)]
735                 [MonoTODO ("Stub, does nothing")]
736                 public bool ShowSelectionMargin {
737                         get {
738                                 return false;
739                         }
740
741                         set {
742                         }
743                 }
744
745                 [Localizable(true)]
746 #if NET_2_0
747                 [RefreshProperties (RefreshProperties.All)]
748 #endif
749                 public override string Text {
750                         get {
751                                 return base.Text;
752                         }
753
754                         set {
755                                 base.Text = value;
756                         }
757                 }
758
759                 [Browsable(false)]
760                 public override int TextLength {
761                         get {
762                                 return base.TextLength;
763                         }
764                 }
765
766                 [Browsable(false)]
767                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
768                 public string UndoActionName {
769                         get {
770                                 return document.undo.UndoActionName;
771                         }
772                 }
773
774                 [Localizable(true)]
775                 [DefaultValue(1)]
776                 public float ZoomFactor {
777                         get {
778                                 return zoom;
779                         }
780
781                         set {
782                                 zoom = value;
783                         }
784                 }
785                 #endregion      // Public Instance Properties
786
787                 #region Protected Instance Properties
788                 protected override CreateParams CreateParams {
789                         get {
790                                 return base.CreateParams;
791                         }
792                 }
793
794                 protected override Size DefaultSize {
795                         get {
796                                 return new Size(100, 96);
797                         }
798                 }
799                 #endregion      // Protected Instance Properties
800
801                 #region Public Instance Methods
802                 public bool CanPaste(DataFormats.Format clipFormat) {
803                         if ((clipFormat.Name == DataFormats.Rtf) ||
804                                 (clipFormat.Name == DataFormats.Text) ||
805                                 (clipFormat.Name == DataFormats.UnicodeText)) {
806                                         return true;
807                         }
808                         return false;
809                 }
810
811                 public int Find(char[] characterSet) {
812                         return Find(characterSet, -1, -1);
813                 }
814
815                 public int Find(char[] characterSet, int start) {
816                         return Find(characterSet, start, -1);
817                 }
818
819                 public int Find(char[] characterSet, int start, int end) {
820                         Document.Marker start_mark;
821                         Document.Marker end_mark;
822                         Document.Marker result;
823
824                         if (start == -1) {
825                                 document.GetMarker(out start_mark, true);
826                         } else {
827                                 Line line;
828                                 LineTag tag;
829                                 int pos;
830
831                                 start_mark = new Document.Marker();
832
833                                 document.CharIndexToLineTag(start, out line, out tag, out pos);
834                                 start_mark.line = line;
835                                 start_mark.tag = tag;
836                                 start_mark.pos = pos;
837                         }
838
839                         if (end == -1) {
840                                 document.GetMarker(out end_mark, false);
841                         } else {
842                                 Line line;
843                                 LineTag tag;
844                                 int pos;
845
846                                 end_mark = new Document.Marker();
847
848                                 document.CharIndexToLineTag(end, out line, out tag, out pos);
849                                 end_mark.line = line;
850                                 end_mark.tag = tag;
851                                 end_mark.pos = pos;
852                         }
853
854                         if (document.FindChars(characterSet, start_mark, end_mark, out result)) {
855                                 return document.LineTagToCharIndex(result.line, result.pos);
856                         }
857
858                         return -1;
859                 }
860
861                 public int Find(string str) {
862                         return Find(str, -1, -1, RichTextBoxFinds.None);
863                 }
864
865                 public int Find(string str, int start, int end, RichTextBoxFinds options) {
866                         Document.Marker start_mark;
867                         Document.Marker end_mark;
868                         Document.Marker result;
869
870                         if (start == -1) {
871                                 document.GetMarker(out start_mark, true);
872                         } else {
873                                 Line line;
874                                 LineTag tag;
875                                 int pos;
876
877                                 start_mark = new Document.Marker();
878
879                                 document.CharIndexToLineTag(start, out line, out tag, out pos);
880
881                                 start_mark.line = line;
882                                 start_mark.tag = tag;
883                                 start_mark.pos = pos;
884                         }
885
886                         if (end == -1) {
887                                 document.GetMarker(out end_mark, false);
888                         } else {
889                                 Line line;
890                                 LineTag tag;
891                                 int pos;
892
893                                 end_mark = new Document.Marker();
894
895                                 document.CharIndexToLineTag(end, out line, out tag, out pos);
896
897                                 end_mark.line = line;
898                                 end_mark.tag = tag;
899                                 end_mark.pos = pos;
900                         }
901
902                         if (document.Find(str, start_mark, end_mark, out result, options)) {
903                                 return document.LineTagToCharIndex(result.line, result.pos);
904                         }
905
906                         return -1;
907                 }
908
909                 public int Find(string str, int start, RichTextBoxFinds options) {
910                         return Find(str, start, -1, options);
911                 }
912
913                 public int Find(string str, RichTextBoxFinds options) {
914                         return Find(str, -1, -1, options);
915                 }
916
917                 
918 #if !NET_2_0
919                 public char GetCharFromPosition(Point pt) {
920                         LineTag tag;
921                         int     pos;
922
923                         PointToTagPos(pt, out tag, out pos);
924
925                         if (pos >= tag.Line.text.Length) {
926                                 return '\n';
927                         }
928
929                         return tag.Line.text[pos];
930                 }
931 #else
932                 internal override char GetCharFromPositionInternal (Point p)
933                 {
934                         LineTag tag;
935                         int pos;
936
937                         PointToTagPos (p, out tag, out pos);
938
939                         if (pos >= tag.Line.text.Length)
940                                 return '\n';
941
942                         return tag.Line.text[pos];
943                 }
944 #endif
945
946                 public
947 #if NET_2_0
948                 override
949 #endif  
950                 int GetCharIndexFromPosition(Point pt) {
951                         LineTag tag;
952                         int     pos;
953
954                         PointToTagPos(pt, out tag, out pos);
955
956                         return document.LineTagToCharIndex(tag.Line, pos);
957                 }
958
959                 public
960 #if NET_2_0
961                 override
962 #endif
963                 int GetLineFromCharIndex(int index) {
964                         Line    line;
965                         LineTag tag;
966                         int     pos;
967
968                         document.CharIndexToLineTag(index, out line, out tag, out pos);
969
970                         return line.LineNo - 1;
971                 }
972
973                 public
974 #if NET_2_0
975                 override
976 #endif
977                 Point GetPositionFromCharIndex(int index) {
978                         Line    line;
979                         LineTag tag;
980                         int     pos;
981
982                         document.CharIndexToLineTag(index, out line, out tag, out pos);
983                         return new Point(line.X + (int)line.widths[pos] + document.OffsetX - document.ViewPortX, 
984                                          line.Y + document.OffsetY - document.ViewPortY);
985                 }
986
987                 public void LoadFile(System.IO.Stream data, RichTextBoxStreamType fileType) {
988                         document.Empty();
989
990                         
991                         // FIXME - ignoring unicode
992                         if (fileType == RichTextBoxStreamType.PlainText) {
993                                 StringBuilder sb;
994                                 char[] buffer;
995
996                                 try {
997                                         sb = new StringBuilder ((int) data.Length);
998                                         buffer = new char [1024];
999                                 } catch {
1000                                         throw new IOException("Not enough memory to load document");
1001                                 }
1002
1003                                 StreamReader sr = new StreamReader (data, Encoding.Default, true);
1004                                 int charsRead = sr.Read (buffer, 0, buffer.Length);
1005                                 while (charsRead > 0) {
1006                                         sb.Append (buffer, 0, charsRead);
1007                                         charsRead = sr.Read (buffer, 0, buffer.Length);
1008                                 }
1009
1010                                 // Remove the EOF converted to an extra EOL by the StreamReader
1011                                 if (sb.Length > 0 && sb [sb.Length - 1] == '\n')
1012                                         sb.Remove (sb.Length - 1, 1);
1013
1014                                 base.Text = sb.ToString();
1015                                 return;
1016                         }
1017
1018                         InsertRTFFromStream(data, 0, 1);
1019
1020                         document.PositionCaret (document.GetLine (1), 0);
1021                         document.SetSelectionToCaret (true);
1022                         ScrollToCaret ();
1023                 }
1024
1025                 public void LoadFile(string path) {
1026                         LoadFile (path, RichTextBoxStreamType.RichText);
1027                 }
1028
1029                 public void LoadFile(string path, RichTextBoxStreamType fileType) {
1030                         FileStream      data;
1031
1032                         data = null;
1033
1034
1035                         try {
1036                                 data = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 1024);
1037
1038                                 LoadFile(data, fileType);
1039                         }
1040 #if !DEBUG
1041                         catch (Exception ex) {
1042                                 throw new IOException("Could not open file " + path, ex);
1043                         }
1044 #endif
1045                         finally {
1046                                 if (data != null) {
1047                                         data.Close();
1048                                 }
1049                         }
1050                 }
1051
1052                 public void Paste(DataFormats.Format clipFormat) {
1053                         base.Paste(Clipboard.GetDataObject(), clipFormat, false);
1054                 }
1055
1056                 public void Redo()
1057                 {
1058                         if (document.undo.Redo ())
1059                                 OnTextChanged (EventArgs.Empty);
1060                 }
1061
1062                 public void SaveFile(Stream data, RichTextBoxStreamType fileType) {
1063                         Encoding        encoding;
1064                         int             i;
1065                         Byte[]          bytes;
1066
1067
1068                         if (fileType == RichTextBoxStreamType.UnicodePlainText) {
1069                                 encoding = Encoding.Unicode;
1070                         } else {
1071                                 encoding = Encoding.ASCII;
1072                         }
1073
1074                         switch(fileType) {
1075                                 case RichTextBoxStreamType.PlainText: 
1076                                 case RichTextBoxStreamType.TextTextOleObjs: 
1077                                 case RichTextBoxStreamType.UnicodePlainText: {
1078                                         if (!Multiline) {
1079                                                 bytes = encoding.GetBytes(document.Root.text.ToString());
1080                                                 data.Write(bytes, 0, bytes.Length);
1081                                                 return;
1082                                         }
1083
1084                                         for (i = 1; i < document.Lines; i++) {
1085                                                 // Normalize the new lines to the system ones
1086                                                 string line_text = document.GetLine (i).TextWithoutEnding () + Environment.NewLine;
1087                                                 bytes = encoding.GetBytes(line_text);
1088                                                 data.Write(bytes, 0, bytes.Length);
1089                                         }
1090                                         bytes = encoding.GetBytes(document.GetLine(document.Lines).text.ToString());
1091                                         data.Write(bytes, 0, bytes.Length);
1092                                         return;
1093                                 }
1094                         }
1095
1096                         // If we're here we're saving RTF
1097                         Line            start_line;
1098                         Line            end_line;
1099                         StringBuilder   rtf;
1100                         int             current;
1101                         int             total;
1102
1103                         start_line = document.GetLine(1);
1104                         end_line = document.GetLine(document.Lines);
1105                         rtf = GenerateRTF(start_line, 0, end_line, end_line.text.Length);
1106                         total = rtf.Length;
1107                         bytes = new Byte[4096];
1108
1109                         // Let's chunk it so we don't use up all memory...
1110                         for (i = 0; i < total; i += 1024) {
1111                                 if ((i + 1024) < total) {
1112                                         current = encoding.GetBytes(rtf.ToString(i, 1024), 0, 1024, bytes, 0);
1113                                 } else {
1114                                         current = total - i;
1115                                         current = encoding.GetBytes(rtf.ToString(i, current), 0, current, bytes, 0);
1116                                 }
1117                                 data.Write(bytes, 0, current);
1118                         }
1119                 }
1120
1121                 public void SaveFile(string path) {
1122                         if (path.EndsWith(".rtf")) {
1123                                 SaveFile(path, RichTextBoxStreamType.RichText);
1124                         } else {
1125                                 SaveFile(path, RichTextBoxStreamType.PlainText);
1126                         }
1127                 }
1128
1129                 public void SaveFile(string path, RichTextBoxStreamType fileType) {
1130                         FileStream      data;
1131
1132                         data = null;
1133
1134 //                      try {
1135                                 data = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, 1024, false);
1136                                 SaveFile(data, fileType);
1137 //                      }
1138
1139 //                      catch {
1140 //                              throw new IOException("Could not write document to file " + path);
1141 //                      }
1142
1143 //                      finally {
1144                                 if (data != null) {
1145                                         data.Close();
1146                                 }
1147 //                      }
1148                 }
1149
1150 #if NET_2_0
1151                 [EditorBrowsable (EditorBrowsableState.Never)]
1152                 public new void DrawToBitmap (Bitmap bitmap, Rectangle targetBounds)
1153                 {
1154                         Graphics dc = Graphics.FromImage (bitmap);
1155
1156                         Draw (dc, targetBounds);
1157                 }
1158 #endif
1159
1160                 #endregion      // Public Instance Methods
1161
1162                 #region Protected Instance Methods
1163                 protected virtual object CreateRichEditOleCallback() {
1164                         throw new NotImplementedException();
1165                 }
1166
1167                 protected override void OnBackColorChanged(EventArgs e) {
1168                         base.OnBackColorChanged (e);
1169                 }
1170
1171                 protected virtual void OnContentsResized(ContentsResizedEventArgs e) {
1172                         ContentsResizedEventHandler eh = (ContentsResizedEventHandler)(Events [ContentsResizedEvent]);
1173                         if (eh != null)
1174                                 eh (this, e);
1175                 }
1176
1177                 protected override void OnContextMenuChanged(EventArgs e) {
1178                         base.OnContextMenuChanged (e);
1179                 }
1180
1181                 protected override void OnHandleCreated(EventArgs e) {
1182                         base.OnHandleCreated (e);
1183                 }
1184
1185                 protected override void OnHandleDestroyed(EventArgs e) {
1186                         base.OnHandleDestroyed (e);
1187                 }
1188
1189                 protected virtual void OnHScroll(EventArgs e) {
1190                         EventHandler eh = (EventHandler)(Events [HScrollEvent]);
1191                         if (eh != null)
1192                                 eh (this, e);
1193                 }
1194
1195                 [MonoTODO ("Stub, never called")]
1196                 protected virtual void OnImeChange(EventArgs e) {
1197                         EventHandler eh = (EventHandler)(Events [ImeChangeEvent]);
1198                         if (eh != null)
1199                                 eh (this, e);
1200                 }
1201
1202                 protected virtual void OnLinkClicked(LinkClickedEventArgs e) {
1203                         LinkClickedEventHandler eh = (LinkClickedEventHandler)(Events [LinkClickedEvent]);
1204                         if (eh != null)
1205                                 eh (this, e);
1206                 }
1207
1208                 protected virtual void OnProtected(EventArgs e) {
1209                         EventHandler eh = (EventHandler)(Events [ProtectedEvent]);
1210                         if (eh != null)
1211                                 eh (this, e);
1212                 }
1213
1214                 protected override void OnRightToLeftChanged(EventArgs e) {
1215                         base.OnRightToLeftChanged (e);
1216                 }
1217
1218                 protected virtual void OnSelectionChanged(EventArgs e) {
1219                         EventHandler eh = (EventHandler)(Events [SelectionChangedEvent]);
1220                         if (eh != null)
1221                                 eh (this, e);
1222                 }
1223
1224 #if !NET_2_0
1225                 protected override void OnSystemColorsChanged(EventArgs e) {
1226                         base.OnSystemColorsChanged (e);
1227                 }
1228
1229                 protected override void OnTextChanged(EventArgs e) {
1230                         base.OnTextChanged (e);
1231                 }
1232 #endif
1233
1234                 protected virtual void OnVScroll(EventArgs e) {
1235                         EventHandler eh = (EventHandler)(Events [VScrollEvent]);
1236                         if (eh != null)
1237                                 eh (this, e);
1238                 }
1239
1240                 protected override void WndProc(ref Message m) {
1241                         base.WndProc (ref m);
1242                 }
1243
1244 #if NET_2_0
1245                 protected override bool ProcessCmdKey (ref Message m, Keys keyData)
1246                 {
1247                         return base.ProcessCmdKey (ref m, keyData);
1248                 }
1249 #endif
1250                 #endregion      // Protected Instance Methods
1251
1252                 #region Events
1253                 static object ContentsResizedEvent = new object ();
1254                 static object HScrollEvent = new object ();
1255                 static object ImeChangeEvent = new object ();
1256                 static object LinkClickedEvent = new object ();
1257                 static object ProtectedEvent = new object ();
1258                 static object SelectionChangedEvent = new object ();
1259                 static object VScrollEvent = new object ();
1260
1261                 [Browsable(false)]
1262                 [EditorBrowsable(EditorBrowsableState.Never)]
1263                 public new event EventHandler BackgroundImageChanged {
1264                         add { base.BackgroundImageChanged += value; }
1265                         remove { base.BackgroundImageChanged -= value; }
1266                 }
1267
1268 #if NET_2_0
1269                 [Browsable (false)]
1270                 [EditorBrowsable (EditorBrowsableState.Never)]
1271                 public new event EventHandler BackgroundImageLayoutChanged {
1272                         add { base.BackgroundImageLayoutChanged += value; }
1273                         remove { base.BackgroundImageLayoutChanged -= value; }
1274                 }
1275 #endif
1276
1277                 public event ContentsResizedEventHandler ContentsResized {
1278                         add { Events.AddHandler (ContentsResizedEvent, value); }
1279                         remove { Events.RemoveHandler (ContentsResizedEvent, value); }
1280                 }
1281
1282 #if !NET_2_0
1283                 [Browsable(false)]
1284                 [EditorBrowsable(EditorBrowsableState.Never)]
1285                 public new event EventHandler DoubleClick {
1286                         add { base.DoubleClick += value; }
1287                         remove { base.DoubleClick -= value; }
1288                 }
1289 #endif
1290
1291                 [Browsable(false)]
1292 #if !NET_2_0
1293                 [EditorBrowsable(EditorBrowsableState.Never)]
1294 #endif
1295                 public new event DragEventHandler DragDrop {
1296                         add { base.DragDrop += value; }
1297                         remove { base.DragDrop -= value; }
1298                 }
1299
1300                 [Browsable(false)]
1301 #if !NET_2_0
1302                 [EditorBrowsable(EditorBrowsableState.Never)]
1303 #endif
1304                 public new event DragEventHandler DragEnter {
1305                         add { base.DragEnter += value; }
1306                         remove { base.DragEnter -= value; }
1307                 }
1308
1309                 [Browsable(false)]
1310                 [EditorBrowsable(EditorBrowsableState.Never)]
1311                 public new event EventHandler DragLeave {
1312                         add { base.DragLeave += value; }
1313                         remove { base.DragLeave -= value; }
1314                 }
1315
1316
1317                 [Browsable(false)]
1318                 [EditorBrowsable(EditorBrowsableState.Never)]
1319                 public new event DragEventHandler DragOver {
1320                         add { base.DragOver += value; }
1321                         remove { base.DragOver -= value; }
1322                 }
1323
1324
1325                 [Browsable(false)]
1326                 [EditorBrowsable(EditorBrowsableState.Never)]
1327                 public new event GiveFeedbackEventHandler GiveFeedback {
1328                         add { base.GiveFeedback += value; }
1329                         remove { base.GiveFeedback -= value; }
1330                 }
1331
1332                 public event EventHandler HScroll {
1333                         add { Events.AddHandler (HScrollEvent, value); }
1334                         remove { Events.RemoveHandler (HScrollEvent, value); }
1335                 }
1336
1337                 public event EventHandler ImeChange {
1338                         add { Events.AddHandler (ImeChangeEvent, value); }
1339                         remove { Events.RemoveHandler (ImeChangeEvent, value); }
1340                 }
1341
1342                 public event LinkClickedEventHandler LinkClicked {
1343                         add { Events.AddHandler (LinkClickedEvent, value); }
1344                         remove { Events.RemoveHandler (LinkClickedEvent, value); }
1345                 }
1346
1347                 public event EventHandler Protected {
1348                         add { Events.AddHandler (ProtectedEvent, value); }
1349                         remove { Events.RemoveHandler (ProtectedEvent, value); }
1350                 }
1351
1352                 [Browsable(false)]
1353                 [EditorBrowsable(EditorBrowsableState.Never)]
1354                 public new event QueryContinueDragEventHandler QueryContinueDrag {
1355                         add { base.QueryContinueDrag += value; }
1356                         remove { base.QueryContinueDrag -= value; }
1357                 }
1358
1359                 [MonoTODO ("Event never raised")]
1360                 public event EventHandler SelectionChanged {
1361                         add { Events.AddHandler (SelectionChangedEvent, value); }
1362                         remove { Events.RemoveHandler (SelectionChangedEvent, value); }
1363                 }
1364
1365                 public event EventHandler VScroll {
1366                         add { Events.AddHandler (VScrollEvent, value); }
1367                         remove { Events.RemoveHandler (VScrollEvent, value); }
1368                 }
1369                 #endregion      // Events
1370
1371                 #region Private Methods
1372
1373                 internal override void SelectWord ()
1374                 {
1375                         document.ExpandSelection(CaretSelection.Word, false);
1376                 }
1377
1378                 private class RtfSectionStyle : ICloneable {
1379                         internal Color rtf_color;
1380                         internal RTF.Font rtf_rtffont;
1381                         internal int rtf_rtffont_size;
1382                         internal FontStyle rtf_rtfstyle;
1383                         internal HorizontalAlignment rtf_rtfalign;
1384                         internal int rtf_par_line_left_indent;
1385                         internal bool rtf_visible;
1386                         internal int rtf_skip_width;
1387
1388                         public object Clone ()
1389                         {
1390                                 RtfSectionStyle new_style = new RtfSectionStyle ();
1391
1392                                 new_style.rtf_color = rtf_color;
1393                                 new_style.rtf_par_line_left_indent = rtf_par_line_left_indent;
1394                                 new_style.rtf_rtfalign = rtf_rtfalign;
1395                                 new_style.rtf_rtffont = rtf_rtffont;
1396                                 new_style.rtf_rtffont_size = rtf_rtffont_size;
1397                                 new_style.rtf_rtfstyle = rtf_rtfstyle;
1398                                 new_style.rtf_visible = rtf_visible;
1399                                 new_style.rtf_skip_width = rtf_skip_width;
1400
1401                                 return new_style;
1402                         }
1403                 }
1404
1405                 // To allow us to keep track of the sections and revert formatting
1406                 // as we go in and out of sections of the document.
1407                 private void HandleGroup (RTF.RTF rtf)
1408                 {
1409                         //start group - save the current formatting on to a stack
1410                         //end group - go back to the formatting at the current group
1411                         if (rtf_section_stack == null) {
1412                                 rtf_section_stack = new Stack ();
1413                         }
1414
1415                         if (rtf.Major == RTF.Major.BeginGroup) {
1416                                 rtf_section_stack.Push (rtf_style.Clone ());
1417                                 //spec specifies resetting unicode ignore at begin group as an attempt at error
1418                                 //recovery.
1419                                 rtf_skip_count = 0;
1420                         } else if (rtf.Major == RTF.Major.EndGroup) {
1421                                 if (rtf_section_stack.Count > 0) {
1422                                         FlushText (rtf, false);
1423
1424                                         rtf_style = (RtfSectionStyle) rtf_section_stack.Pop ();
1425                                 }
1426                         }
1427                 }
1428
1429                 [MonoInternalNote ("Add QuadJust support for justified alignment")]
1430                 private void HandleControl(RTF.RTF rtf) {
1431                         switch(rtf.Major) {
1432                                 case RTF.Major.Unicode: {
1433                                         switch(rtf.Minor) {
1434                                                 case RTF.Minor.UnicodeCharBytes: {
1435                                                         rtf_style.rtf_skip_width = rtf.Param;
1436                                                         break;
1437                                                 }
1438
1439                                                 case RTF.Minor.UnicodeChar: {
1440                                                         FlushText (rtf, false);
1441                                                         rtf_skip_count += rtf_style.rtf_skip_width;
1442                                                         rtf_line.Append((char)rtf.Param);
1443                                                         break;
1444                                                 }
1445                                         }
1446                                         break;
1447                                 }
1448
1449                                 case RTF.Major.Destination: {
1450 //                                      Console.Write("[Got Destination control {0}]", rtf.Minor);
1451                                         rtf.SkipGroup();
1452                                         break;
1453                                 }
1454
1455                                 case RTF.Major.PictAttr:
1456                                         if (rtf.Picture != null && rtf.Picture.IsValid ()) {
1457                                                 Line line = document.GetLine (rtf_cursor_y);
1458                                                 document.InsertPicture (line, 0, rtf.Picture);
1459                                                 rtf_cursor_x++;
1460
1461                                                 FlushText (rtf, true);
1462                                                 rtf.Picture = null;
1463                                         }
1464                                         break;
1465
1466                                 case RTF.Major.CharAttr: {
1467                                         switch(rtf.Minor) {
1468                                                 case RTF.Minor.ForeColor: {
1469                                                         System.Windows.Forms.RTF.Color  color;
1470
1471                                                         color = System.Windows.Forms.RTF.Color.GetColor(rtf, rtf.Param);
1472                                                         
1473                                                         if (color != null) {
1474                                                                 FlushText(rtf, false);
1475                                                                 if (color.Red == -1 && color.Green == -1 && color.Blue == -1) {
1476                                                                         this.rtf_style.rtf_color = ForeColor;
1477                                                                 } else {
1478                                                                         this.rtf_style.rtf_color = Color.FromArgb(color.Red, color.Green, color.Blue);
1479                                                                 }
1480                                                                 FlushText (rtf, false);
1481                                                         }
1482                                                         break;
1483                                                 }
1484
1485                                                 case RTF.Minor.FontSize: {
1486                                                         FlushText(rtf, false);
1487                                                         this.rtf_style.rtf_rtffont_size = rtf.Param / 2;
1488                                                         break;
1489                                                 }
1490
1491                                                 case RTF.Minor.FontNum: {
1492                                                         System.Windows.Forms.RTF.Font   font;
1493
1494                                                         font = System.Windows.Forms.RTF.Font.GetFont(rtf, rtf.Param);
1495                                                         if (font != null) {
1496                                                                 FlushText(rtf, false);
1497                                                                 this.rtf_style.rtf_rtffont = font;
1498                                                         }
1499                                                         break;
1500                                                 }
1501
1502                                                 case RTF.Minor.Plain: {
1503                                                         FlushText(rtf, false);
1504                                                         rtf_style.rtf_rtfstyle = FontStyle.Regular;
1505                                                         break;
1506                                                 }
1507
1508                                                 case RTF.Minor.Bold: {
1509                                                         FlushText(rtf, false);
1510                                                         if (rtf.Param == RTF.RTF.NoParam) {
1511                                                                 rtf_style.rtf_rtfstyle |= FontStyle.Bold;
1512                                                         } else {
1513                                                                 rtf_style.rtf_rtfstyle &= ~FontStyle.Bold;
1514                                                         }
1515                                                         break;
1516                                                 }
1517
1518                                                 case RTF.Minor.Italic: {
1519                                                         FlushText(rtf, false);
1520                                                         if (rtf.Param == RTF.RTF.NoParam) {
1521                                                                 rtf_style.rtf_rtfstyle |= FontStyle.Italic;
1522                                                         } else {
1523                                                                 rtf_style.rtf_rtfstyle &= ~FontStyle.Italic;
1524                                                         }
1525                                                         break;
1526                                                 }
1527
1528                                                 case RTF.Minor.StrikeThru: {
1529                                                         FlushText(rtf, false);
1530                                                         if (rtf.Param == RTF.RTF.NoParam) {
1531                                                                 rtf_style.rtf_rtfstyle |= FontStyle.Strikeout;
1532                                                         } else {
1533                                                                 rtf_style.rtf_rtfstyle &= ~FontStyle.Strikeout;
1534                                                         }
1535                                                         break;
1536                                                 }
1537
1538                                                 case RTF.Minor.Underline: {
1539                                                         FlushText(rtf, false);
1540                                                         if (rtf.Param == RTF.RTF.NoParam) {
1541                                                                 rtf_style.rtf_rtfstyle |= FontStyle.Underline;
1542                                                         } else {
1543                                                                 rtf_style.rtf_rtfstyle = rtf_style.rtf_rtfstyle & ~FontStyle.Underline;
1544                                                         }
1545                                                         break;
1546                                                 }
1547
1548                                                 case RTF.Minor.Invisible: {
1549                                                         FlushText (rtf, false);
1550                                                         rtf_style.rtf_visible = false;
1551                                                         break;
1552                                                 }
1553
1554                                                 case RTF.Minor.NoUnderline: {
1555                                                         FlushText(rtf, false);
1556                                                         rtf_style.rtf_rtfstyle &= ~FontStyle.Underline;
1557                                                         break;
1558                                                 }
1559                                         }
1560                                         break;
1561                                 }
1562
1563                         case RTF.Major.ParAttr: {
1564                                 switch (rtf.Minor) {
1565
1566                                 case RTF.Minor.ParDef:
1567                                         FlushText (rtf, false);
1568                                         rtf_style.rtf_par_line_left_indent = 0;
1569                                         rtf_style.rtf_rtfalign = HorizontalAlignment.Left;
1570                                         break;
1571
1572                                 case RTF.Minor.LeftIndent:
1573                                         rtf_style.rtf_par_line_left_indent = (int) (((float) rtf.Param / 1440.0F) * CreateGraphics ().DpiX + 0.5F);
1574                                         break;
1575
1576                                 case RTF.Minor.QuadCenter:
1577                                         FlushText (rtf, false);
1578                                         rtf_style.rtf_rtfalign = HorizontalAlignment.Center;
1579                                         break;
1580
1581                                 case RTF.Minor.QuadJust:
1582                                         FlushText (rtf, false);
1583                                         rtf_style.rtf_rtfalign = HorizontalAlignment.Center;
1584                                         break;
1585
1586                                 case RTF.Minor.QuadLeft:
1587                                         FlushText (rtf, false);
1588                                         rtf_style.rtf_rtfalign = HorizontalAlignment.Left;
1589                                         break;
1590
1591                                 case RTF.Minor.QuadRight:
1592                                         FlushText (rtf, false);
1593                                         rtf_style.rtf_rtfalign = HorizontalAlignment.Right;
1594                                         break;
1595                                 }
1596                                 break;
1597                         }
1598
1599                         case RTF.Major.SpecialChar: {
1600                                         //Console.Write("[Got SpecialChar control {0}]", rtf.Minor);
1601                                         SpecialChar (rtf);
1602                                         break;
1603                                 }
1604                         }
1605                 }
1606
1607                 private void SpecialChar(RTF.RTF rtf) {
1608                         switch(rtf.Minor) {
1609                                 case RTF.Minor.Page:
1610                                 case RTF.Minor.Sect:
1611                                 case RTF.Minor.Row:
1612                                 case RTF.Minor.Line:
1613                                 case RTF.Minor.Par: {
1614                                         FlushText(rtf, true);
1615                                         break;
1616                                 }
1617
1618                                 case RTF.Minor.Cell: {
1619                                         Console.Write(" ");
1620                                         break;
1621                                 }
1622
1623                                 case RTF.Minor.NoBrkSpace: {
1624                                         Console.Write(" ");
1625                                         break;
1626                                 }
1627
1628                                 case RTF.Minor.Tab: {
1629                                         rtf_line.Append ("\t");
1630 //                                      FlushText (rtf, false);
1631                                         break;
1632                                 }
1633
1634                                 case RTF.Minor.NoReqHyphen:
1635                                 case RTF.Minor.NoBrkHyphen: {
1636                                         rtf_line.Append ("-");
1637 //                                      FlushText (rtf, false);
1638                                         break;
1639                                 }
1640
1641                                 case RTF.Minor.Bullet: {
1642                                         Console.WriteLine("*");
1643                                         break;
1644                                 }
1645
1646                         case RTF.Minor.WidowCtrl:
1647                                 break;
1648
1649                                 case RTF.Minor.EmDash: {
1650                                 rtf_line.Append ("\u2014");
1651                                         break;
1652                                 }
1653
1654                                 case RTF.Minor.EnDash: {
1655                                         rtf_line.Append ("\u2013");
1656                                         break;
1657                                 }
1658 /*
1659                                 case RTF.Minor.LQuote: {
1660                                         Console.Write("\u2018");
1661                                         break;
1662                                 }
1663
1664                                 case RTF.Minor.RQuote: {
1665                                         Console.Write("\u2019");
1666                                         break;
1667                                 }
1668
1669                                 case RTF.Minor.LDblQuote: {
1670                                         Console.Write("\u201C");
1671                                         break;
1672                                 }
1673
1674                                 case RTF.Minor.RDblQuote: {
1675                                         Console.Write("\u201D");
1676                                         break;
1677                                 }
1678 */
1679                                 default: {
1680 //                                      Console.WriteLine ("skipped special char:   {0}", rtf.Minor);
1681 //                                      rtf.SkipGroup();
1682                                         break;
1683                                 }
1684                         }
1685                 }
1686
1687                 private void HandleText(RTF.RTF rtf) {
1688                         string str = rtf.EncodedText;
1689
1690                         //todo - simplistically skips characters, should skip bytes?
1691                         if (rtf_skip_count > 0 && str.Length > 0) {
1692                                 int iToRemove = Math.Min (rtf_skip_count, str.Length);
1693
1694                                 str = str.Substring (iToRemove);
1695                                 rtf_skip_count-=iToRemove;
1696                         }
1697
1698                         /*
1699                         if ((RTF.StandardCharCode)rtf.Minor != RTF.StandardCharCode.nothing) {
1700                                 rtf_line.Append(rtf_text_map[(RTF.StandardCharCode)rtf.Minor]);
1701                         } else {
1702                                 if ((int)rtf.Major > 31 && (int)rtf.Major < 128) {
1703                                         rtf_line.Append((char)rtf.Major);
1704                                 } else {
1705                                         //rtf_line.Append((char)rtf.Major);
1706                                         Console.Write("[Literal:0x{0:X2}]", (int)rtf.Major);
1707                                 }
1708                         }
1709                         */
1710
1711                         if  (rtf_style.rtf_visible)
1712                                 rtf_line.Append (str);
1713                 }
1714
1715                 private void FlushText(RTF.RTF rtf, bool newline) {
1716                         int             length;
1717                         Font            font;
1718
1719                         length = rtf_line.Length;
1720                         if (!newline && (length == 0)) {
1721                                 return;
1722                         }
1723
1724                         if (rtf_style.rtf_rtffont == null) {
1725                                 // First font in table is default
1726                                 rtf_style.rtf_rtffont = System.Windows.Forms.RTF.Font.GetFont (rtf, 0);
1727                         }
1728
1729                         font = new Font (rtf_style.rtf_rtffont.Name, rtf_style.rtf_rtffont_size, rtf_style.rtf_rtfstyle);
1730
1731                         if (rtf_style.rtf_color == Color.Empty) {
1732                                 System.Windows.Forms.RTF.Color color;
1733
1734                                 // First color in table is default
1735                                 color = System.Windows.Forms.RTF.Color.GetColor (rtf, 0);
1736
1737                                 if ((color == null) || (color.Red == -1 && color.Green == -1 && color.Blue == -1)) {
1738                                         rtf_style.rtf_color = ForeColor;
1739                                 } else {
1740                                         rtf_style.rtf_color = Color.FromArgb (color.Red, color.Green, color.Blue);
1741                                 }
1742
1743                         }
1744
1745                         rtf_chars += rtf_line.Length;
1746
1747
1748
1749                         if (rtf_cursor_x == 0) {
1750                                 if (newline && rtf_line.ToString ().EndsWith (Environment.NewLine) == false)
1751                                         rtf_line.Append (Environment.NewLine);
1752
1753                                 document.Add (rtf_cursor_y, rtf_line.ToString (), rtf_style.rtf_rtfalign, font, rtf_style.rtf_color,
1754                                                                 newline ? LineEnding.Rich : LineEnding.Wrap);
1755                                 if (rtf_style.rtf_par_line_left_indent != 0) {
1756                                         Line line = document.GetLine (rtf_cursor_y);
1757                                         line.indent = rtf_style.rtf_par_line_left_indent;
1758                                 }
1759                         } else {
1760                                 Line line;
1761
1762                                 line = document.GetLine (rtf_cursor_y);
1763                                 line.indent = rtf_style.rtf_par_line_left_indent;
1764                                 if (rtf_line.Length > 0) {
1765                                         document.InsertString (line, rtf_cursor_x, rtf_line.ToString ());
1766                                         document.FormatText (line, rtf_cursor_x + 1, line, rtf_cursor_x + 1 + length,
1767                             font, rtf_style.rtf_color, Color.Empty,
1768                                                         FormatSpecified.Font | FormatSpecified.Color);
1769                                 }
1770                                 if (newline) {
1771                                         line = document.GetLine (rtf_cursor_y);
1772                                         line.ending = LineEnding.Rich;
1773
1774                                         if (line.Text.EndsWith (Environment.NewLine) == false)
1775                                                 line.Text += Environment.NewLine;
1776                                 }
1777                         }
1778
1779                         if (newline) {
1780                                 rtf_cursor_x = 0;
1781                                 rtf_cursor_y++;
1782                         } else {
1783                                 rtf_cursor_x += length;
1784                         }
1785                         rtf_line.Length = 0;    // Empty line
1786                 }
1787
1788                 private void InsertRTFFromStream(Stream data, int cursor_x, int cursor_y) {
1789                         int     x;
1790                         int     y;
1791                         int     chars;
1792
1793                         InsertRTFFromStream(data, cursor_x, cursor_y, out x, out y, out chars);
1794                 }
1795
1796                 private void InsertRTFFromStream(Stream data, int cursor_x, int cursor_y, out int to_x, out int to_y, out int chars) {
1797                         RTF.RTF         rtf;
1798
1799                         rtf = new RTF.RTF(data);
1800
1801                         // Prepare
1802                         rtf.ClassCallback[RTF.TokenClass.Text] = new RTF.ClassDelegate(HandleText);
1803                         rtf.ClassCallback[RTF.TokenClass.Control] = new RTF.ClassDelegate(HandleControl);
1804                         rtf.ClassCallback[RTF.TokenClass.Group] = new RTF.ClassDelegate(HandleGroup);
1805
1806                         rtf_skip_count = 0;
1807                         rtf_line = new StringBuilder();
1808                         rtf_style.rtf_color = Color.Empty;
1809                         rtf_style.rtf_rtffont_size = (int)this.Font.Size;
1810                         rtf_style.rtf_rtfalign = HorizontalAlignment.Left;
1811                         rtf_style.rtf_rtfstyle = FontStyle.Regular;
1812                         rtf_style.rtf_rtffont = null;
1813                         rtf_style.rtf_visible = true;
1814                         rtf_style.rtf_skip_width = 1;
1815                         rtf_cursor_x = cursor_x;
1816                         rtf_cursor_y = cursor_y;
1817                         rtf_chars = 0;
1818                         rtf.DefaultFont(this.Font.Name);
1819
1820                         rtf_text_map = new RTF.TextMap();
1821                         RTF.TextMap.SetupStandardTable(rtf_text_map.Table);
1822
1823                         document.SuspendRecalc ();
1824
1825                         try {
1826                                 rtf.Read();     // That's it
1827                                 FlushText(rtf, false);
1828
1829                         }
1830
1831
1832                         catch (RTF.RTFException e) {
1833 #if DEBUG
1834                                 throw e;
1835 #endif
1836                                 // Seems to be plain text or broken RTF
1837                                 Console.WriteLine("RTF Parsing failure: {0}", e.Message);
1838                         }                     
1839
1840                         to_x = rtf_cursor_x;
1841                         to_y = rtf_cursor_y;
1842                         chars = rtf_chars;
1843
1844                         // clear the section stack if it was used
1845                         if (rtf_section_stack != null)
1846                                 rtf_section_stack.Clear();
1847
1848                         document.RecalculateDocument(CreateGraphicsInternal(), cursor_y, document.Lines, false);
1849                         document.ResumeRecalc (true);
1850
1851                         document.Invalidate (document.GetLine(cursor_y), 0, document.GetLine(document.Lines), -1);
1852                 }
1853
1854                 private void RichTextBox_HScrolled(object sender, EventArgs e) {
1855                         OnHScroll(e);
1856                 }
1857
1858                 private void RichTextBox_VScrolled(object sender, EventArgs e) {
1859                         OnVScroll(e);
1860                 }
1861
1862                 private void PointToTagPos(Point pt, out LineTag tag, out int pos) {
1863                         Point p;
1864
1865                         p = pt;
1866
1867                         if (p.X >= document.ViewPortWidth) {
1868                                 p.X = document.ViewPortWidth - 1;
1869                         } else if (p.X < 0) {
1870                                 p.X = 0;
1871                         }
1872
1873                         if (p.Y >= document.ViewPortHeight) {
1874                                 p.Y = document.ViewPortHeight - 1;
1875                         } else if (p.Y < 0) {
1876                                 p.Y = 0;
1877                         }
1878
1879                         tag = document.FindCursor(p.X + document.ViewPortX, p.Y + document.ViewPortY, out pos);
1880                 }
1881
1882                 private void EmitRTFFontProperties(StringBuilder rtf, int prev_index, int font_index, Font prev_font, Font font) {
1883                         if (prev_index != font_index) {
1884                                 rtf.Append(String.Format("\\f{0}", font_index));        // Font table entry
1885                         }
1886
1887                         if ((prev_font == null) || (prev_font.Size != font.Size)) {
1888                                 rtf.Append(String.Format("\\fs{0}", (int)(font.Size * 2)));             // Font size
1889                         }
1890
1891                         if ((prev_font == null) || (font.Bold != prev_font.Bold)) {
1892                                 if (font.Bold) {
1893                                         rtf.Append("\\b");
1894                                 } else {
1895                                         if (prev_font != null) {
1896                                                 rtf.Append("\\b0");
1897                                         }
1898                                 }
1899                         }
1900
1901                         if ((prev_font == null) || (font.Italic != prev_font.Italic)) {
1902                                 if (font.Italic) {
1903                                         rtf.Append("\\i");
1904                                 } else {
1905                                         if (prev_font != null) {
1906                                                 rtf.Append("\\i0");
1907                                         }
1908                                 }
1909                         }
1910
1911                         if ((prev_font == null) || (font.Strikeout != prev_font.Strikeout)) {
1912                                 if (font.Strikeout) {
1913                                         rtf.Append("\\strike");
1914                                 } else {
1915                                         if (prev_font != null) {
1916                                                 rtf.Append("\\strike0");
1917                                         }
1918                                 }
1919                         }
1920
1921                         if ((prev_font == null) || (font.Underline != prev_font.Underline)) {
1922                                 if (font.Underline) {
1923                                         rtf.Append("\\ul");
1924                                 } else {
1925                                         if (prev_font != null) {
1926                                                 rtf.Append("\\ul0");
1927                                         }
1928                                 }
1929                         }
1930                 }
1931
1932                 [MonoInternalNote ("Emit unicode and other special characters properly")]
1933                 private void EmitRTFText(StringBuilder rtf, string text) {
1934                         rtf.Append(text);
1935                 }
1936
1937                 // start_pos and end_pos are 0-based
1938                 private StringBuilder GenerateRTF(Line start_line, int start_pos, Line end_line, int end_pos) {
1939                         StringBuilder   sb;
1940                         ArrayList       fonts;
1941                         ArrayList       colors;
1942                         Color           color;
1943                         Font            font;
1944                         Line            line;
1945                         LineTag         tag;
1946                         int             pos;
1947                         int             line_no;
1948                         int             line_len;
1949                         int             i;
1950                         int             length;
1951
1952                         sb = new StringBuilder();
1953                         fonts = new ArrayList(10);
1954                         colors = new ArrayList(10);
1955
1956                         // Two runs, first we parse to determine tables;
1957                         // and unlike most of our processing here we work on tags
1958
1959                         line = start_line;
1960                         line_no = start_line.line_no;
1961                         pos = start_pos;
1962
1963                         // Add default font and color; to optimize document content we don't
1964                         // use this.Font and this.ForeColor but the font/color from the first tag
1965                         tag = LineTag.FindTag(start_line, pos);
1966                         font = tag.Font;
1967                         color = tag.Color;
1968                         fonts.Add(font.Name);
1969                         colors.Add(color);
1970
1971                         while (line_no <= end_line.line_no) {
1972                                 line = document.GetLine(line_no);
1973                                 tag = LineTag.FindTag(line, pos);
1974
1975                                 if (line_no != end_line.line_no) {
1976                                         line_len = line.text.Length;
1977                                 } else {
1978                                         line_len = end_pos;
1979                                 }
1980
1981                                 while (pos < line_len) {
1982                                         if (tag.Font.Name != font.Name) {
1983                                                 font = tag.Font;
1984                                                 if (!fonts.Contains(font.Name)) {
1985                                                         fonts.Add(font.Name);
1986                                                 }
1987                                         }
1988
1989                                         if (tag.Color != color) {
1990                                                 color = tag.Color;
1991                                                 if (!colors.Contains(color)) {
1992                                                         colors.Add(color);
1993                                                 }
1994                                         }
1995
1996                                         pos = tag.Start + tag.Length - 1;
1997                                         tag = tag.Next;
1998                                 }
1999                                 pos = 0;
2000                                 line_no++;
2001                         }
2002
2003                         // We have the tables, emit the header
2004                         sb.Append("{\\rtf1\\ansi");
2005                         sb.Append("\\ansicpg1252");     // FIXME - is this correct?
2006
2007                         // Default Font
2008                         sb.Append(String.Format("\\deff{0}", fonts.IndexOf(this.Font.Name)));
2009
2010                         // Default Language 
2011                         sb.Append("\\deflang1033" + Environment.NewLine);       // FIXME - always 1033?
2012
2013                         // Emit the font table
2014                         sb.Append("{\\fonttbl");
2015                         for (i = 0; i < fonts.Count; i++) {
2016                                 sb.Append(String.Format("{{\\f{0}", i));        // {Font 
2017                                 sb.Append("\\fnil");                    // Family
2018                                 sb.Append("\\fcharset0 ");              // Charset ANSI<space>
2019                                 sb.Append((string)fonts[i]);            // Font name
2020                                 sb.Append(";}");                        // }
2021                         }
2022                         sb.Append("}");
2023                         sb.Append(Environment.NewLine);
2024
2025                         // Emit the color table (if needed)
2026                         if ((colors.Count > 1) || ((((Color)colors[0]).R != this.ForeColor.R) || (((Color)colors[0]).G != this.ForeColor.G) || (((Color)colors[0]).B != this.ForeColor.B))) {
2027                                 sb.Append("{\\colortbl ");                      // Header and NO! default color
2028                                 for (i = 0; i < colors.Count; i++) {
2029                                         sb.Append(String.Format("\\red{0}", ((Color)colors[i]).R));
2030                                         sb.Append(String.Format("\\green{0}", ((Color)colors[i]).G));
2031                                         sb.Append(String.Format("\\blue{0}", ((Color)colors[i]).B));
2032                                         sb.Append(";");
2033                                 }
2034                                 sb.Append("}");
2035                                 sb.Append(Environment.NewLine);
2036                         }
2037
2038                         sb.Append("{\\*\\generator Mono RichTextBox;}");
2039                         // Emit initial paragraph settings
2040                         tag = LineTag.FindTag(start_line, start_pos);
2041                         sb.Append("\\pard");    // Reset to default paragraph properties
2042                         EmitRTFFontProperties(sb, -1, fonts.IndexOf(tag.Font.Name), null, tag.Font);    // Font properties
2043                         sb.Append(" ");         // Space separator
2044
2045                         font = tag.Font;
2046                         color = (Color)colors[0];
2047                         line = start_line;
2048                         line_no = start_line.line_no;
2049                         pos = start_pos;
2050
2051                         while (line_no <= end_line.line_no) {
2052                                 line = document.GetLine(line_no);
2053                                 tag = LineTag.FindTag(line, pos);
2054
2055                                 if (line_no != end_line.line_no) {
2056                                         line_len = line.text.Length;
2057                                 } else {
2058                                         line_len = end_pos;
2059                                 }
2060
2061                                 while (pos < line_len) {
2062                                         length = sb.Length;
2063
2064                                         if (tag.Font != font) {
2065                                                 EmitRTFFontProperties(sb, fonts.IndexOf(font.Name), fonts.IndexOf(tag.Font.Name), font, tag.Font);
2066                                                 font = tag.Font;
2067                                         }
2068
2069                                         if (tag.Color != color) {
2070                                                 color = tag.Color;
2071                                                 sb.Append(String.Format("\\cf{0}", colors.IndexOf(color)));
2072                                         }
2073                                         if (length != sb.Length) {
2074                                                 sb.Append(" "); // Emit space to separate keywords from text
2075                                         }
2076
2077                                         // Emit the string itself
2078                                         if (line_no != end_line.line_no) {
2079                                                 EmitRTFText(sb, tag.Line.text.ToString(pos, tag.Start + tag.Length - pos - 1));
2080                                         } else {
2081                                                 if (end_pos < (tag.Start + tag.Length - 1)) {
2082                                                         // Emit partial tag only, end_pos is inside this tag
2083                                                         EmitRTFText(sb, tag.Line.text.ToString(pos, end_pos - pos));
2084                                                 } else {
2085                                                         EmitRTFText(sb, tag.Line.text.ToString(pos, tag.Start + tag.Length - pos - 1));
2086                                                 }
2087                                         }
2088
2089                                         pos = tag.Start + tag.Length - 1;
2090                                         tag = tag.Next;
2091                                 }
2092                                 if (pos >= line.text.Length) {
2093                                         if (line.ending != LineEnding.Wrap) {
2094                                                 sb.Append("\\par");
2095                                                 sb.Append(Environment.NewLine);
2096                                         }
2097                                 }
2098                                 pos = 0;
2099                                 line_no++;
2100                         }
2101
2102                         sb.Append("}");
2103                         sb.Append(Environment.NewLine);
2104
2105                         return sb;
2106                 }
2107                 #endregion      // Private Methods
2108         }
2109 }