2005-09-08 Peter Dennis Bartok <pbartok@novell.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 Novell, Inc. (http://www.novell.com)
21 //
22 // Authors:
23 //      Peter Bartok    <pbartok@novell.com>
24 //
25 //
26
27 // NOT COMPLETE
28
29 using System;
30 using System.ComponentModel;
31 using System.Drawing;
32 using System.IO;
33 using System.Text;
34 using RTF=System.Windows.Forms.RTF;
35
36 namespace System.Windows.Forms {
37         public class RichTextBox : TextBoxBase {
38                 #region Local Variables
39                 internal bool           auto_word_select;
40                 internal int            bullet_indent;
41                 internal bool           can_redo;
42                 internal bool           detect_urls;
43                 internal string         redo_action_name;
44                 internal int            margin_right;
45                 internal string         undo_action_name;
46                 internal float          zoom;
47
48                 private RTF.TextMap     rtf_text_map;
49                 private int             rtf_skip_width;
50                 private int             rtf_skip_count;
51                 private StringBuilder   rtf_line;
52                 private Font            rtf_font;
53                 private SolidBrush      rtf_color;
54                 private RTF.Font        rtf_rtffont;
55                 private int             rtf_rtffont_size;
56                 private FontStyle       rtf_rtfstyle;
57                 private HorizontalAlignment rtf_rtfalign;
58                 private int             rtf_cursor_x;
59                 private int             rtf_cursor_y;
60                 #endregion      // Local Variables
61
62                 #region Public Constructors
63                 public RichTextBox() {
64                         accepts_return = true;
65                         auto_word_select = false;
66                         bullet_indent = 0;
67                         can_redo = false;
68                         detect_urls = true;
69                         max_length = Int32.MaxValue;
70                         redo_action_name = string.Empty;
71                         margin_right = 0;
72                         undo_action_name = string.Empty;
73                         zoom = 1;
74                         base.Multiline = true;
75                         document.CRLFSize = 1;
76
77                         scrollbars = RichTextBoxScrollBars.Both;
78                         alignment = HorizontalAlignment.Left;
79                         this.LostFocus +=new EventHandler(RichTextBox_LostFocus);
80                         this.BackColor = ThemeEngine.Current.ColorWindow;
81                         this.ForeColor = ThemeEngine.Current.ColorWindowText;
82
83                         Console.WriteLine("A friendly request: Do not log a bug about debug messages being emitted when\n" +
84                                 "using RichTextBox. It's not yet finished, it will spew debug information, and\n" +
85                                 "it may not work the way you like it just yet. Some methods also are also not yet\n" + 
86                                 "implemented. And we're also aware that text gets bolder with every change.");
87                         Console.WriteLine("To quote Sean Gilkes: Patience is a virtue, waiting doesn't hurt you :-)");
88                 }
89                 #endregion      // Public Constructors
90
91                 #region Private & Internal Methods
92                 private void RichTextBox_LostFocus(object sender, EventArgs e) {\r
93                         has_focus = false;\r
94                         Invalidate();\r
95                 }\r
96                 #endregion      // Private & Internal Methods
97
98                 #region Public Instance Properties
99                 public override bool AllowDrop {\r
100                         get {\r
101                                 return base.AllowDrop;\r
102                         }\r
103 \r
104                         set {\r
105                                 base.AllowDrop = value;\r
106                         }\r
107                 }\r
108 \r
109                 [DefaultValue(false)]\r
110                 public override bool AutoSize {\r
111                         get {\r
112                                 return auto_size;\r
113                         }\r
114 \r
115                         set {\r
116                                 base.AutoSize = value;\r
117                         }\r
118                 }\r
119 \r
120                 [DefaultValue(false)]\r
121                 public bool AutoWordSelection {\r
122                         get {\r
123                                 return auto_word_select;\r
124                         }\r
125 \r
126                         set {\r
127                                 auto_word_select = true;\r
128                         }\r
129                 }\r
130 \r
131                 [Browsable(false)]
132                 [EditorBrowsable(EditorBrowsableState.Never)]
133                 public override System.Drawing.Image BackgroundImage {\r
134                         get {\r
135                                 return background_image;\r
136                         }\r
137 \r
138                         set {\r
139                                 base.BackgroundImage = value;\r
140                         }\r
141                 }\r
142 \r
143                 [DefaultValue(0)]\r
144                 [Localizable(true)]\r
145                 public int BulletIndent {
146                         get {
147                                 return bullet_indent;
148                         }
149
150                         set {
151                                 bullet_indent = value;
152                         }
153                 }
154
155                 [Browsable(false)]
156                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
157                 public bool CanRedo {
158                         get {
159                                 return can_redo;
160                         }
161                 }
162
163                 [DefaultValue(true)]
164                 public bool DetectUrls {
165                         get {
166                                 return detect_urls;
167                         }
168
169                         set {
170                                 detect_urls = true;
171                         }
172                 }
173
174                 public override Font Font {\r
175                         get {\r
176                                 return base.Font;\r
177                         }\r
178 \r
179                         set {\r
180                                 if (font != value) {\r
181                                         if (auto_size) {\r
182                                                 if (PreferredHeight != Height) {
183                                                         Height = PreferredHeight;
184                                                 }
185                                         }\r
186 \r
187                                         base.Font = value;\r
188                                 }\r
189                         }\r
190                 }\r
191
192                 public override Color ForeColor {\r
193                         get {\r
194                                 return base.ForeColor;\r
195                         }\r
196 \r
197                         set {\r
198                                 base.ForeColor = value;\r
199                         }\r
200                 }\r
201
202                 [DefaultValue(Int32.MaxValue)]
203                 public override int MaxLength {\r
204                         get {\r
205                                 return base.max_length;\r
206                         }\r
207 \r
208                         set {\r
209                                 base.max_length = value;\r
210                         }\r
211                 }\r
212
213                 [DefaultValue(true)]
214                 public override bool Multiline {\r
215                         get {\r
216                                 return multiline;\r
217                         }\r
218 \r
219                         set {\r
220                                 base.Multiline = value;\r
221                         }\r
222                 }\r
223
224                 [Browsable(false)]
225                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
226                 [MonoTODO]
227                 public string RedoActionName {
228                         get {
229                                 return redo_action_name;
230                         }
231                 }
232
233                 [DefaultValue(0)]
234                 [Localizable(true)]
235                 [MonoTODO("Teach TextControl.RecalculateLine to consider the right margin as well")]
236                 public int RightMargin {
237                         get {
238                                 return margin_right;
239                         }
240
241                         set {
242                                 margin_right = value;
243                         }
244                 }
245
246                 [Browsable(false)]
247                 [DefaultValue("")]
248                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
249                 [MonoTODO("finish and plug in the rtf parser/generator")]
250                 public string Rtf {
251                         get {
252                                 // FIXME
253                                 return null;
254                         }
255
256                         set {
257                                 // FIXME
258                         }
259                 }
260
261                 [DefaultValue(RichTextBoxScrollBars.Both)]
262                 [Localizable(true)]
263                 public RichTextBoxScrollBars ScrollBars {
264                         get {
265                                 return scrollbars;
266                         }
267
268                         set {
269                                 scrollbars = value;
270                         }
271                 }
272
273                 [MonoTODO("finish and plug in rtf parser/generator")]
274                 public string SelectedRtf {
275                         get {
276                                 // FIXME
277                                 return null;
278                         }
279
280                         set {
281                                 // FIXME
282                         }
283                 }
284
285                 public override string SelectedText {\r
286                         get {\r
287                                 return base.SelectedText;\r
288                         }\r
289 \r
290                         set {\r
291                                 base.SelectedText = value;\r
292                         }\r
293                 }\r
294
295                 [Browsable(false)]
296                 [DefaultValue(HorizontalAlignment.Left)]
297                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
298                 public HorizontalAlignment SelectionAlignment {
299                         get {
300                                 HorizontalAlignment     align;
301                                 int                     line_no;
302                                 Line                    start;
303                                 Line                    end;
304                                 Line                    line;
305
306                                 start = document.ParagraphStart(document.selection_start.line);
307                                 align = start.alignment;
308                                 line_no = start.line_no;
309
310                                 end = document.ParagraphEnd(document.selection_end.line);
311
312                                 line = start;
313
314                                 while (true) {
315                                         if (line.alignment != align) {
316                                                 return HorizontalAlignment.Left;
317                                         }
318
319                                         if (line == end) {
320                                                 break;
321                                         }
322                                         line = document.GetLine(line.line_no + 1);
323                                 }
324
325                                 return align;
326                         }
327
328                         set {
329                                 HorizontalAlignment     align;
330                                 int                     line_no;
331                                 Line                    start;
332                                 Line                    end;
333                                 Line                    line;
334
335                                 start = document.ParagraphStart(document.selection_start.line);
336                                 line_no = start.line_no;
337
338                                 end = document.ParagraphEnd(document.selection_end.line);
339
340                                 line = start;
341
342                                 while (true) {
343                                         line.alignment = value;
344
345                                         if (line == end) {
346                                                 break;
347                                         }
348                                         line = document.GetLine(line.line_no + 1);
349                                 }
350                                 this.CalculateDocument();
351                         }
352                 }
353
354
355                 public Font SelectionFont {
356                         get {
357                                 Font    font;
358                                 LineTag start;
359                                 LineTag end;
360                                 LineTag tag;
361
362                                 start = document.selection_start.tag;
363                                 end = document.selection_end.tag;
364                                 font = document.selection_start.tag.font;
365
366                                 tag = start;
367                                 while (true) {
368                                         if (!font.Equals(tag.font)) {
369                                                 return null;
370                                         }
371
372                                         if (tag == end) {
373                                                 break;
374                                         }
375
376                                         tag = document.NextTag(tag);
377
378                                         if (tag == null) {
379                                                 break;
380                                         }
381                                 }
382
383                                 return font;
384                         }
385
386                         set {
387                                 int     sel_start;
388                                 int     sel_end;
389
390                                 sel_start = document.LineTagToCharIndex(document.selection_start.line, document.selection_start.pos);
391                                 sel_end = document.LineTagToCharIndex(document.selection_end.line, document.selection_end.pos);
392
393                                 document.FormatText(document.selection_start.line, document.selection_start.pos + 1, document.selection_end.line, document.selection_end.pos, value, document.selection_start.tag.color);
394
395                                 document.CharIndexToLineTag(sel_start, out document.selection_start.line, out document.selection_start.tag, out document.selection_start.pos);
396                                 document.CharIndexToLineTag(sel_end, out document.selection_end.line, out document.selection_end.tag, out document.selection_end.pos);
397
398                                 document.UpdateView(document.selection_start.line, 0);
399                                 document.AlignCaret();
400                                 
401                         }
402                 }
403
404                 [Localizable(true)]
405                 public override string Text {\r
406                         get {\r
407                                 return base.Text;\r
408                         }\r
409 \r
410                         set {\r
411                                 base.Text = value;\r
412                         }\r
413                 }\r
414
415                 [Browsable(false)]
416                 public override int TextLength {\r
417                         get {\r
418                                 return base.TextLength;\r
419                         }\r
420                 }\r
421
422                 [Browsable(false)]
423                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
424                 public string UndoActionName {
425                         get {
426                                 return undo_action_name;
427                         }
428                 }
429
430                 [Localizable(true)]
431                 [DefaultValue(1)]
432                 public float ZoomFactor {
433                         get {
434                                 return zoom;
435                         }
436
437                         set {
438                                 zoom = value;
439                         }
440                 }
441                 #endregion      // Public Instance Properties
442
443                 #region Protected Instance Properties
444                 protected override CreateParams CreateParams {\r
445                         get {\r
446                                 return base.CreateParams;\r
447                         }\r
448                 }\r
449
450                 protected override Size DefaultSize {\r
451                         get {\r
452                                 return new Size(100, 96);\r
453                         }\r
454                 }\r
455                 #endregion      // Protected Instance Properties
456
457                 #region Public Instance Methods
458                 public void LoadFile(System.IO.Stream data, RichTextBoxStreamType fileType) {
459                         RTF.RTF rtf;    // Not 'using SWF.RTF' to avoid ambiguities with font and color
460
461                         document.Empty();
462
463                         // FIXME - ignoring unicode
464                         if (fileType == RichTextBoxStreamType.PlainText) {
465                                 StringBuilder   sb;\r
466                                 int             count;\r
467                                 byte[]          buffer;\r
468 \r
469                                 try {\r
470                                         sb = new StringBuilder((int)data.Length);\r
471                                         buffer = new byte[1024];\r
472                                 }\r
473 \r
474                                 catch {\r
475                                         throw new IOException("Not enough memory to load document");\r
476                                         return;\r
477                                 }\r
478 \r
479                                 count = 0;\r
480                                 while (count < data.Length) {\r
481                                         count += data.Read(buffer, count, 1024);\r
482                                         sb.Append(buffer);\r
483                                 }\r
484                                 base.Text = sb.ToString();\r
485                                 return;\r
486                         }\r
487
488
489                         rtf = new RTF.RTF(data);
490
491                         // Prepare
492                         rtf.ClassCallback[RTF.TokenClass.Text] = new RTF.ClassDelegate(HandleText);
493                         rtf.ClassCallback[RTF.TokenClass.Control] = new RTF.ClassDelegate(HandleControl);
494
495                         rtf_skip_width = 0;
496                         rtf_skip_count = 0;
497                         rtf_line = new StringBuilder();
498                         rtf_font = Font;
499                         rtf_color = new SolidBrush(ForeColor);
500                         rtf_rtffont_size = this.Font.Height;
501                         rtf_rtfalign = HorizontalAlignment.Left;
502                         rtf_rtffont = null;
503                         rtf_cursor_x = 0;
504                         rtf_cursor_y = 1;
505
506                         rtf_text_map = new RTF.TextMap();
507                         RTF.TextMap.SetupStandardTable(rtf_text_map.Table);
508
509                         rtf.Read();     // That's it
510                         document.RecalculateDocument(CreateGraphics());
511                 }
512
513                 public void LoadFile(string path) {
514                         if (path.EndsWith(".rtf")) {
515                                 LoadFile(path, RichTextBoxStreamType.RichText);
516                         } else {
517                                 LoadFile(path, RichTextBoxStreamType.PlainText);
518                         }
519                 }
520
521                 public void LoadFile(string path, RichTextBoxStreamType fileType) {
522                         FileStream      data;
523
524                         data = null;
525
526 //                      try {
527                                 data = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 1024);
528                                 LoadFile(data, fileType);
529 //                      }
530
531 //                      catch {
532 //                              throw new IOException("Could not open file " + path);
533 //                      }
534
535 //                      finally {
536                                 if (data != null) {
537                                         data.Close();
538 //                              }
539                         }
540                 }
541
542                 public void SaveFile(Stream data, RichTextBoxStreamType fileType) {
543                 }
544
545                 public void SaveFile(string path) {
546                         if (path.EndsWith(".rtf")) {
547                                 SaveFile(path, RichTextBoxStreamType.RichText);
548                         } else {
549                                 SaveFile(path, RichTextBoxStreamType.PlainText);
550                         }
551                 }
552
553                 public void SaveFile(string path, RichTextBoxStreamType fileType) {
554                         FileStream      data;
555                         Encoding        encoding;
556
557                         data = null;
558                         if (fileType == RichTextBoxStreamType.UnicodePlainText) {
559                                 encoding = Encoding.Unicode;
560                         } else {
561                                 encoding = Encoding.ASCII;
562                         }
563
564                         try {
565                                 data = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, 1024, false);
566                                 SaveFile(data, fileType);
567                         }
568
569                         catch {
570                                 throw new IOException("Could not write document to file " + path);
571                         }
572
573                         finally {
574                                 if (data != null) {
575                                         data.Close();
576                                 }
577                         }
578                 }
579
580                 #endregion      // Public Instance Methods
581
582                 #region Protected Instance Methods
583                 protected override void OnBackColorChanged(EventArgs e) {\r
584                         base.OnBackColorChanged (e);\r
585                 }\r
586 \r
587                 protected override void OnContextMenuChanged(EventArgs e) {\r
588                         base.OnContextMenuChanged (e);\r
589                 }\r
590 \r
591                 protected override void OnHandleCreated(EventArgs e) {\r
592                         base.OnHandleCreated (e);\r
593                 }\r
594 \r
595                 protected override void OnHandleDestroyed(EventArgs e) {\r
596                         base.OnHandleDestroyed (e);\r
597                 }\r
598 \r
599                 protected override void OnRightToLeftChanged(EventArgs e) {\r
600                         base.OnRightToLeftChanged (e);\r
601                 }\r
602 \r
603                 protected override void OnSystemColorsChanged(EventArgs e) {\r
604                         base.OnSystemColorsChanged (e);\r
605                 }\r
606 \r
607                 protected override void OnTextChanged(EventArgs e) {\r
608                         base.OnTextChanged (e);\r
609                 }\r
610 \r
611                 protected override void WndProc(ref Message m) {\r
612                         base.WndProc (ref m);\r
613                 }\r
614                 #endregion      // Protected Instance Methods
615
616                 #region Events
617                 [Browsable(false)]
618                 [EditorBrowsable(EditorBrowsableState.Never)]
619                 public event EventHandler                       BackgroundImageChanged;
620
621                 public event ContentsResizedEventHandler        ContentsResized;
622
623                 [Browsable(false)]
624                 [EditorBrowsable(EditorBrowsableState.Never)]
625                 public event EventHandler                       DoubleClick;
626
627                 [Browsable(false)]
628                 [EditorBrowsable(EditorBrowsableState.Never)]
629                 public event DragEventHandler                   DragDrop;
630
631                 [Browsable(false)]
632                 [EditorBrowsable(EditorBrowsableState.Never)]
633                 public event DragEventHandler                   DragEnter;
634
635                 [Browsable(false)]
636                 [EditorBrowsable(EditorBrowsableState.Never)]
637                 public event EventHandler                       DragLeave;
638
639                 [Browsable(false)]
640                 [EditorBrowsable(EditorBrowsableState.Never)]
641                 public event DragEventHandler                   DragOver;
642
643                 [Browsable(false)]
644                 [EditorBrowsable(EditorBrowsableState.Never)]
645                 public event GiveFeedbackEventHandler           GiveFeedback;
646
647                 public event EventHandler                       HScroll;
648                 public event EventHandler                       ImeChange;
649                 public event LinkClickedEventHandler            LinkClicked;
650                 public event EventHandler                       Protected;
651
652                 [Browsable(false)]
653                 [EditorBrowsable(EditorBrowsableState.Never)]
654                 public event QueryContinueDragEventHandler      QueryContinueDrag;
655                 public event EventHandler                       SelectionChanged;
656                 public event EventHandler                       VScroll;
657                 #endregion      // Events
658
659                 #region Private Methods
660                 void HandleControl(RTF.RTF rtf) {
661                         switch(rtf.Major) {
662                                 case RTF.Major.Unicode: {
663                                         switch(rtf.Minor) {
664                                                 case Minor.UnicodeCharBytes: {
665                                                         rtf_skip_width = rtf.Param;
666                                                         break;
667                                                 }
668
669                                                 case Minor.UnicodeChar: {
670                                                         rtf_skip_count += rtf_skip_width;
671                                                         rtf_line.Append((char)rtf.Param);
672                                                         break;
673                                                 }
674                                         }
675                                         break;
676                                 }
677
678                                 case RTF.Major.Destination: {
679                                         Console.Write("[Got Destination control {0}]", rtf.Minor);
680                                         rtf.SkipGroup();
681                                         break;
682                                 }
683
684                                 case RTF.Major.CharAttr: {
685                                         switch(rtf.Minor) {
686                                                 case Minor.ForeColor: {
687                                                         System.Windows.Forms.RTF.Color  color;
688                                                         int     num;
689
690                                                         color = System.Windows.Forms.RTF.Color.GetColor(rtf, rtf.Param);
691                                                         if (color != null) {
692                                                                 FlushText(false);
693                                                                 if (color.Red == -1 && color.Green == -1 && color.Blue == -1) {
694                                                                         this.rtf_color = new SolidBrush(ForeColor);
695                                                                 } else {
696                                                                         this.rtf_color = new SolidBrush(Color.FromArgb(color.Red, color.Green, color.Blue));
697                                                                 }
698                                                         }
699                                                         break;
700                                                 }
701
702                                                 case Minor.FontSize: {
703                                                         this.rtf_rtffont_size = rtf.Param / 2;
704                                                         break;
705                                                 }
706
707                                                 case Minor.FontNum: {
708                                                         System.Windows.Forms.RTF.Font   font;
709
710                                                         font = System.Windows.Forms.RTF.Font.GetFont(rtf, rtf.Param);
711                                                         if (font != null) {
712                                                                 FlushText(false);
713                                                                 this.rtf_rtffont = font;
714                                                         }
715                                                         break;
716                                                 }
717
718                                                 case Minor.Plain: {
719                                                         FlushText(false);
720                                                         rtf_rtfstyle = FontStyle.Regular;
721                                                         break;
722                                                 }
723
724                                                 case Minor.Bold: {
725                                                         FlushText(false);
726                                                         if (rtf.Param == RTF.RTF.NoParam) {
727                                                                 rtf_rtfstyle |= FontStyle.Bold;
728                                                         } else {
729                                                                 rtf_rtfstyle &= ~FontStyle.Bold;
730                                                         }
731                                                         break;
732                                                 }
733
734                                                 case Minor.Italic: {
735                                                         FlushText(false);
736                                                         if (rtf.Param == RTF.RTF.NoParam) {
737                                                                 rtf_rtfstyle |= FontStyle.Italic;
738                                                         } else {
739                                                                 rtf_rtfstyle &= ~FontStyle.Italic;
740                                                         }
741                                                         break;
742                                                 }
743
744                                                 case Minor.StrikeThru: {
745                                                         FlushText(false);
746                                                         if (rtf.Param == RTF.RTF.NoParam) {
747                                                                 rtf_rtfstyle |= FontStyle.Strikeout;
748                                                         } else {
749                                                                 rtf_rtfstyle &= ~FontStyle.Strikeout;
750                                                         }
751                                                         break;
752                                                 }
753
754                                                 case Minor.Underline: {
755                                                         FlushText(false);
756                                                         if (rtf.Param == RTF.RTF.NoParam) {
757                                                                 rtf_rtfstyle |= FontStyle.Underline;
758                                                         } else {
759                                                                 rtf_rtfstyle &= ~FontStyle.Underline;
760                                                         }
761                                                         break;
762                                                 }
763
764                                                 case Minor.NoUnderline: {
765                                                         FlushText(false);
766                                                         rtf_rtfstyle &= ~FontStyle.Underline;
767                                                         break;
768                                                 }
769                                         }
770                                         break;
771                                 }
772
773                                 case RTF.Major.SpecialChar: {
774                                         Console.Write("[Got SpecialChar control {0}]", rtf.Minor);
775                                         SpecialChar(rtf);
776                                         break;
777                                 }
778                         }
779                 }
780
781                 void SpecialChar(RTF.RTF rtf) {
782                         switch(rtf.Minor) {
783                                 case Minor.Page:
784                                 case Minor.Sect:
785                                 case Minor.Row:
786                                 case Minor.Line:
787                                 case Minor.Par: {
788                                         FlushText(true);
789                                         break;
790                                 }
791
792                                 case Minor.Cell: {
793                                         Console.Write(" ");
794                                         break;
795                                 }
796
797                                 case Minor.NoBrkSpace: {
798                                         Console.Write(" ");
799                                         break;
800                                 }
801
802                                 case Minor.Tab: {
803                                         Console.Write("\t");
804                                         break;
805                                 }
806
807                                 case Minor.NoBrkHyphen: {
808                                         Console.Write("-");
809                                         break;
810                                 }
811
812                                 case Minor.Bullet: {
813                                         Console.Write("*");
814                                         break;
815                                 }
816
817                                 case Minor.EmDash: {
818                                         Console.Write("\97");
819                                         break;
820                                 }
821
822                                 case Minor.EnDash: {
823                                         Console.Write("\96");
824                                         break;
825                                 }
826
827                                 case Minor.LQuote: {
828                                         Console.Write("\91");
829                                         break;
830                                 }
831
832                                 case Minor.RQuote: {
833                                         Console.Write("\92");
834                                         break;
835                                 }
836
837                                 case Minor.LDblQuote: {
838                                         Console.Write("\93");
839                                         break;
840                                 }
841
842                                 case Minor.RDblQuote: {
843                                         Console.Write("\94");
844                                         break;
845                                 }
846
847                                 default: {
848                                         rtf.SkipGroup();
849                                         break;
850                                 }
851                         }
852                 }
853
854
855                 void HandleText(RTF.RTF rtf) {
856                         if (rtf_skip_count > 0) {
857                                 rtf_skip_count--;
858                                 return;
859                         }
860
861                         if ((RTF.StandardCharCode)rtf.Minor != RTF.StandardCharCode.nothing) {
862                                 rtf_line.Append(rtf_text_map[(RTF.StandardCharCode)rtf.Minor]);
863                         } else {
864                                 if ((int)rtf.Major > 31 && (int)rtf.Major < 128) {
865                                         rtf_line.Append((char)rtf.Major);
866                                 } else {
867                                         //rtf_line.Append((char)rtf.Major);
868                                         Console.Write("[Literal:0x{0:X2}]", (int)rtf.Major);
869                                 }
870                         }
871                 }
872
873                 void FlushText(bool newline) {
874                         int             length;
875                         Font            font;
876
877                         length = rtf_line.Length;
878                         if (length == 0) {
879                                 return;
880                         }
881
882                         if (rtf_rtffont != null) {
883                                 font = new Font(rtf_rtffont.Name, rtf_rtffont_size, rtf_rtfstyle);
884                         } else {
885                                 font = this.Font;
886                         }
887
888                         if (rtf_cursor_x == 0) {
889                                 document.Add(rtf_cursor_y, rtf_line.ToString(), rtf_rtfalign, font, rtf_color);
890                         } else {
891                                 Line    line;
892
893                                 line = document.GetLine(rtf_cursor_y);
894                                 document.InsertString(line, rtf_cursor_x, rtf_line.ToString());
895                                 document.FormatText(line, rtf_cursor_x, line, rtf_cursor_x + length, font, rtf_color);
896                         }
897
898                         if (newline) {
899                                 rtf_cursor_x = 0;
900                                 rtf_cursor_y++;
901                         } else {
902                                 rtf_cursor_x += length;
903                         }
904                         rtf_line.Length = 0;    // Empty line
905                 }
906                 #endregion      // Private Methods
907         }
908 }