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) {
96 #endregion // Private & Internal Methods
98 #region Public Instance Properties
99 public override bool AllowDrop {
101 return base.AllowDrop;
105 base.AllowDrop = value;
109 [DefaultValue(false)]
110 public override bool AutoSize {
116 base.AutoSize = value;
120 [DefaultValue(false)]
121 public bool AutoWordSelection {
123 return auto_word_select;
127 auto_word_select = true;
132 [EditorBrowsable(EditorBrowsableState.Never)]
133 public override System.Drawing.Image BackgroundImage {
135 return background_image;
139 base.BackgroundImage = value;
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 {
182 if (PreferredHeight != Height) {
183 Height = PreferredHeight;
192 public override Color ForeColor {
194 return base.ForeColor;
198 base.ForeColor = value;
202 [DefaultValue(Int32.MaxValue)]
203 public override int MaxLength {
205 return base.max_length;
209 base.max_length = value;
214 public override bool Multiline {
220 base.Multiline = value;
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 {
287 return base.SelectedText;
291 base.SelectedText = value;
296 [DefaultValue(HorizontalAlignment.Left)]
297 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
298 public HorizontalAlignment SelectionAlignment {
300 HorizontalAlignment align;
305 start = document.ParagraphStart(document.selection_start.line);
306 align = start.alignment;
308 end = document.ParagraphEnd(document.selection_end.line);
313 if (line.alignment != align) {
314 return HorizontalAlignment.Left;
320 line = document.GetLine(line.line_no + 1);
331 start = document.ParagraphStart(document.selection_start.line);
333 end = document.ParagraphEnd(document.selection_end.line);
338 line.alignment = value;
343 line = document.GetLine(line.line_no + 1);
345 this.CalculateDocument();
350 public Font SelectionFont {
357 start = document.selection_start.tag;
358 end = document.selection_end.tag;
359 font = document.selection_start.tag.font;
363 if (!font.Equals(tag.font)) {
371 tag = document.NextTag(tag);
385 sel_start = document.LineTagToCharIndex(document.selection_start.line, document.selection_start.pos);
386 sel_end = document.LineTagToCharIndex(document.selection_end.line, document.selection_end.pos);
388 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);
390 document.CharIndexToLineTag(sel_start, out document.selection_start.line, out document.selection_start.tag, out document.selection_start.pos);
391 document.CharIndexToLineTag(sel_end, out document.selection_end.line, out document.selection_end.tag, out document.selection_end.pos);
393 document.UpdateView(document.selection_start.line, 0);
394 document.AlignCaret();
400 public override string Text {
411 public override int TextLength {
413 return base.TextLength;
418 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
419 public string UndoActionName {
421 return undo_action_name;
427 public float ZoomFactor {
436 #endregion // Public Instance Properties
438 #region Protected Instance Properties
439 protected override CreateParams CreateParams {
441 return base.CreateParams;
445 protected override Size DefaultSize {
447 return new Size(100, 96);
450 #endregion // Protected Instance Properties
452 #region Public Instance Methods
453 public void LoadFile(System.IO.Stream data, RichTextBoxStreamType fileType) {
454 RTF.RTF rtf; // Not 'using SWF.RTF' to avoid ambiguities with font and color
458 // FIXME - ignoring unicode
459 if (fileType == RichTextBoxStreamType.PlainText) {
465 sb = new StringBuilder((int)data.Length);
466 buffer = new byte[1024];
470 throw new IOException("Not enough memory to load document");
474 while (count < data.Length) {
475 count += data.Read(buffer, count, 1024);
478 base.Text = sb.ToString();
483 rtf = new RTF.RTF(data);
486 rtf.ClassCallback[RTF.TokenClass.Text] = new RTF.ClassDelegate(HandleText);
487 rtf.ClassCallback[RTF.TokenClass.Control] = new RTF.ClassDelegate(HandleControl);
491 rtf_line = new StringBuilder();
493 rtf_color = new SolidBrush(ForeColor);
494 rtf_rtffont_size = this.Font.Height;
495 rtf_rtfalign = HorizontalAlignment.Left;
500 rtf_text_map = new RTF.TextMap();
501 RTF.TextMap.SetupStandardTable(rtf_text_map.Table);
503 rtf.Read(); // That's it
504 document.RecalculateDocument(CreateGraphics());
507 public void LoadFile(string path) {
508 if (path.EndsWith(".rtf")) {
509 LoadFile(path, RichTextBoxStreamType.RichText);
511 LoadFile(path, RichTextBoxStreamType.PlainText);
515 public void LoadFile(string path, RichTextBoxStreamType fileType) {
521 data = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 1024);
522 LoadFile(data, fileType);
526 // throw new IOException("Could not open file " + path);
536 public void SaveFile(Stream data, RichTextBoxStreamType fileType) {
540 if (fileType == RichTextBoxStreamType.UnicodePlainText) {
541 encoding = Encoding.Unicode;
543 encoding = Encoding.ASCII;
548 public void SaveFile(string path) {
549 if (path.EndsWith(".rtf")) {
550 SaveFile(path, RichTextBoxStreamType.RichText);
552 SaveFile(path, RichTextBoxStreamType.PlainText);
556 public void SaveFile(string path, RichTextBoxStreamType fileType) {
562 data = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None, 1024, false);
563 SaveFile(data, fileType);
567 throw new IOException("Could not write document to file " + path);
577 #endregion // Public Instance Methods
579 #region Protected Instance Methods
580 protected override void OnBackColorChanged(EventArgs e) {
581 base.OnBackColorChanged (e);
584 protected override void OnContextMenuChanged(EventArgs e) {
585 base.OnContextMenuChanged (e);
588 protected override void OnHandleCreated(EventArgs e) {
589 base.OnHandleCreated (e);
592 protected override void OnHandleDestroyed(EventArgs e) {
593 base.OnHandleDestroyed (e);
596 protected override void OnRightToLeftChanged(EventArgs e) {
597 base.OnRightToLeftChanged (e);
600 protected override void OnSystemColorsChanged(EventArgs e) {
601 base.OnSystemColorsChanged (e);
604 protected override void OnTextChanged(EventArgs e) {
605 base.OnTextChanged (e);
608 protected override void WndProc(ref Message m) {
609 base.WndProc (ref m);
611 #endregion // Protected Instance Methods
615 [EditorBrowsable(EditorBrowsableState.Never)]
616 public event EventHandler BackgroundImageChanged;
618 public event ContentsResizedEventHandler ContentsResized;
621 [EditorBrowsable(EditorBrowsableState.Never)]
622 public event EventHandler DoubleClick;
625 [EditorBrowsable(EditorBrowsableState.Never)]
626 public event DragEventHandler DragDrop;
629 [EditorBrowsable(EditorBrowsableState.Never)]
630 public event DragEventHandler DragEnter;
633 [EditorBrowsable(EditorBrowsableState.Never)]
634 public event EventHandler DragLeave;
637 [EditorBrowsable(EditorBrowsableState.Never)]
638 public event DragEventHandler DragOver;
641 [EditorBrowsable(EditorBrowsableState.Never)]
642 public event GiveFeedbackEventHandler GiveFeedback;
644 public event EventHandler HScroll;
645 public event EventHandler ImeChange;
646 public event LinkClickedEventHandler LinkClicked;
647 public event EventHandler Protected;
650 [EditorBrowsable(EditorBrowsableState.Never)]
651 public event QueryContinueDragEventHandler QueryContinueDrag;
652 public event EventHandler SelectionChanged;
653 public event EventHandler VScroll;
656 #region Private Methods
657 void HandleControl(RTF.RTF rtf) {
659 case RTF.Major.Unicode: {
661 case Minor.UnicodeCharBytes: {
662 rtf_skip_width = rtf.Param;
666 case Minor.UnicodeChar: {
667 rtf_skip_count += rtf_skip_width;
668 rtf_line.Append((char)rtf.Param);
675 case RTF.Major.Destination: {
676 Console.Write("[Got Destination control {0}]", rtf.Minor);
681 case RTF.Major.CharAttr: {
683 case Minor.ForeColor: {
684 System.Windows.Forms.RTF.Color color;
686 color = System.Windows.Forms.RTF.Color.GetColor(rtf, rtf.Param);
689 if (color.Red == -1 && color.Green == -1 && color.Blue == -1) {
690 this.rtf_color = new SolidBrush(ForeColor);
692 this.rtf_color = new SolidBrush(Color.FromArgb(color.Red, color.Green, color.Blue));
698 case Minor.FontSize: {
699 this.rtf_rtffont_size = rtf.Param / 2;
703 case Minor.FontNum: {
704 System.Windows.Forms.RTF.Font font;
706 font = System.Windows.Forms.RTF.Font.GetFont(rtf, rtf.Param);
709 this.rtf_rtffont = font;
716 rtf_rtfstyle = FontStyle.Regular;
722 if (rtf.Param == RTF.RTF.NoParam) {
723 rtf_rtfstyle |= FontStyle.Bold;
725 rtf_rtfstyle &= ~FontStyle.Bold;
732 if (rtf.Param == RTF.RTF.NoParam) {
733 rtf_rtfstyle |= FontStyle.Italic;
735 rtf_rtfstyle &= ~FontStyle.Italic;
740 case Minor.StrikeThru: {
742 if (rtf.Param == RTF.RTF.NoParam) {
743 rtf_rtfstyle |= FontStyle.Strikeout;
745 rtf_rtfstyle &= ~FontStyle.Strikeout;
750 case Minor.Underline: {
752 if (rtf.Param == RTF.RTF.NoParam) {
753 rtf_rtfstyle |= FontStyle.Underline;
755 rtf_rtfstyle &= ~FontStyle.Underline;
760 case Minor.NoUnderline: {
762 rtf_rtfstyle &= ~FontStyle.Underline;
769 case RTF.Major.SpecialChar: {
770 Console.Write("[Got SpecialChar control {0}]", rtf.Minor);
777 void SpecialChar(RTF.RTF rtf) {
793 case Minor.NoBrkSpace: {
803 case Minor.NoBrkHyphen: {
814 Console.Write("
\97");
819 Console.Write("
\96");
824 Console.Write("
\91");
829 Console.Write("
\92");
833 case Minor.LDblQuote: {
834 Console.Write("
\93");
838 case Minor.RDblQuote: {
839 Console.Write("
\94");
851 void HandleText(RTF.RTF rtf) {
852 if (rtf_skip_count > 0) {
857 if ((RTF.StandardCharCode)rtf.Minor != RTF.StandardCharCode.nothing) {
858 rtf_line.Append(rtf_text_map[(RTF.StandardCharCode)rtf.Minor]);
860 if ((int)rtf.Major > 31 && (int)rtf.Major < 128) {
861 rtf_line.Append((char)rtf.Major);
863 //rtf_line.Append((char)rtf.Major);
864 Console.Write("[Literal:0x{0:X2}]", (int)rtf.Major);
869 void FlushText(bool newline) {
873 length = rtf_line.Length;
878 if (rtf_rtffont != null) {
879 font = new Font(rtf_rtffont.Name, rtf_rtffont_size, rtf_rtfstyle);
884 if (rtf_cursor_x == 0) {
885 document.Add(rtf_cursor_y, rtf_line.ToString(), rtf_rtfalign, font, rtf_color);
889 line = document.GetLine(rtf_cursor_y);
890 document.InsertString(line, rtf_cursor_x, rtf_line.ToString());
891 document.FormatText(line, rtf_cursor_x, line, rtf_cursor_x + length, font, rtf_color);
898 rtf_cursor_x += length;
900 rtf_line.Length = 0; // Empty line
902 #endregion // Private Methods