1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
23 // Peter Bartok <pbartok@novell.com>
30 using System.ComponentModel;
34 using RTF=System.Windows.Forms.RTF;
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;
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
62 #region Public Constructors
63 public RichTextBox() {
64 accepts_return = true;
65 auto_word_select = false;
69 max_length = Int32.MaxValue;
70 redo_action_name = string.Empty;
72 undo_action_name = string.Empty;
74 base.Multiline = true;
75 document.CRLFSize = 1;
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;
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 :-)");
89 #endregion // Public Constructors
91 #region Private & Internal Methods
92 private void RichTextBox_LostFocus(object sender, EventArgs e) {
\r
96 #endregion // Private & Internal Methods
98 #region Public Instance Properties
99 public override bool AllowDrop {
\r
101 return base.AllowDrop;
\r
105 base.AllowDrop = value;
\r
109 [DefaultValue(false)]
\r
110 public override bool AutoSize {
\r
116 base.AutoSize = value;
\r
120 [DefaultValue(false)]
\r
121 public bool AutoWordSelection {
\r
123 return auto_word_select;
\r
127 auto_word_select = true;
\r
132 [EditorBrowsable(EditorBrowsableState.Never)]
133 public override System.Drawing.Image BackgroundImage {
\r
135 return background_image;
\r
139 base.BackgroundImage = value;
\r
144 [Localizable(true)]
\r
145 public int BulletIndent {
147 return bullet_indent;
151 bullet_indent = value;
156 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
157 public bool CanRedo {
164 public bool DetectUrls {
174 public override Font Font {
\r
180 if (font != value) {
\r
182 if (PreferredHeight != Height) {
183 Height = PreferredHeight;
192 public override Color ForeColor {
\r
194 return base.ForeColor;
\r
198 base.ForeColor = value;
\r
202 [DefaultValue(Int32.MaxValue)]
203 public override int MaxLength {
\r
205 return base.max_length;
\r
209 base.max_length = value;
\r
214 public override bool Multiline {
\r
220 base.Multiline = value;
\r
225 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
227 public string RedoActionName {
229 return redo_action_name;
235 [MonoTODO("Teach TextControl.RecalculateLine to consider the right margin as well")]
236 public int RightMargin {
242 margin_right = value;
248 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
249 [MonoTODO("finish and plug in the rtf parser/generator")]
261 [DefaultValue(RichTextBoxScrollBars.Both)]
263 public RichTextBoxScrollBars ScrollBars {
273 [MonoTODO("finish and plug in rtf parser/generator")]
274 public string SelectedRtf {
285 public override string SelectedText {
\r
287 return base.SelectedText;
\r
291 base.SelectedText = value;
\r
296 [DefaultValue(HorizontalAlignment.Left)]
297 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
298 public HorizontalAlignment SelectionAlignment {
300 HorizontalAlignment align;
306 start = document.ParagraphStart(document.selection_start.line);
307 align = start.alignment;
308 line_no = start.line_no;
310 end = document.ParagraphEnd(document.selection_end.line);
315 if (line.alignment != align) {
316 return HorizontalAlignment.Left;
322 line = document.GetLine(line.line_no + 1);
329 HorizontalAlignment align;
335 start = document.ParagraphStart(document.selection_start.line);
336 line_no = start.line_no;
338 end = document.ParagraphEnd(document.selection_end.line);
343 line.alignment = value;
348 line = document.GetLine(line.line_no + 1);
350 this.CalculateDocument();
355 public Font SelectionFont {
362 start = document.selection_start.tag;
363 end = document.selection_end.tag;
364 font = document.selection_start.tag.font;
368 if (!font.Equals(tag.font)) {
376 tag = document.NextTag(tag);
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);
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);
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);
398 document.UpdateView(document.selection_start.line, 0);
399 document.AlignCaret();
405 public override string Text {
\r
416 public override int TextLength {
\r
418 return base.TextLength;
\r
423 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
424 public string UndoActionName {
426 return undo_action_name;
432 public float ZoomFactor {
441 #endregion // Public Instance Properties
443 #region Protected Instance Properties
444 protected override CreateParams CreateParams {
\r
446 return base.CreateParams;
\r
450 protected override Size DefaultSize {
\r
452 return new Size(100, 96);
\r
455 #endregion // Protected Instance Properties
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
463 // FIXME - ignoring unicode
464 if (fileType == RichTextBoxStreamType.PlainText) {
470 sb = new StringBuilder((int)data.Length);
\r
471 buffer = new byte[1024];
\r
475 throw new IOException("Not enough memory to load document");
\r
480 while (count < data.Length) {
\r
481 count += data.Read(buffer, count, 1024);
\r
484 base.Text = sb.ToString();
\r
489 rtf = new RTF.RTF(data);
492 rtf.ClassCallback[RTF.TokenClass.Text] = new RTF.ClassDelegate(HandleText);
493 rtf.ClassCallback[RTF.TokenClass.Control] = new RTF.ClassDelegate(HandleControl);
497 rtf_line = new StringBuilder();
499 rtf_color = new SolidBrush(ForeColor);
500 rtf_rtffont_size = this.Font.Height;
501 rtf_rtfalign = HorizontalAlignment.Left;
506 rtf_text_map = new RTF.TextMap();
507 RTF.TextMap.SetupStandardTable(rtf_text_map.Table);
509 rtf.Read(); // That's it
510 document.RecalculateDocument(CreateGraphics());
513 public void LoadFile(string path) {
514 if (path.EndsWith(".rtf")) {
515 LoadFile(path, RichTextBoxStreamType.RichText);
517 LoadFile(path, RichTextBoxStreamType.PlainText);
521 public void LoadFile(string path, RichTextBoxStreamType fileType) {
527 data = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 1024);
528 LoadFile(data, fileType);
532 // throw new IOException("Could not open file " + path);
542 public void SaveFile(Stream data, RichTextBoxStreamType fileType) {
545 public void SaveFile(string path) {
546 if (path.EndsWith(".rtf")) {
547 SaveFile(path, RichTextBoxStreamType.RichText);
549 SaveFile(path, RichTextBoxStreamType.PlainText);
553 public void SaveFile(string path, RichTextBoxStreamType fileType) {
558 if (fileType == RichTextBoxStreamType.UnicodePlainText) {
559 encoding = Encoding.Unicode;
561 encoding = Encoding.ASCII;
565 data = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, 1024, false);
566 SaveFile(data, fileType);
570 throw new IOException("Could not write document to file " + path);
580 #endregion // Public Instance Methods
582 #region Protected Instance Methods
583 protected override void OnBackColorChanged(EventArgs e) {
\r
584 base.OnBackColorChanged (e);
\r
587 protected override void OnContextMenuChanged(EventArgs e) {
\r
588 base.OnContextMenuChanged (e);
\r
591 protected override void OnHandleCreated(EventArgs e) {
\r
592 base.OnHandleCreated (e);
\r
595 protected override void OnHandleDestroyed(EventArgs e) {
\r
596 base.OnHandleDestroyed (e);
\r
599 protected override void OnRightToLeftChanged(EventArgs e) {
\r
600 base.OnRightToLeftChanged (e);
\r
603 protected override void OnSystemColorsChanged(EventArgs e) {
\r
604 base.OnSystemColorsChanged (e);
\r
607 protected override void OnTextChanged(EventArgs e) {
\r
608 base.OnTextChanged (e);
\r
611 protected override void WndProc(ref Message m) {
\r
612 base.WndProc (ref m);
\r
614 #endregion // Protected Instance Methods
618 [EditorBrowsable(EditorBrowsableState.Never)]
619 public event EventHandler BackgroundImageChanged;
621 public event ContentsResizedEventHandler ContentsResized;
624 [EditorBrowsable(EditorBrowsableState.Never)]
625 public event EventHandler DoubleClick;
628 [EditorBrowsable(EditorBrowsableState.Never)]
629 public event DragEventHandler DragDrop;
632 [EditorBrowsable(EditorBrowsableState.Never)]
633 public event DragEventHandler DragEnter;
636 [EditorBrowsable(EditorBrowsableState.Never)]
637 public event EventHandler DragLeave;
640 [EditorBrowsable(EditorBrowsableState.Never)]
641 public event DragEventHandler DragOver;
644 [EditorBrowsable(EditorBrowsableState.Never)]
645 public event GiveFeedbackEventHandler GiveFeedback;
647 public event EventHandler HScroll;
648 public event EventHandler ImeChange;
649 public event LinkClickedEventHandler LinkClicked;
650 public event EventHandler Protected;
653 [EditorBrowsable(EditorBrowsableState.Never)]
654 public event QueryContinueDragEventHandler QueryContinueDrag;
655 public event EventHandler SelectionChanged;
656 public event EventHandler VScroll;
659 #region Private Methods
660 void HandleControl(RTF.RTF rtf) {
662 case RTF.Major.Unicode: {
664 case Minor.UnicodeCharBytes: {
665 rtf_skip_width = rtf.Param;
669 case Minor.UnicodeChar: {
670 rtf_skip_count += rtf_skip_width;
671 rtf_line.Append((char)rtf.Param);
678 case RTF.Major.Destination: {
679 Console.Write("[Got Destination control {0}]", rtf.Minor);
684 case RTF.Major.CharAttr: {
686 case Minor.ForeColor: {
687 System.Windows.Forms.RTF.Color color;
690 color = System.Windows.Forms.RTF.Color.GetColor(rtf, rtf.Param);
693 if (color.Red == -1 && color.Green == -1 && color.Blue == -1) {
694 this.rtf_color = new SolidBrush(ForeColor);
696 this.rtf_color = new SolidBrush(Color.FromArgb(color.Red, color.Green, color.Blue));
702 case Minor.FontSize: {
703 this.rtf_rtffont_size = rtf.Param / 2;
707 case Minor.FontNum: {
708 System.Windows.Forms.RTF.Font font;
710 font = System.Windows.Forms.RTF.Font.GetFont(rtf, rtf.Param);
713 this.rtf_rtffont = font;
720 rtf_rtfstyle = FontStyle.Regular;
726 if (rtf.Param == RTF.RTF.NoParam) {
727 rtf_rtfstyle |= FontStyle.Bold;
729 rtf_rtfstyle &= ~FontStyle.Bold;
736 if (rtf.Param == RTF.RTF.NoParam) {
737 rtf_rtfstyle |= FontStyle.Italic;
739 rtf_rtfstyle &= ~FontStyle.Italic;
744 case Minor.StrikeThru: {
746 if (rtf.Param == RTF.RTF.NoParam) {
747 rtf_rtfstyle |= FontStyle.Strikeout;
749 rtf_rtfstyle &= ~FontStyle.Strikeout;
754 case Minor.Underline: {
756 if (rtf.Param == RTF.RTF.NoParam) {
757 rtf_rtfstyle |= FontStyle.Underline;
759 rtf_rtfstyle &= ~FontStyle.Underline;
764 case Minor.NoUnderline: {
766 rtf_rtfstyle &= ~FontStyle.Underline;
773 case RTF.Major.SpecialChar: {
774 Console.Write("[Got SpecialChar control {0}]", rtf.Minor);
781 void SpecialChar(RTF.RTF rtf) {
797 case Minor.NoBrkSpace: {
807 case Minor.NoBrkHyphen: {
818 Console.Write("
\97");
823 Console.Write("
\96");
828 Console.Write("
\91");
833 Console.Write("
\92");
837 case Minor.LDblQuote: {
838 Console.Write("
\93");
842 case Minor.RDblQuote: {
843 Console.Write("
\94");
855 void HandleText(RTF.RTF rtf) {
856 if (rtf_skip_count > 0) {
861 if ((RTF.StandardCharCode)rtf.Minor != RTF.StandardCharCode.nothing) {
862 rtf_line.Append(rtf_text_map[(RTF.StandardCharCode)rtf.Minor]);
864 if ((int)rtf.Major > 31 && (int)rtf.Major < 128) {
865 rtf_line.Append((char)rtf.Major);
867 //rtf_line.Append((char)rtf.Major);
868 Console.Write("[Literal:0x{0:X2}]", (int)rtf.Major);
873 void FlushText(bool newline) {
877 length = rtf_line.Length;
882 if (rtf_rtffont != null) {
883 font = new Font(rtf_rtffont.Name, rtf_rtffont_size, rtf_rtfstyle);
888 if (rtf_cursor_x == 0) {
889 document.Add(rtf_cursor_y, rtf_line.ToString(), rtf_rtfalign, font, rtf_color);
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);
902 rtf_cursor_x += length;
904 rtf_line.Length = 0; // Empty line
906 #endregion // Private Methods