X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;ds=sidebyside;f=mcs%2Fclass%2FManaged.Windows.Forms%2FSystem.Windows.Forms%2FRichTextBox.cs;h=5dbb0c7d8371074494c8412fd2e4689a6f23d637;hb=f231b4440acbef04fc8ad8a4fd75a02f99955f7e;hp=5d20bfd5fc76c6edb5b409e7e3574acd7bfdcbd2;hpb=00e065484e866f3a0349c882f804c4a79a13ee5c;p=mono.git diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/RichTextBox.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/RichTextBox.cs index 5d20bfd5fc7..5dbb0c7d837 100644 --- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/RichTextBox.cs +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/RichTextBox.cs @@ -24,40 +24,51 @@ // // -// NOT COMPLETE +// #define DEBUG using System; using System.Collections; using System.ComponentModel; using System.Drawing; +using System.Drawing.Imaging; using System.IO; using System.Text; +using System.Runtime.InteropServices; using RTF=System.Windows.Forms.RTF; namespace System.Windows.Forms { +#if NET_2_0 + [ClassInterface (ClassInterfaceType.AutoDispatch)] + [Docking (DockingBehavior.Ask)] + [ComVisible (true)] + [Designer ("System.Windows.Forms.Design.RichTextBoxDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")] +#endif public class RichTextBox : TextBoxBase { #region Local Variables internal bool auto_word_select; internal int bullet_indent; - internal bool can_redo; internal bool detect_urls; - internal string redo_action_name; internal int margin_right; - internal string undo_action_name; internal float zoom; - - private RTF.TextMap rtf_text_map; - private int rtf_skip_width; - private int rtf_skip_count; private StringBuilder rtf_line; - private SolidBrush rtf_color; - private RTF.Font rtf_rtffont; - private int rtf_rtffont_size; - private FontStyle rtf_rtfstyle; - private HorizontalAlignment rtf_rtfalign; + + private RtfSectionStyle rtf_style; // Replaces individual style + // properties so we can revert + private Stack rtf_section_stack; + + private RTF.TextMap rtf_text_map; + private int rtf_skip_width; + private int rtf_skip_count; private int rtf_cursor_x; private int rtf_cursor_y; private int rtf_chars; + +#if NET_2_0 + private bool enable_auto_drag_drop; + private RichTextBoxLanguageOptions language_option; + private bool rich_text_shortcuts_enabled; + private Color selection_back_color; +#endif #endregion // Local Variables #region Public Constructors @@ -65,40 +76,74 @@ namespace System.Windows.Forms { accepts_return = true; auto_word_select = false; bullet_indent = 0; - can_redo = false; - detect_urls = true; max_length = Int32.MaxValue; - redo_action_name = string.Empty; margin_right = 0; - undo_action_name = string.Empty; zoom = 1; base.Multiline = true; document.CRLFSize = 1; + shortcuts_enabled = true; + base.EnableLinks = true; + + rtf_style = new RtfSectionStyle (); + rtf_section_stack = null; scrollbars = RichTextBoxScrollBars.Both; alignment = HorizontalAlignment.Left; LostFocus += new EventHandler(RichTextBox_LostFocus); GotFocus += new EventHandler(RichTextBox_GotFocus); BackColor = ThemeEngine.Current.ColorWindow; +#if NET_2_0 + backcolor_set = false; + language_option = RichTextBoxLanguageOptions.AutoFontSizeAdjust; + rich_text_shortcuts_enabled = true; + selection_back_color = DefaultBackColor; +#endif ForeColor = ThemeEngine.Current.ColorWindowText; + base.HScrolled += new EventHandler(RichTextBox_HScrolled); base.VScrolled += new EventHandler(RichTextBox_VScrolled); + +#if NET_2_0 + SetStyle (ControlStyles.StandardDoubleClick, false); +#endif } #endregion // Public Constructors #region Private & Internal Methods + + internal override void HandleLinkClicked (LinkRectangle link) + { + OnLinkClicked (new LinkClickedEventArgs (link.LinkTag.LinkText)); + } + + internal override Color ChangeBackColor (Color backColor) + { + if (backColor == Color.Empty) { +#if NET_2_0 + backcolor_set = false; + if (!ReadOnly) { + backColor = SystemColors.Window; + } +#else + backColor = SystemColors.Window; +#endif + } + return backColor; + } + private void RichTextBox_LostFocus(object sender, EventArgs e) { - has_focus = false; Invalidate(); } private void RichTextBox_GotFocus(object sender, EventArgs e) { - has_focus = true; Invalidate(); } #endregion // Private & Internal Methods #region Public Instance Properties +#if NET_2_0 + [Browsable (false)] +#endif public override bool AllowDrop { get { return base.AllowDrop; @@ -110,7 +155,14 @@ namespace System.Windows.Forms { } [DefaultValue(false)] +#if NET_2_0 + [DesignerSerializationVisibility (DesignerSerializationVisibility.Visible)] + [RefreshProperties (RefreshProperties.Repaint)] + [EditorBrowsable (EditorBrowsableState.Never)] + [Browsable (false)] +#else [Localizable(true)] +#endif public override bool AutoSize { get { return auto_size; @@ -121,28 +173,28 @@ namespace System.Windows.Forms { } } + [MonoTODO ("Value not respected, always true")] [DefaultValue(false)] public bool AutoWordSelection { - get { - return auto_word_select; - } - - set { - auto_word_select = true; - } + get { return auto_word_select; } + set { auto_word_select = value; } } [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Never)] public override System.Drawing.Image BackgroundImage { - get { - return background_image; - } + get { return base.BackgroundImage; } + set { base.BackgroundImage = value; } + } - set { - base.BackgroundImage = value; - } +#if NET_2_0 + [Browsable (false)] + [EditorBrowsable (EditorBrowsableState.Never)] + public override ImageLayout BackgroundImageLayout { + get { return base.BackgroundImageLayout; } + set { base.BackgroundImageLayout = value; } } +#endif [DefaultValue(0)] [Localizable(true)] @@ -160,20 +212,24 @@ namespace System.Windows.Forms { [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public bool CanRedo { get { - return can_redo; + return document.undo.CanRedo; } } [DefaultValue(true)] public bool DetectUrls { - get { - return detect_urls; - } + get { return base.EnableLinks; } + set { base.EnableLinks = value; } + } - set { - detect_urls = true; - } +#if NET_2_0 + [MonoTODO ("Stub")] + [DefaultValue (false)] + public bool EnableAutoDragDrop { + get { return enable_auto_drag_drop; } + set { enable_auto_drag_drop = value; } } +#endif public override Font Font { get { @@ -196,7 +252,7 @@ namespace System.Windows.Forms { // Font changes always set the whole doc to that font start = document.GetLine(1); end = document.GetLine(document.Lines); - document.FormatText(start, 1, end, end.text.Length + 1, base.Font, new SolidBrush(this.ForeColor)); + document.FormatText(start, 1, end, end.text.Length + 1, base.Font, Color.Empty, Color.Empty, FormatSpecified.Font); } } } @@ -211,6 +267,16 @@ namespace System.Windows.Forms { } } +#if NET_2_0 + [MonoTODO ("Stub")] + [Browsable (false)] + [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] + public RichTextBoxLanguageOptions LanguageOption { + get { return language_option; } + set { language_option = value; } + } +#endif + [DefaultValue(Int32.MaxValue)] public override int MaxLength { get { @@ -225,7 +291,7 @@ namespace System.Windows.Forms { [DefaultValue(true)] public override bool Multiline { get { - return multiline; + return base.Multiline; } set { @@ -238,10 +304,21 @@ namespace System.Windows.Forms { [MonoTODO] public string RedoActionName { get { - return redo_action_name; + return document.undo.RedoActionName; } } +#if NET_2_0 + [MonoTODO ("Stub")] + [Browsable (false)] + [DefaultValue (true)] + [EditorBrowsable (EditorBrowsableState.Never)] + public bool RichTextShortcutsEnabled { + get { return rich_text_shortcuts_enabled; } + set { rich_text_shortcuts_enabled = value; } + } +#endif + [DefaultValue(0)] [Localizable(true)] [MonoTODO("Teach TextControl.RecalculateLine to consider the right margin as well")] @@ -256,8 +333,12 @@ namespace System.Windows.Forms { } [Browsable(false)] - [DefaultValue("")] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] +#if NET_2_0 + [RefreshProperties (RefreshProperties.All)] +#else + [DefaultValue("")] +#endif public string Rtf { get { Line start_line; @@ -290,7 +371,14 @@ namespace System.Windows.Forms { } set { - scrollbars = value; + if (!Enum.IsDefined (typeof (RichTextBoxScrollBars), value)) + throw new InvalidEnumArgumentException ("value", (int) value, + typeof (RichTextBoxScrollBars)); + + if (value != scrollbars) { + scrollbars = value; + CalculateDocument (); + } } } @@ -302,7 +390,7 @@ namespace System.Windows.Forms { return GenerateRTF(document.selection_start.line, document.selection_start.pos, document.selection_end.line, document.selection_end.pos).ToString(); } - set { + set { MemoryStream data; int x; int y; @@ -312,7 +400,7 @@ namespace System.Windows.Forms { LineTag tag; if (document.selection_visible) { - document.ReplaceSelection(""); + document.ReplaceSelection("", false); } sel_start = document.LineTagToCharIndex(document.selection_start.line, document.selection_start.pos); @@ -397,6 +485,16 @@ namespace System.Windows.Forms { } } +#if NET_2_0 + [MonoTODO ("Stub")] + [Browsable (false)] + [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] + public Color SelectionBackColor { + get { return selection_back_color; } + set { selection_back_color = value; } + } +#endif + [Browsable(false)] [DefaultValue(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] @@ -432,48 +530,53 @@ namespace System.Windows.Forms { LineTag end; LineTag tag; - start = document.selection_start.tag; - end = document.selection_end.tag; - color = ((SolidBrush)document.selection_start.tag.color).Color; + if (selection_length > 0) { + start = document.selection_start.line.FindTag (document.selection_start.pos + 1); + end = document.selection_start.line.FindTag (document.selection_end.pos); + } else { + start = document.selection_start.line.FindTag (document.selection_start.pos); + end = start; + } + + color = start.Color; tag = start; - while (true) { - if (!color.Equals(((SolidBrush)tag.color).Color)) { + while (tag != null) { + + if (!color.Equals (tag.Color)) return Color.Empty; - } - if (tag == end) { + if (tag == end) break; - } - tag = document.NextTag(tag); - - if (tag == null) { - break; - } + tag = document.NextTag (tag); } return color; } set { - FontDefinition attributes; - int sel_start; - int sel_end; - - attributes = new FontDefinition(); - attributes.color = value; + if (value == Color.Empty) + value = DefaultForeColor; + + int sel_start; + int sel_end; sel_start = document.LineTagToCharIndex(document.selection_start.line, document.selection_start.pos); sel_end = document.LineTagToCharIndex(document.selection_end.line, document.selection_end.pos); - document.FormatText(document.selection_start.line, document.selection_start.pos + 1, document.selection_end.line, document.selection_end.pos + 1, attributes); + document.FormatText (document.selection_start.line, document.selection_start.pos + 1, + document.selection_end.line, document.selection_end.pos + 1, null, + value, Color.Empty, FormatSpecified.Color); document.CharIndexToLineTag(sel_start, out document.selection_start.line, out document.selection_start.tag, out document.selection_start.pos); document.CharIndexToLineTag(sel_end, out document.selection_end.line, out document.selection_end.tag, out document.selection_end.pos); document.UpdateView(document.selection_start.line, 0); - document.AlignCaret(); + + //Re-Align the caret in case its changed size or position + //probably not necessary here + document.AlignCaret(false); } } @@ -486,24 +589,27 @@ namespace System.Windows.Forms { LineTag end; LineTag tag; - start = document.selection_start.tag; - end = document.selection_end.tag; - font = document.selection_start.tag.font; + if (selection_length > 0) { + start = document.selection_start.line.FindTag (document.selection_start.pos + 1); + end = document.selection_start.line.FindTag (document.selection_end.pos); + } else { + start = document.selection_start.line.FindTag (document.selection_start.pos); + end = start; + } + + font = start.Font; - tag = start; - while (true) { - if (!font.Equals(tag.font)) { - return null; - } + if (selection_length > 1) { + tag = start; + while (tag != null) { - if (tag == end) { - break; - } + if (!font.Equals(tag.Font)) + return null; - tag = document.NextTag(tag); + if (tag == end) + break; - if (tag == null) { - break; + tag = document.NextTag (tag); } } @@ -511,23 +617,22 @@ namespace System.Windows.Forms { } set { - FontDefinition attributes; int sel_start; int sel_end; - attributes = new FontDefinition(); - attributes.font_obj = value; - sel_start = document.LineTagToCharIndex(document.selection_start.line, document.selection_start.pos); sel_end = document.LineTagToCharIndex(document.selection_end.line, document.selection_end.pos); - document.FormatText(document.selection_start.line, document.selection_start.pos + 1, document.selection_end.line, document.selection_end.pos + 1, attributes); + document.FormatText (document.selection_start.line, document.selection_start.pos + 1, + document.selection_end.line, document.selection_end.pos + 1, value, + Color.Empty, Color.Empty, FormatSpecified.Font); document.CharIndexToLineTag(sel_start, out document.selection_start.line, out document.selection_start.tag, out document.selection_start.pos); document.CharIndexToLineTag(sel_end, out document.selection_end.line, out document.selection_end.tag, out document.selection_end.pos); document.UpdateView(document.selection_start.line, 0); - document.AlignCaret(); + //Re-Align the caret in case its changed size or position + Document.AlignCaret (false); } } @@ -637,6 +742,9 @@ namespace System.Windows.Forms { } [Localizable(true)] +#if NET_2_0 + [RefreshProperties (RefreshProperties.All)] +#endif public override string Text { get { return base.Text; @@ -658,7 +766,7 @@ namespace System.Windows.Forms { [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public string UndoActionName { get { - return document.undo.UndoName; + return document.undo.UndoActionName; } } @@ -805,30 +913,53 @@ namespace System.Windows.Forms { return Find(str, -1, -1, options); } + +#if !NET_2_0 public char GetCharFromPosition(Point pt) { LineTag tag; int pos; PointToTagPos(pt, out tag, out pos); - if (pos >= tag.line.text.Length) { + if (pos >= tag.Line.text.Length) { return '\n'; } - return tag.line.text[pos]; - + return tag.Line.text[pos]; } +#else + internal override char GetCharFromPositionInternal (Point p) + { + LineTag tag; + int pos; - public int GetCharIndexFromPosition(Point pt) { + PointToTagPos (p, out tag, out pos); + + if (pos >= tag.Line.text.Length) + return '\n'; + + return tag.Line.text[pos]; + } +#endif + + public +#if NET_2_0 + override +#endif + int GetCharIndexFromPosition(Point pt) { LineTag tag; int pos; PointToTagPos(pt, out tag, out pos); - return document.LineTagToCharIndex(tag.line, pos); + return document.LineTagToCharIndex(tag.Line, pos); } - public int GetLineFromCharIndex(int index) { + public +#if NET_2_0 + override +#endif + int GetLineFromCharIndex(int index) { Line line; LineTag tag; int pos; @@ -838,7 +969,11 @@ namespace System.Windows.Forms { return line.LineNo - 1; } - public Point GetPositionFromCharIndex(int index) { + public +#if NET_2_0 + override +#endif + Point GetPositionFromCharIndex(int index) { Line line; LineTag tag; int pos; @@ -851,31 +986,34 @@ namespace System.Windows.Forms { public void LoadFile(System.IO.Stream data, RichTextBoxStreamType fileType) { document.Empty(); + // FIXME - ignoring unicode if (fileType == RichTextBoxStreamType.PlainText) { - StringBuilder sb; - int count; - byte[] buffer; + StringBuilder sb; + char[] buffer; try { - sb = new StringBuilder((int)data.Length); - buffer = new byte[1024]; - } - - catch { + sb = new StringBuilder ((int) data.Length); + buffer = new char [1024]; + } catch { throw new IOException("Not enough memory to load document"); } - count = 0; - while (count < data.Length) { - count += data.Read(buffer, count, 1024); - sb.Append(buffer); + StreamReader sr = new StreamReader (data, Encoding.Default, true); + int charsRead = sr.Read (buffer, 0, buffer.Length); + while (charsRead > 0) { + sb.Append (buffer, 0, charsRead); + charsRead = sr.Read (buffer, 0, buffer.Length); } base.Text = sb.ToString(); return; } InsertRTFFromStream(data, 0, 1); + + document.PositionCaret (document.GetLine (1), 0); + document.SetSelectionToCaret (true); + ScrollToCaret (); } [MonoTODO("Make smarter RTF detection?")] @@ -892,15 +1030,17 @@ namespace System.Windows.Forms { data = null; + try { data = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, 1024); + LoadFile(data, fileType); } - - catch { - throw new IOException("Could not open file " + path); +#if !DEBUG + catch (Exception ex) { + throw new IOException("Could not open file " + path, ex); } - +#endif finally { if (data != null) { data.Close(); @@ -912,8 +1052,9 @@ namespace System.Windows.Forms { base.Paste(Clipboard.GetDataObject(), clipFormat, false); } - [MonoTODO()] - public void Redo() { + public void Redo() + { + document.undo.Redo (); } public void SaveFile(Stream data, RichTextBoxStreamType fileType) { @@ -932,7 +1073,7 @@ namespace System.Windows.Forms { case RichTextBoxStreamType.PlainText: case RichTextBoxStreamType.TextTextOleObjs: case RichTextBoxStreamType.UnicodePlainText: { - if (!multiline) { + if (!Multiline) { bytes = encoding.GetBytes(document.Root.text.ToString()); data.Write(bytes, 0, bytes.Length); return; @@ -1002,6 +1143,23 @@ namespace System.Windows.Forms { // } } +#if NET_2_0 + [EditorBrowsable (EditorBrowsableState.Never)] + public new void DrawToBitmap (Bitmap bitmap, Rectangle clip) + { + Graphics dc = Graphics.FromImage (bitmap); + + if (backcolor_set || (Enabled && !read_only)) { + dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (BackColor), clip); + } else { + dc.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (ThemeEngine.Current.ColorControl), clip); + } + + // Draw the viewable document + document.Draw (dc, clip); + } +#endif + #endregion // Public Instance Methods #region Protected Instance Methods @@ -1014,9 +1172,9 @@ namespace System.Windows.Forms { } protected virtual void OnContentsResized(ContentsResizedEventArgs e) { - if (ContentsResized != null) { - ContentsResized(this, e); - } + ContentsResizedEventHandler eh = (ContentsResizedEventHandler)(Events [ContentsResizedEvent]); + if (eh != null) + eh (this, e); } protected override void OnContextMenuChanged(EventArgs e) { @@ -1032,28 +1190,28 @@ namespace System.Windows.Forms { } protected virtual void OnHScroll(EventArgs e) { - if (HScroll != null) { - HScroll(this, e); - } + EventHandler eh = (EventHandler)(Events [HScrollEvent]); + if (eh != null) + eh (this, e); } [MonoTODO("Determine when to call this")] protected virtual void OnImeChange(EventArgs e) { - if (ImeChange != null) { - ImeChange(this, e); - } + EventHandler eh = (EventHandler)(Events [ImeChangeEvent]); + if (eh != null) + eh (this, e); } protected virtual void OnLinkClicked(LinkClickedEventArgs e) { - if (LinkClicked != null) { - LinkClicked(this, e); - } + LinkClickedEventHandler eh = (LinkClickedEventHandler)(Events [LinkClickedEvent]); + if (eh != null) + eh (this, e); } protected virtual void OnProtected(EventArgs e) { - if (Protected != null) { - Protected(this, e); - } + EventHandler eh = (EventHandler)(Events [ProtectedEvent]); + if (eh != null) + eh (this, e); } protected override void OnRightToLeftChanged(EventArgs e) { @@ -1061,11 +1219,12 @@ namespace System.Windows.Forms { } protected virtual void OnSelectionChanged(EventArgs e) { - if (SelectionChanged != null) { - SelectionChanged(this, e); - } + EventHandler eh = (EventHandler)(Events [SelectionChangedEvent]); + if (eh != null) + eh (this, e); } +#if !NET_2_0 protected override void OnSystemColorsChanged(EventArgs e) { base.OnSystemColorsChanged (e); } @@ -1073,106 +1232,207 @@ namespace System.Windows.Forms { protected override void OnTextChanged(EventArgs e) { base.OnTextChanged (e); } +#endif protected virtual void OnVScroll(EventArgs e) { - if (VScroll != null) { - VScroll(this, e); - } + EventHandler eh = (EventHandler)(Events [VScrollEvent]); + if (eh != null) + eh (this, e); } protected override void WndProc(ref Message m) { base.WndProc (ref m); } + +#if NET_2_0 + protected override bool ProcessCmdKey (ref Message msg, Keys keyData) + { + return base.ProcessCmdKey (ref msg, keyData); + } +#endif #endregion // Protected Instance Methods #region Events + static object ContentsResizedEvent = new object (); + static object HScrollEvent = new object (); + static object ImeChangeEvent = new object (); + static object LinkClickedEvent = new object (); + static object ProtectedEvent = new object (); + static object SelectionChangedEvent = new object (); + static object VScrollEvent = new object (); + [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Never)] - public event EventHandler BackgroundImageChanged; + public new event EventHandler BackgroundImageChanged { + add { base.BackgroundImageChanged += value; } + remove { base.BackgroundImageChanged -= value; } + } + +#if NET_2_0 + [Browsable (false)] + [EditorBrowsable (EditorBrowsableState.Never)] + public new event EventHandler BackgroundImageLayoutChanged { + add { base.BackgroundImageLayoutChanged += value; } + remove { base.BackgroundImageLayoutChanged -= value; } + } +#endif - public event ContentsResizedEventHandler ContentsResized; + public event ContentsResizedEventHandler ContentsResized { + add { Events.AddHandler (ContentsResizedEvent, value); } + remove { Events.RemoveHandler (ContentsResizedEvent, value); } + } +#if !NET_2_0 [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Never)] - public event EventHandler DoubleClick; + public new event EventHandler DoubleClick { + add { base.DoubleClick += value; } + remove { base.DoubleClick -= value; } + } +#endif [Browsable(false)] +#if !NET_2_0 [EditorBrowsable(EditorBrowsableState.Never)] - public event DragEventHandler DragDrop { - add { - base.DragDrop += value; - } - - remove { - base.DragDrop -= value; - } +#endif + public new event DragEventHandler DragDrop { + add { base.DragDrop += value; } + remove { base.DragDrop -= value; } } [Browsable(false)] +#if !NET_2_0 [EditorBrowsable(EditorBrowsableState.Never)] - public event DragEventHandler DragEnter { - add { - base.DragEnter += value; - } - - remove { - base.DragEnter -= value; - } +#endif + public new event DragEventHandler DragEnter { + add { base.DragEnter += value; } + remove { base.DragEnter -= value; } } [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Never)] - public event EventHandler DragLeave { - add { - base.DragLeave += value; - } - - remove { - base.DragLeave -= value; - } + public new event EventHandler DragLeave { + add { base.DragLeave += value; } + remove { base.DragLeave -= value; } } [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Never)] - public event DragEventHandler DragOver { - add { - base.DragOver += value; - } - - remove { - base.DragOver -= value; - } + public new event DragEventHandler DragOver { + add { base.DragOver += value; } + remove { base.DragOver -= value; } } [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Never)] - public event GiveFeedbackEventHandler GiveFeedback; + public new event GiveFeedbackEventHandler GiveFeedback { + add { base.GiveFeedback += value; } + remove { base.GiveFeedback -= value; } + } + + public event EventHandler HScroll { + add { Events.AddHandler (HScrollEvent, value); } + remove { Events.RemoveHandler (HScrollEvent, value); } + } - public event EventHandler HScroll; - public event EventHandler ImeChange; - public event LinkClickedEventHandler LinkClicked; - public event EventHandler Protected; + public event EventHandler ImeChange { + add { Events.AddHandler (ImeChangeEvent, value); } + remove { Events.RemoveHandler (ImeChangeEvent, value); } + } + + public event LinkClickedEventHandler LinkClicked { + add { Events.AddHandler (LinkClickedEvent, value); } + remove { Events.RemoveHandler (LinkClickedEvent, value); } + } + + public event EventHandler Protected { + add { Events.AddHandler (ProtectedEvent, value); } + remove { Events.RemoveHandler (ProtectedEvent, value); } + } [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Never)] - public event QueryContinueDragEventHandler QueryContinueDrag; - public event EventHandler SelectionChanged; - public event EventHandler VScroll; + public new event QueryContinueDragEventHandler QueryContinueDrag { + add { base.QueryContinueDrag += value; } + remove { base.QueryContinueDrag -= value; } + } + + [MonoTODO("Currently does not ever fire")] + public event EventHandler SelectionChanged { + add { Events.AddHandler (SelectionChangedEvent, value); } + remove { Events.RemoveHandler (SelectionChangedEvent, value); } + } + + public event EventHandler VScroll { + add { Events.AddHandler (VScrollEvent, value); } + remove { Events.RemoveHandler (VScrollEvent, value); } + } #endregion // Events #region Private Methods + + internal override void SelectWord () + { + document.ExpandSelection(CaretSelection.Word, false); + } + + private class RtfSectionStyle : ICloneable { + internal Color rtf_color; + internal RTF.Font rtf_rtffont; + internal int rtf_rtffont_size; + internal FontStyle rtf_rtfstyle; + internal HorizontalAlignment rtf_rtfalign; + internal int rtf_par_line_left_indent; + + public object Clone () + { + RtfSectionStyle new_style = new RtfSectionStyle (); + + new_style.rtf_color = rtf_color; + new_style.rtf_par_line_left_indent = rtf_par_line_left_indent; + new_style.rtf_rtfalign = rtf_rtfalign; + new_style.rtf_rtffont = rtf_rtffont; + new_style.rtf_rtffont_size = rtf_rtffont_size; + new_style.rtf_rtfstyle = rtf_rtfstyle; + + return new_style; + } + } + + // To allow us to keep track of the sections and revert formatting + // as we go in and out of sections of the document. + private void HandleGroup (RTF.RTF rtf) + { + //start group - save the current formatting on to a stack + //end group - go back to the formatting at the current group + if (rtf_section_stack == null) { + rtf_section_stack = new Stack (); + } + + if (rtf.Major == RTF.Major.BeginGroup) { + rtf_section_stack.Push (rtf_style.Clone ()); + } else if (rtf.Major == RTF.Major.EndGroup) { + if (rtf_section_stack.Count > 0) { + FlushText (rtf, false); + + rtf_style = (RtfSectionStyle) rtf_section_stack.Pop (); + } + } + } + + [MonoTODO("Add QuadJust support for justified alignment")] private void HandleControl(RTF.RTF rtf) { switch(rtf.Major) { case RTF.Major.Unicode: { switch(rtf.Minor) { - case Minor.UnicodeCharBytes: { + case RTF.Minor.UnicodeCharBytes: { rtf_skip_width = rtf.Param; break; } - case Minor.UnicodeChar: { + case RTF.Minor.UnicodeChar: { rtf_skip_count += rtf_skip_width; rtf_line.Append((char)rtf.Param); break; @@ -1182,103 +1442,152 @@ namespace System.Windows.Forms { } case RTF.Major.Destination: { - Console.Write("[Got Destination control {0}]", rtf.Minor); +// Console.Write("[Got Destination control {0}]", rtf.Minor); rtf.SkipGroup(); break; } + case RTF.Major.PictAttr: + if (rtf.Picture != null && rtf.Picture.IsValid ()) { + Line line = document.GetLine (rtf_cursor_y); + document.InsertPicture (line, 0, rtf.Picture); + rtf_cursor_x++; + + FlushText (rtf, true); + rtf.Picture = null; + } + break; + case RTF.Major.CharAttr: { switch(rtf.Minor) { - case Minor.ForeColor: { + case RTF.Minor.ForeColor: { System.Windows.Forms.RTF.Color color; color = System.Windows.Forms.RTF.Color.GetColor(rtf, rtf.Param); + if (color != null) { FlushText(rtf, false); if (color.Red == -1 && color.Green == -1 && color.Blue == -1) { - this.rtf_color = new SolidBrush(ForeColor); + this.rtf_style.rtf_color = ForeColor; } else { - this.rtf_color = new SolidBrush(Color.FromArgb(color.Red, color.Green, color.Blue)); + this.rtf_style.rtf_color = Color.FromArgb(color.Red, color.Green, color.Blue); } + FlushText (rtf, false); } break; } - case Minor.FontSize: { + case RTF.Minor.FontSize: { FlushText(rtf, false); - this.rtf_rtffont_size = rtf.Param / 2; + this.rtf_style.rtf_rtffont_size = rtf.Param / 2; break; } - case Minor.FontNum: { + case RTF.Minor.FontNum: { System.Windows.Forms.RTF.Font font; font = System.Windows.Forms.RTF.Font.GetFont(rtf, rtf.Param); if (font != null) { FlushText(rtf, false); - this.rtf_rtffont = font; + this.rtf_style.rtf_rtffont = font; } break; } - case Minor.Plain: { + case RTF.Minor.Plain: { FlushText(rtf, false); - rtf_rtfstyle = FontStyle.Regular; + rtf_style.rtf_rtfstyle = FontStyle.Regular; break; } - case Minor.Bold: { + case RTF.Minor.Bold: { FlushText(rtf, false); if (rtf.Param == RTF.RTF.NoParam) { - rtf_rtfstyle |= FontStyle.Bold; + rtf_style.rtf_rtfstyle |= FontStyle.Bold; } else { - rtf_rtfstyle &= ~FontStyle.Bold; + rtf_style.rtf_rtfstyle &= ~FontStyle.Bold; } break; } - case Minor.Italic: { + case RTF.Minor.Italic: { FlushText(rtf, false); if (rtf.Param == RTF.RTF.NoParam) { - rtf_rtfstyle |= FontStyle.Italic; + rtf_style.rtf_rtfstyle |= FontStyle.Italic; } else { - rtf_rtfstyle &= ~FontStyle.Italic; + rtf_style.rtf_rtfstyle &= ~FontStyle.Italic; } break; } - case Minor.StrikeThru: { + case RTF.Minor.StrikeThru: { FlushText(rtf, false); if (rtf.Param == RTF.RTF.NoParam) { - rtf_rtfstyle |= FontStyle.Strikeout; + rtf_style.rtf_rtfstyle |= FontStyle.Strikeout; } else { - rtf_rtfstyle &= ~FontStyle.Strikeout; + rtf_style.rtf_rtfstyle &= ~FontStyle.Strikeout; } break; } - case Minor.Underline: { + case RTF.Minor.Underline: { FlushText(rtf, false); if (rtf.Param == RTF.RTF.NoParam) { - rtf_rtfstyle |= FontStyle.Underline; + rtf_style.rtf_rtfstyle |= FontStyle.Underline; } else { - rtf_rtfstyle = rtf_rtfstyle & ~FontStyle.Underline; + rtf_style.rtf_rtfstyle = rtf_style.rtf_rtfstyle & ~FontStyle.Underline; } break; } - case Minor.NoUnderline: { + case RTF.Minor.NoUnderline: { FlushText(rtf, false); - rtf_rtfstyle &= ~FontStyle.Underline; + rtf_style.rtf_rtfstyle &= ~FontStyle.Underline; break; } } break; } - case RTF.Major.SpecialChar: { + case RTF.Major.ParAttr: { + switch (rtf.Minor) { + + case RTF.Minor.ParDef: + FlushText (rtf, false); + rtf_style.rtf_par_line_left_indent = 0; + rtf_style.rtf_rtfalign = HorizontalAlignment.Left; + break; + + case RTF.Minor.LeftIndent: + rtf_style.rtf_par_line_left_indent = (int) (((float) rtf.Param / 1440.0F) * CreateGraphics ().DpiX + 0.5F); + break; + + case RTF.Minor.QuadCenter: + FlushText (rtf, false); + rtf_style.rtf_rtfalign = HorizontalAlignment.Center; + break; + + case RTF.Minor.QuadJust: + FlushText (rtf, false); + rtf_style.rtf_rtfalign = HorizontalAlignment.Center; + break; + + case RTF.Minor.QuadLeft: + FlushText (rtf, false); + rtf_style.rtf_rtfalign = HorizontalAlignment.Left; + break; + + case RTF.Minor.QuadRight: + FlushText (rtf, false); + rtf_style.rtf_rtfalign = HorizontalAlignment.Right; + break; + } + break; + } + + case RTF.Major.SpecialChar: { //Console.Write("[Got SpecialChar control {0}]", rtf.Minor); - SpecialChar(rtf); + SpecialChar (rtf); break; } } @@ -1286,72 +1595,79 @@ namespace System.Windows.Forms { private void SpecialChar(RTF.RTF rtf) { switch(rtf.Minor) { - case Minor.Page: - case Minor.Sect: - case Minor.Row: - case Minor.Line: - case Minor.Par: { + case RTF.Minor.Page: + case RTF.Minor.Sect: + case RTF.Minor.Row: + case RTF.Minor.Line: + case RTF.Minor.Par: { FlushText(rtf, true); break; } - case Minor.Cell: { + case RTF.Minor.Cell: { Console.Write(" "); break; } - case Minor.NoBrkSpace: { + case RTF.Minor.NoBrkSpace: { Console.Write(" "); break; } - case Minor.Tab: { - Console.Write("\t"); + case RTF.Minor.Tab: { + rtf_line.Append ("\t"); +// FlushText (rtf, false); break; } - case Minor.NoBrkHyphen: { - Console.Write("-"); + case RTF.Minor.NoReqHyphen: + case RTF.Minor.NoBrkHyphen: { + rtf_line.Append ("-"); +// FlushText (rtf, false); break; } - case Minor.Bullet: { - Console.Write("*"); + case RTF.Minor.Bullet: { + Console.WriteLine("*"); break; } - case Minor.EmDash: { - Console.Write("\u2014"); + case RTF.Minor.WidowCtrl: + break; + + case RTF.Minor.EmDash: { + rtf_line.Append ("\u2014"); break; } - case Minor.EnDash: { - Console.Write("\u2013"); + case RTF.Minor.EnDash: { + rtf_line.Append ("\u2013"); break; } - - case Minor.LQuote: { +/* + case RTF.Minor.LQuote: { Console.Write("\u2018"); break; } - case Minor.RQuote: { + case RTF.Minor.RQuote: { Console.Write("\u2019"); break; } - case Minor.LDblQuote: { + case RTF.Minor.LDblQuote: { Console.Write("\u201C"); break; } - case Minor.RDblQuote: { + case RTF.Minor.RDblQuote: { Console.Write("\u201D"); break; } - +*/ default: { - rtf.SkipGroup(); +// Console.WriteLine ("skipped special char: {0}", rtf.Minor); +// rtf.SkipGroup(); break; } } @@ -1363,6 +1679,7 @@ namespace System.Windows.Forms { return; } + /* if ((RTF.StandardCharCode)rtf.Minor != RTF.StandardCharCode.nothing) { rtf_line.Append(rtf_text_map[(RTF.StandardCharCode)rtf.Minor]); } else { @@ -1373,6 +1690,8 @@ namespace System.Windows.Forms { Console.Write("[Literal:0x{0:X2}]", (int)rtf.Major); } } + */ + rtf_line.Append (rtf.EncodedText); } private void FlushText(RTF.RTF rtf, bool newline) { @@ -1384,40 +1703,59 @@ namespace System.Windows.Forms { return; } - if (rtf_rtffont == null) { + if (rtf_style.rtf_rtffont == null) { // First font in table is default - rtf_rtffont = System.Windows.Forms.RTF.Font.GetFont(rtf, 0); + rtf_style.rtf_rtffont = System.Windows.Forms.RTF.Font.GetFont (rtf, 0); } - font = new Font(rtf_rtffont.Name, rtf_rtffont_size, rtf_rtfstyle); + font = new Font (rtf_style.rtf_rtffont.Name, rtf_style.rtf_rtffont_size, rtf_style.rtf_rtfstyle); - if (rtf_color == null) { + if (rtf_style.rtf_color == Color.Empty) { System.Windows.Forms.RTF.Color color; // First color in table is default - color = System.Windows.Forms.RTF.Color.GetColor(rtf, 0); + color = System.Windows.Forms.RTF.Color.GetColor (rtf, 0); if ((color == null) || (color.Red == -1 && color.Green == -1 && color.Blue == -1)) { - rtf_color = new SolidBrush(ForeColor); + rtf_style.rtf_color = ForeColor; } else { - rtf_color = new SolidBrush(Color.FromArgb(color.Red, color.Green, color.Blue)); + rtf_style.rtf_color = Color.FromArgb (color.Red, color.Green, color.Blue); } + } rtf_chars += rtf_line.Length; + + if (rtf_cursor_x == 0) { - document.Add(rtf_cursor_y, rtf_line.ToString(), rtf_rtfalign, font, rtf_color); + if (newline && rtf_line.ToString ().EndsWith ("\n") == false) + rtf_line.Append ("\n"); + + document.Add (rtf_cursor_y, rtf_line.ToString (), rtf_style.rtf_rtfalign, font, rtf_style.rtf_color, + newline ? LineEnding.Rich : LineEnding.Wrap); + if (rtf_style.rtf_par_line_left_indent != 0) { + Line line = document.GetLine (rtf_cursor_y); + line.indent = rtf_style.rtf_par_line_left_indent; + } } else { - Line line; + Line line; - line = document.GetLine(rtf_cursor_y); + line = document.GetLine (rtf_cursor_y); + line.indent = rtf_style.rtf_par_line_left_indent; if (rtf_line.Length > 0) { - document.InsertString(line, rtf_cursor_x, rtf_line.ToString()); - document.FormatText(line, rtf_cursor_x + 1, line, rtf_cursor_x + 1 + length, font, rtf_color); // FormatText is 1-based + document.InsertString (line, rtf_cursor_x, rtf_line.ToString ()); + document.FormatText (line, rtf_cursor_x + 1, line, rtf_cursor_x + 1 + length, + font, rtf_style.rtf_color, Color.Empty, + FormatSpecified.Font | FormatSpecified.Color); } if (newline) { - document.Split(line, rtf_cursor_x + length); + document.Split (line, rtf_cursor_x + length); + line = document.GetLine (rtf_cursor_y); + line.ending = LineEnding.Rich; + + if (line.Text.EndsWith ("\n") == false) + line.Text += "\n"; } } @@ -1446,15 +1784,16 @@ namespace System.Windows.Forms { // Prepare rtf.ClassCallback[RTF.TokenClass.Text] = new RTF.ClassDelegate(HandleText); rtf.ClassCallback[RTF.TokenClass.Control] = new RTF.ClassDelegate(HandleControl); + rtf.ClassCallback[RTF.TokenClass.Group] = new RTF.ClassDelegate(HandleGroup); rtf_skip_width = 0; rtf_skip_count = 0; rtf_line = new StringBuilder(); - rtf_color = null; - rtf_rtffont_size = (int)this.Font.Size; - rtf_rtfalign = HorizontalAlignment.Left; - rtf_rtfstyle = FontStyle.Regular; - rtf_rtffont = null; + rtf_style.rtf_color = Color.Empty; + rtf_style.rtf_rtffont_size = (int)this.Font.Size; + rtf_style.rtf_rtfalign = HorizontalAlignment.Left; + rtf_style.rtf_rtfstyle = FontStyle.Regular; + rtf_style.rtf_rtffont = null; rtf_cursor_x = cursor_x; rtf_cursor_y = cursor_y; rtf_chars = 0; @@ -1463,26 +1802,35 @@ namespace System.Windows.Forms { rtf_text_map = new RTF.TextMap(); RTF.TextMap.SetupStandardTable(rtf_text_map.Table); - document.NoRecalc = true; + document.SuspendRecalc (); try { rtf.Read(); // That's it FlushText(rtf, false); + } + catch (RTF.RTFException e) { +#if DEBUG + throw e; +#endif // Seems to be plain text or broken RTF Console.WriteLine("RTF Parsing failure: {0}", e.Message); - } + } to_x = rtf_cursor_x; to_y = rtf_cursor_y; chars = rtf_chars; + // clear the section stack if it was used + if (rtf_section_stack != null) + rtf_section_stack.Clear(); + document.RecalculateDocument(CreateGraphicsInternal(), cursor_y, document.Lines, false); - document.NoRecalc = false; + document.ResumeRecalc (true); - document.Invalidate(document.GetLine(cursor_y), 0, document.GetLine(document.Lines), -1); + document.Invalidate (document.GetLine(cursor_y), 0, document.GetLine(document.Lines), -1); } private void RichTextBox_HScrolled(object sender, EventArgs e) { @@ -1597,8 +1945,8 @@ namespace System.Windows.Forms { // Add default font and color; to optimize document content we don't // use this.Font and this.ForeColor but the font/color from the first tag tag = LineTag.FindTag(start_line, pos); - font = tag.font; - color = ((SolidBrush)tag.color).Color; + font = tag.Font; + color = tag.Color; fonts.Add(font.Name); colors.Add(color); @@ -1613,22 +1961,22 @@ namespace System.Windows.Forms { } while (pos < line_len) { - if (tag.font.Name != font.Name) { - font = tag.font; + if (tag.Font.Name != font.Name) { + font = tag.Font; if (!fonts.Contains(font.Name)) { fonts.Add(font.Name); } } - if (((SolidBrush)tag.color).Color != color) { - color = ((SolidBrush)tag.color).Color; + if (tag.Color != color) { + color = tag.Color; if (!colors.Contains(color)) { colors.Add(color); } } - pos = tag.start + tag.length - 1; - tag = tag.next; + pos = tag.Start + tag.Length - 1; + tag = tag.Next; } pos = 0; line_no++; @@ -1671,10 +2019,10 @@ namespace System.Windows.Forms { // Emit initial paragraph settings tag = LineTag.FindTag(start_line, start_pos); sb.Append("\\pard"); // Reset to default paragraph properties - EmitRTFFontProperties(sb, -1, fonts.IndexOf(tag.font.Name), null, tag.font); // Font properties + EmitRTFFontProperties(sb, -1, fonts.IndexOf(tag.Font.Name), null, tag.Font); // Font properties sb.Append(" "); // Space separator - font = tag.font; + font = tag.Font; color = (Color)colors[0]; line = start_line; line_no = start_line.line_no; @@ -1693,13 +2041,13 @@ namespace System.Windows.Forms { while (pos < line_len) { length = sb.Length; - if (tag.font != font) { - EmitRTFFontProperties(sb, fonts.IndexOf(font.Name), fonts.IndexOf(tag.font.Name), font, tag.font); - font = tag.font; + if (tag.Font != font) { + EmitRTFFontProperties(sb, fonts.IndexOf(font.Name), fonts.IndexOf(tag.Font.Name), font, tag.Font); + font = tag.Font; } - if (((SolidBrush)tag.color).Color != color) { - color = ((SolidBrush)tag.color).Color; + if (tag.Color != color) { + color = tag.Color; sb.Append(String.Format("\\cf{0}", colors.IndexOf(color))); } if (length != sb.Length) { @@ -1708,21 +2056,21 @@ namespace System.Windows.Forms { // Emit the string itself if (line_no != end_line.line_no) { - EmitRTFText(sb, tag.line.text.ToString(pos, tag.start + tag.length - pos - 1)); + EmitRTFText(sb, tag.Line.text.ToString(pos, tag.Start + tag.Length - pos - 1)); } else { - if (end_pos < (tag.start + tag.length - 1)) { + if (end_pos < (tag.Start + tag.Length - 1)) { // Emit partial tag only, end_pos is inside this tag - EmitRTFText(sb, tag.line.text.ToString(pos, end_pos - pos)); + EmitRTFText(sb, tag.Line.text.ToString(pos, end_pos - pos)); } else { - EmitRTFText(sb, tag.line.text.ToString(pos, tag.start + tag.length - pos - 1)); + EmitRTFText(sb, tag.Line.text.ToString(pos, tag.Start + tag.Length - pos - 1)); } } - pos = tag.start + tag.length - 1; - tag = tag.next; + pos = tag.Start + tag.Length - 1; + tag = tag.Next; } if (pos >= line.text.Length) { - if (!line.soft_break) { + if (line.ending != LineEnding.Wrap) { sb.Append("\\par\n"); } }