2005-06-21 Peter Bartok <pbartok@novell.com>
authorPeter Dennis Bartok <pbartok@mono-cvs.ximian.com>
Tue, 21 Jun 2005 22:51:07 +0000 (22:51 -0000)
committerPeter Dennis Bartok <pbartok@mono-cvs.ximian.com>
Tue, 21 Jun 2005 22:51:07 +0000 (22:51 -0000)
* Form.cs: Set focus to active control when form is activated
* TextControl.cs:
  - Added word-wrap functionality to RecalculateLine()
  - Added some short function descriptions for VS.Net to aid in
    writing dependent controls
  - Added Caret property, returning the current coords of the caret
  - Added ViewPortWidth and ViewPortHeight properties
  - Added Wrap property
  - Added CaretMoved event
  - Removed some old debug code
  - Split() can now create soft splits
  - Added PreviousTag()/NextTag() to allow walking "tag-lists"
  - Added method to format existing text
  - Fixed size/alignment calculations to use viewport
  - RecalculateDocument now can handle changing line-numbers while
    calculating lines

* TextBox.cs:
  - Added some wrap logic, we don't wrap if alignment is not left
  - Added casts for scrollbar var, base class switched types to
    also support RichTextBoxA
  - Implemented handling of scrollbar visibility flags

* TextBoxBase.cs:
  - Switched scrollbars type to RichTextBoxScrollBars to support
    RichTextBox
  - Added tracking of canvas width/height
  - Switched scrollbars to be not selectable (to keep focus on text)
  - Added central CalculateDocument() method to handle all redraw
    requirements
  - Added ReadOnly support
  - Added WordWrap support
  - Fixed handling of Enter key (we now treat it as a DialogKey)
  - Fixed caret positioning when h or v scroll is not zero
  - Fixed placing/generation of vertical scrollbar
  - Added CalculateScrollBars() method to allow updating scrollbar
    limits and visibility
  - Fixed handling of horizontal scroll
  - Added handling of vertical scroll
  - Implemented auto-'jump' when caret moves to close to a left or
    right border and there is text to be scrolled into view (currently
    there's the potential for a stack overflow, until a bug in
    scrollbar is fixed)

svn path=/trunk/mcs/; revision=46335

mcs/class/Managed.Windows.Forms/System.Windows.Forms/ChangeLog
mcs/class/Managed.Windows.Forms/System.Windows.Forms/Form.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/TextBox.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/TextBoxBase.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/TextControl.cs

index 2bee177a44d009d0bf32bc25caab0edfbd7c5130..9bc8ce08d7d617c01775e2491e1e0d503ec0d7a3 100644 (file)
@@ -1,3 +1,49 @@
+2005-06-21  Peter Bartok  <pbartok@novell.com>
+
+       * Form.cs: Set focus to active control when form is activated
+       * TextControl.cs: 
+         - Added word-wrap functionality to RecalculateLine() 
+         - Added some short function descriptions for VS.Net to aid in
+           writing dependent controls
+         - Added Caret property, returning the current coords of the caret
+         - Added ViewPortWidth and ViewPortHeight properties
+         - Added Wrap property
+         - Added CaretMoved event
+         - Removed some old debug code
+         - Split() can now create soft splits
+         - Added PreviousTag()/NextTag() to allow walking "tag-lists"
+         - Added method to format existing text
+         - Fixed size/alignment calculations to use viewport
+         - RecalculateDocument now can handle changing line-numbers while
+           calculating lines
+
+       * TextBox.cs:
+         - Added some wrap logic, we don't wrap if alignment is not left
+         - Added casts for scrollbar var, base class switched types to
+           also support RichTextBoxA
+         - Implemented handling of scrollbar visibility flags
+
+       * TextBoxBase.cs:
+         - Switched scrollbars type to RichTextBoxScrollBars to support
+           RichTextBox
+         - Added tracking of canvas width/height
+         - Switched scrollbars to be not selectable (to keep focus on text)
+         - Added central CalculateDocument() method to handle all redraw
+           requirements
+         - Added ReadOnly support
+         - Added WordWrap support
+         - Fixed handling of Enter key (we now treat it as a DialogKey)
+         - Fixed caret positioning when h or v scroll is not zero
+         - Fixed placing/generation of vertical scrollbar
+         - Added CalculateScrollBars() method to allow updating scrollbar
+           limits and visibility
+         - Fixed handling of horizontal scroll
+         - Added handling of vertical scroll
+         - Implemented auto-'jump' when caret moves to close to a left or
+           right border and there is text to be scrolled into view (currently
+           there's the potential for a stack overflow, until a bug in
+           scrollbar is fixed)
+
 2005-06-21  Geoff Norton  <gnorton@customerdna.com>
        
        * XplatUIOSX.cs: Initial implementation of WM_ERASEBKGND
index 44d171f1aaf127b52f193646096e17f032221cd8..d2b04135eb3eca5de7e8a668cd4d47b1277c0ff7 100644 (file)
@@ -1317,11 +1317,10 @@ namespace System.Windows.Forms {
                                }
 
                                case Msg.WM_SETFOCUS: {
-#if not
                                        if (this.ActiveControl != null) {
                                                ActiveControl.Focus();
+                                               return; // FIXME - do we need to run base.WndProc, even though we just changed focus?
                                        }
-#endif
                                        base.WndProc(ref m);
                                        return;
                                }
index f0297e33d79129f7bc0b7759dc5c8bdebf7daf6b..39ad2916211f5df41021a2a6c8fab6d4a99bc275 100644 (file)
@@ -41,7 +41,7 @@ namespace System.Windows.Forms {
                public TextBox() {
                        accepts_return = false;
                        password_char = '\u25cf';
-                       scrollbars = ScrollBars.None;
+                       scrollbars = RichTextBoxScrollBars.None;
                        alignment = HorizontalAlignment.Left;
                        this.LostFocus +=new EventHandler(TextBox_LostFocus);
                        this.BackColor = ThemeEngine.Current.ColorWindow;
@@ -102,12 +102,13 @@ namespace System.Windows.Forms {
                [Localizable(true)]
                public ScrollBars ScrollBars {
                        get {
-                               return scrollbars;
+                               return (ScrollBars)scrollbars;
                        }
 
                        set {
-                               if (value != scrollbars) {
-                                       scrollbars = value;
+                               if (value != (ScrollBars)scrollbars) {
+                                       scrollbars = (RichTextBoxScrollBars)value;
+                                       base.CalculateScrollBars();
                                }
                        }
                }
@@ -144,6 +145,14 @@ namespace System.Windows.Forms {
                        set {
                                if (value != alignment) {
                                        alignment = value;
+
+                                       // MS word-wraps if alignment isn't left
+                                       if (alignment != HorizontalAlignment.Left) {
+                                               document.Wrap = true;
+                                       } else {
+                                               document.Wrap = word_wrap;
+                                       }
+
                                        for (int i = 1; i <= document.Lines; i++) {
                                                document.GetLine(i).Alignment = value;
                                        }
index 31ab6b7898130c8bd39b8b5ef766b4781d434188..974a2fcfa21fc90d08ac5028960a8776e225ca2c 100644 (file)
@@ -54,15 +54,15 @@ namespace System.Windows.Forms {
                internal Document               document;
                internal LineTag                caret_tag;              // tag our cursor is in
                internal int                    caret_pos;              // position on the line our cursor is in (can be 0 = beginning of line)
-               internal int                    viewport_x;             // left visible pixel
-               internal int                    viewport_y;             // top visible pixel
                internal HScrollBar             hscroll;
                internal VScrollBar             vscroll;
-               internal ScrollBars             scrollbars;
+               internal RichTextBoxScrollBars  scrollbars;
                internal bool                   grabbed;
                internal bool                   richtext;
                internal int                    requested_height;
-
+               internal int                    canvas_width;
+               internal int                    canvas_height;
+               internal int                    track_width = 20;
                #if Debug
                internal static bool    draw_lines = false;
                #endif
@@ -87,6 +87,8 @@ namespace System.Windows.Forms {
                        word_wrap = true;
                        richtext = false;
                        document = new Document(this);
+                       //document.CaretMoved += new EventHandler(CaretMoved);
+                       document.Wrap = true;
                        requested_height = -1;
 
                        MouseDown += new MouseEventHandler(TextBoxBase_MouseDown);
@@ -96,14 +98,18 @@ namespace System.Windows.Forms {
                        FontChanged += new EventHandler(TextBoxBase_FontOrColorChanged);
                        ForeColorChanged += new EventHandler(TextBoxBase_FontOrColorChanged);
                        
-                       scrollbars = ScrollBars.None;
+                       scrollbars = RichTextBoxScrollBars.None;
 
                        hscroll = new HScrollBar();
-                       hscroll.ValueChanged +=new EventHandler(hscroll_ValueChanged);
-                       hscroll.Enabled = true;
+                       hscroll.ValueChanged += new EventHandler(hscroll_ValueChanged);
+                       hscroll.control_style &= ~ControlStyles.Selectable;
+                       hscroll.Enabled = false;
                        hscroll.Visible = false;
 
                        vscroll = new VScrollBar();
+                       vscroll.ValueChanged += new EventHandler(vscroll_ValueChanged);
+                       vscroll.control_style &= ~ControlStyles.Selectable;
+                       vscroll.Enabled = false;
                        vscroll.Visible = false;
 
                        this.Controls.Add(hscroll);
@@ -112,6 +118,11 @@ namespace System.Windows.Forms {
                        //SetStyle(ControlStyles.ResizeRedraw, true);
                        SetStyle(ControlStyles.AllPaintingInWmPaint, true);
                        SetStyle(ControlStyles.UserPaint, true);
+
+                       canvas_width = this.Width;
+                       canvas_height = this.Height;
+
+                       CalculateScrollBars();
                }
                #endregion      // Internal Constructor
 
@@ -271,7 +282,7 @@ namespace System.Windows.Forms {
                                for (i = 0; i < l; i++) {
                                        document.Add(i+1, CaseAdjust(value[i]), alignment, Font, brush);
                                }
-                               document.RecalculateDocument(CreateGraphics());
+                               CalculateDocument();
                                OnTextChanged(EventArgs.Empty);
                        }
                }
@@ -361,8 +372,10 @@ namespace System.Windows.Forms {
                        }
 
                        set {
-                               document.ReplaceSelection(CaseAdjust(value));
-                               OnTextChanged(EventArgs.Empty);
+                               if (!read_only) {
+                                       document.ReplaceSelection(CaseAdjust(value));
+                                       OnTextChanged(EventArgs.Empty);
+                               }
                        }
                }
 
@@ -431,14 +444,14 @@ namespace System.Windows.Forms {
                                        for (i = 1; i < document.Lines; i++) {
                                                sb.Append(document.GetLine(i).text.ToString() + Environment.NewLine);
                                        }
-
                                        return sb.ToString();
                                }
                        }
 
                        set {
-                               if (value == base.Text)
+                               if (value == base.Text) {
                                        return;
+                               }
 
                                if (value != null) {
                                        Line    line;
@@ -463,7 +476,7 @@ namespace System.Windows.Forms {
                                        } else {
                                                document.Clear();
                                                document.Add(1, CaseAdjust(value), alignment, Font, ThemeEngine.Current.ResPool.GetSolidBrush(ForeColor));
-                                               document.RecalculateDocument(CreateGraphics());
+                                               CalculateDocument();
                                                line = document.GetLine(1);
                                                document.SetSelectionStart(line, 0);
                                                document.SetSelectionEnd(line, value.Length);
@@ -508,6 +521,7 @@ namespace System.Windows.Forms {
                        set {
                                if (value != word_wrap) {
                                        word_wrap = value;
+                                       document.Wrap = value;
                                }
                        }
                }
@@ -529,7 +543,6 @@ namespace System.Windows.Forms {
 
                #region Public Instance Methods
                public void AppendText(string text) {
-
                        if (multiline) {
                                string[]        lines;
                                int             linecount;
@@ -553,9 +566,8 @@ namespace System.Windows.Forms {
                                        document.Add(document.CaretLine.LineNo+i, CaseAdjust(lines[i]), alignment, document.CaretTag.font, document.CaretTag.color);
                                }
 
-                               document.RecalculateDocument(CreateGraphics());
+                               CalculateDocument();
                                document.MoveCaret(CaretDirection.CtrlEnd);
-                               Invalidate();
                        } else {
                                document.MoveCaret(CaretDirection.CtrlEnd);
                                document.InsertStringAtCaret(text, true);
@@ -639,12 +651,15 @@ namespace System.Windows.Forms {
 
                protected override bool IsInputKey(Keys keyData) {
                        switch (keyData) {
+#if not
+                               // We handle Enter in ProcessDialogKey
                                case Keys.Enter: {
                                        if (multiline && (accepts_return || ((keyData & Keys.Control) != 0))) {
                                                return true;
                                        }
                                        return false;
                                }
+#endif
 
                                case Keys.Tab: {
                                        if (accepts_tab) {
@@ -727,6 +742,7 @@ namespace System.Windows.Forms {
                                        } else {
                                                document.MoveCaret(CaretDirection.CharBack);
                                        }
+                                       CaretMoved(this, null);
                                        return true;
                                }
 
@@ -738,18 +754,21 @@ namespace System.Windows.Forms {
                                        } else {
                                                document.MoveCaret(CaretDirection.CharForward);
                                        }
+                                       CaretMoved(this, null);
                                        return true;
                                }
 
                                case Keys.Up: {
                                        document.SetSelectionToCaret(true);
                                        document.MoveCaret(CaretDirection.LineUp);
+                                       CaretMoved(this, null);
                                        return true;
                                }
 
                                case Keys.Down: {
                                        document.SetSelectionToCaret(true);
                                        document.MoveCaret(CaretDirection.LineDown);
+                                       CaretMoved(this, null);
                                        return true;
                                }
 
@@ -761,6 +780,7 @@ namespace System.Windows.Forms {
                                        } else {
                                                document.MoveCaret(CaretDirection.Home);
                                        }
+                                       CaretMoved(this, null);
                                        return true;
                                }
 
@@ -772,27 +792,33 @@ namespace System.Windows.Forms {
                                        } else {
                                                document.MoveCaret(CaretDirection.End);
                                        }
+                                       CaretMoved(this, null);
                                        return true;
                                }
 
                                case Keys.Enter: {
-                                       if (multiline && (accepts_return || ((Control.ModifierKeys & Keys.Control) != 0))) {
+                                       if (!read_only && multiline && (accepts_return || ((Control.ModifierKeys & Keys.Control) != 0))) {
+                                               Line    line;
+
                                                if (document.selection_visible) {
                                                        document.ReplaceSelection("");
                                                }
                                                document.SetSelectionToCaret(true);
 
-                                               document.Split(document.CaretLine, document.CaretTag, document.CaretPosition);
+                                               line = document.CaretLine;
+
+                                               document.Split(document.CaretLine, document.CaretTag, document.CaretPosition, false);
                                                OnTextChanged(EventArgs.Empty);
-                                               document.UpdateView(document.CaretLine, 2, 0);
+                                               document.UpdateView(line, 2, 0);
                                                document.MoveCaret(CaretDirection.CharForward);
+                                               CaretMoved(this, null);
                                                return true;
                                        }
                                        break;
                                }
 
                                case Keys.Tab: {
-                                       if (accepts_tab) {
+                                       if (!read_only && accepts_tab) {
                                                document.InsertChar(document.CaretLine, document.CaretPosition, '\t');
                                                if (document.selection_visible) {
                                                        document.ReplaceSelection("");
@@ -800,6 +826,7 @@ namespace System.Windows.Forms {
                                                document.SetSelectionToCaret(true);
 
                                                OnTextChanged(EventArgs.Empty);
+                                               CaretMoved(this, null);
                                                return true;
                                        }
                                        break;
@@ -807,6 +834,10 @@ namespace System.Windows.Forms {
 
 
                                case Keys.Back: {
+                                       if (read_only) {
+                                               break;
+                                       }
+
                                        // delete only deletes on the line, doesn't do the combine
                                        if (document.selection_visible) {
                                                document.ReplaceSelection("");
@@ -831,10 +862,15 @@ namespace System.Windows.Forms {
                                                document.MoveCaret(CaretDirection.CharBack);
                                                OnTextChanged(EventArgs.Empty);
                                        }
+                                       CaretMoved(this, null);
                                        return true;
                                }
 
                                case Keys.Delete: {
+                                       if (read_only) {
+                                               break;
+                                       }
+
                                        // delete only deletes on the line, doesn't do the combine
                                        if (document.CaretPosition == document.CaretLine.text.Length) {
                                                if (document.CaretLine.LineNo < document.Lines) {
@@ -861,6 +897,7 @@ namespace System.Windows.Forms {
                                                document.DeleteChar(document.CaretTag, document.CaretPosition, true);
                                                OnTextChanged(EventArgs.Empty);
                                        }
+                                       CaretMoved(this, null);
                                        return true;
                                }
                        }
@@ -879,6 +916,11 @@ namespace System.Windows.Forms {
                                }
                        }
 
+                       document.ViewPortWidth = this.Width;
+                       document.ViewPortHeight = this.Height;
+
+                       CalculateDocument();
+
                        base.SetBoundsCore (x, y, width, height, specified);
                }
 
@@ -924,7 +966,7 @@ Console.WriteLine("Destroying caret");
                                                return;
                                        }
 
-                                       if (m.WParam.ToInt32() >= 32) { // FIXME, tabs should probably go through
+                                       if (!read_only && (m.WParam.ToInt32() >= 32)) { // FIXME, tabs should probably go through
                                                if (document.selection_visible) {
                                                        document.ReplaceSelection("");
                                                }
@@ -933,18 +975,21 @@ Console.WriteLine("Destroying caret");
                                                        case CharacterCasing.Normal: {
                                                                document.InsertCharAtCaret((char)m.WParam, true);
                                                                OnTextChanged(EventArgs.Empty);
+                                                               CaretMoved(this, null);
                                                                return;
                                                        }
 
                                                        case CharacterCasing.Lower: {
                                                                document.InsertCharAtCaret(Char.ToLower((char)m.WParam), true);
                                                                OnTextChanged(EventArgs.Empty);
+                                                               CaretMoved(this, null);
                                                                return;
                                                        }
 
                                                        case CharacterCasing.Upper: {
                                                                document.InsertCharAtCaret(Char.ToUpper((char)m.WParam), true);
                                                                OnTextChanged(EventArgs.Empty);
+                                                               CaretMoved(this, null);
                                                                return;
                                                        }
                                                }
@@ -1000,7 +1045,7 @@ static int current;
                private void PaintControl(PaintEventArgs pevent) {
                        // Fill background
                        pevent.Graphics.FillRectangle(ThemeEngine.Current.ResPool.GetSolidBrush(BackColor), pevent.ClipRectangle);
-                       //pevent.Graphics.TextRenderingHint=TextRenderingHint.AntiAlias;
+                       pevent.Graphics.TextRenderingHint=TextRenderingHint.AntiAlias;
 
                        // Draw the viewable document
                        document.Draw(pevent.Graphics, pevent.ClipRectangle);
@@ -1008,22 +1053,7 @@ static int current;
                        Rectangle       rect = ClientRectangle;
                        rect.Width--;
                        rect.Height--;
-                       pevent.Graphics.DrawRectangle(ThemeEngine.Current.ResPool.GetPen(ThemeEngine.Current.ColorButtonShadow), rect);
-
-                       // Set the scrollbar
-                       switch (scrollbars) {
-                               case ScrollBars.Both: {
-                                       break;
-                               }
-                               case ScrollBars.Vertical: {
-                                       break;
-                               }
-                               case ScrollBars.Horizontal: {
-                                       hscroll.Minimum = 0;
-                                       hscroll.Maximum = document.Width - this.Width;
-                                       break;
-                               }
-                       }
+                       //pevent.Graphics.DrawRectangle(ThemeEngine.Current.ResPool.GetPen(ThemeEngine.Current.ColorButtonShadow), rect);
 
                        #if Debug
                                int             start;
@@ -1035,8 +1065,8 @@ static int current;
                                p = new Pen(Color.Red, 1);
 
                                // First, figure out from what line to what line we need to draw
-                               start = document.GetLineByPixel(pevent.ClipRectangle.Top - viewport_y, false).line_no;
-                               end = document.GetLineByPixel(pevent.ClipRectangle.Bottom - viewport_y, false).line_no;
+                               start = document.GetLineByPixel(pevent.ClipRectangle.Top - document.ViewPortY, false).line_no;
+                               end = document.GetLineByPixel(pevent.ClipRectangle.Bottom - document.ViewPortY, false).line_no;
 
                                //Console.WriteLine("Starting drawing on line '{0}'", document.GetLine(start));
                                //Console.WriteLine("Ending drawing on line '{0}'", document.GetLine(end));
@@ -1082,7 +1112,7 @@ static int current;
                                        return;
                                }
 
-                               tag = document.FindTag(e.X, e.Y, out pos, false);
+                               tag = document.FindTag(e.X + document.ViewPortX, e.Y + document.ViewPortY, out pos, false);
 
                                Console.WriteLine("Click found tag {0}, character {1}", tag, pos);
                                line = tag.line;
@@ -1111,7 +1141,7 @@ static int current;
                        this.Capture = false;
                        this.grabbed = false;
                        if (e.Button == MouseButtons.Left) {
-                               document.PositionCaret(e.X + viewport_x, e.Y + viewport_y);
+                               document.PositionCaret(e.X, e.Y);
                                document.SetSelectionToCaret(false);
                                document.DisplayCaret();
                                return;
@@ -1121,24 +1151,84 @@ static int current;
 
 
                private void TextBoxBase_SizeChanged(object sender, EventArgs e) {
-
-                       // First, check which scrollbars we need
-                       
+                       canvas_width = this.Width;
+                       canvas_height = this.Height;
+                       // We always move them, they just might not be displayed
                        hscroll.Bounds = new Rectangle (ClientRectangle.Left, ClientRectangle.Bottom - hscroll.Height, Width, hscroll.Height);
+                       vscroll.Bounds = new Rectangle (ClientRectangle.Right - vscroll.Width, ClientRectangle.Top, vscroll.Width, Height);
                        
                }
 
+               private void CalculateDocument() {
+                       document.RecalculateDocument(CreateGraphics());
+                       CalculateScrollBars();
+                       Invalidate();   // FIXME - do we need this?
+               }
+
+               protected void CalculateScrollBars() {
+                       // No scrollbars for a single line
+                       if (document.Width >= this.Width) {
+                               hscroll.Enabled = true;
+                               hscroll.Minimum = 0;
+                               hscroll.Maximum = document.Width - this.Width;
+                       } else {
+                               hscroll.Enabled = false;
+                       }
+
+                       if (document.Height >= this.Height) {
+                               vscroll.Enabled = true;
+                               vscroll.Minimum = 0;
+                               vscroll.Maximum = document.Height - this.Height;
+                       } else {
+                               vscroll.Enabled = false;
+                       }
+
+
+                       if (!multiline) {
+                               return;
+                       }
+
+                       if ((scrollbars & RichTextBoxScrollBars.Horizontal) != 0) {
+                               if (((scrollbars & RichTextBoxScrollBars.ForcedHorizontal) != 0) || hscroll.Enabled) {
+                                       hscroll.Visible = true;
+                               }
+                       }
+
+                       if ((scrollbars & RichTextBoxScrollBars.Vertical) != 0) {
+                               if (((scrollbars & RichTextBoxScrollBars.ForcedVertical) != 0) || vscroll.Enabled) {
+                                       vscroll.Visible = true;
+                               }
+                       }
+
+                       if (hscroll.Visible) {
+                               vscroll.Maximum += hscroll.Height * 2;
+                               canvas_height = this.Height - hscroll.Height * 2;
+                       }
+
+                       if (vscroll.Visible) {
+                               hscroll.Maximum += vscroll.Width * 2;
+                               canvas_width = this.Width - vscroll.Width * 2;
+                       }
+               }
+
                private void hscroll_ValueChanged(object sender, EventArgs e) {
                        XplatUI.ScrollWindow(this.Handle, document.ViewPortX-this.hscroll.Value, 0, false);
                        document.ViewPortX = this.hscroll.Value;
                        document.UpdateCaret();
-                       Console.WriteLine("Dude scrolled");
+                       Console.WriteLine("Dude scrolled horizontal");
                }
 
+               private void vscroll_ValueChanged(object sender, EventArgs e) {\r
+                       XplatUI.ScrollWindow(this.Handle, 0, document.ViewPortY-this.vscroll.Value, false);
+                       document.ViewPortX = this.vscroll.Value;
+                       document.UpdateCaret();
+                       Console.WriteLine("Dude scrolled vertical");
+               }\r
+
                private void TextBoxBase_MouseMove(object sender, MouseEventArgs e) {
                        // FIXME - handle auto-scrolling if mouse is to the right/left of the window
                        if (grabbed) {
-                               document.PositionCaret(e.X + viewport_x, e.Y + viewport_y);
+                               document.PositionCaret(e.X, e.Y);
                                document.SetSelectionToCaret(false);
                                document.DisplayCaret();
                        }
@@ -1157,6 +1247,61 @@ static int current;
                                // Make sure the caret height is matching the new font height
                                document.AlignCaret();
                        }
-               }
+               }\r
+\r
+               /// <summary>Ensure the caret is always visible</summary>\r
+               internal void CaretMoved(object sender, EventArgs e) {\r
+                       Point   pos;\r
+                       \r
+                       pos = document.Caret;\r
+                       Console.WriteLine("Caret now at {0} (Thumb: {1}x{2}, Canvas: {3}x{4}, Document {5}x{6})", pos, hscroll.Value, vscroll.Value, canvas_width, canvas_height, document.Width, document.Height);\r
+\r
+                       // Handle horizontal scrolling\r
+                       if (pos.X < (document.ViewPortX + track_width)) {\r
+                               if ((hscroll.Value - track_width) >= hscroll.Minimum) {\r
+                                       hscroll.Value -= track_width;\r
+                               } else {\r
+                                       hscroll.Value = hscroll.Minimum;\r
+                               }\r
+                       }\r
+\r
+                       if ((pos.X > (this.Width + document.ViewPortX - track_width)) && (hscroll.Value != hscroll.Maximum)) {\r
+                               if ((hscroll.Value + track_width) <= hscroll.Maximum) {\r
+                                       hscroll.Value += track_width;\r
+                               } else {\r
+                                       hscroll.Value = hscroll.Maximum;\r
+                               }\r
+                       }\r
+\r
+                       if (!multiline) {\r
+                               return;\r
+                       }\r
+#if not\r
+                       // Handle vertical scrolling\r
+                       if (pos.Y < (document.ViewPortY + track_width)) {\r
+                               if ((hscroll.Value - track_width) >= hscroll.Minimum) {\r
+                                       hscroll.Value -= track_width;\r
+                               } else {\r
+                                       hscroll.Value = hscroll.Minimum;\r
+                               }\r
+\r
+                               if (pos.X > this.Width + document.ViewPortX) {\r
+                                       hscroll.Value = hscroll.Minimum;\r
+                               }\r
+                       }\r
+\r
+                       if (pos.X > (this.Width + document.ViewPortX - track_width)) {\r
+                               if ((hscroll.Value + track_width) <= hscroll.Maximum) {\r
+                                       hscroll.Value += track_width;\r
+                               } else {\r
+                                       hscroll.Value = hscroll.Maximum;\r
+                               }\r
+                       }\r
+\r
+                       if (pos.X < document.ViewPortX) {\r
+                               hscroll.Value = hscroll.Minimum;\r
+                       }\r
+#endif\r
+               }\r
        }
 }
index d685ac509d368927514969fddfd3a0625f50f606..d4638edfd86387b4a12563ee0c76ef87ebd655ca 100644 (file)
@@ -17,7 +17,7 @@
 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
-// Copyright (c) 2004 Novell, Inc. (http://www.novell.com)
+// Copyright (c) 2004-2005 Novell, Inc. (http://www.novell.com)
 //
 // Authors:
 //     Peter Bartok    pbartok@novell.com
@@ -80,6 +80,8 @@ namespace System.Windows.Forms {
                internal int                    ascent;                 // Ascent of the line (ascent of the tallest tag)
                internal HorizontalAlignment    alignment;              // Alignment of the line
                internal int                    align_shift;            // Pixel shift caused by the alignment
+               internal bool                   soft_break;             // Tag is 'broken soft' and continuation from previous line
+
 
                // Stuff that's important for the tree
                internal Line                   parent;                 // Our parent line
@@ -99,6 +101,7 @@ namespace System.Windows.Forms {
                        parent = null;
                        text = null;
                        recalc = true;
+                       soft_break = false;
                        alignment = HorizontalAlignment.Left;
 
                        if (string_format == null) {
@@ -265,7 +268,7 @@ namespace System.Windows.Forms {
                        }
                }
 
-               // Find the tag on a line based on the character position
+               /// <summary> Find the tag on a line based on the character position</summary>
                internal LineTag FindTag(int pos) {
                        LineTag tag;
 
@@ -289,17 +292,22 @@ namespace System.Windows.Forms {
                }
 
 
-               //
-               // Go through all tags on a line and recalculate all size-related values
-               // returns true if lineheight changed
-               //
-               internal bool RecalculateLine(Graphics g) {
+               /// <summary>
+               /// Go through all tags on a line and recalculate all size-related values;
+               /// returns true if lineheight changed
+               /// </summary>
+               internal bool RecalculateLine(Graphics g, Document doc) {
                        LineTag tag;
                        int     pos;
                        int     len;
                        SizeF   size;
                        float   w;
                        int     prev_height;
+                       bool    retval;
+                       bool    wrapped;
+                       Line    line;
+                       int     wrap_pos;
+                       float   wrap_width;
 
                        pos = 0;
                        len = this.text.Length;
@@ -311,17 +319,51 @@ namespace System.Windows.Forms {
                        tag.width = 0;
                        widths[0] = 0;
                        this.recalc = false;
+                       retval = false;
+                       wrapped = false;
+
+                       wrap_pos = 0;
+                       wrap_width = 0;
 
                        while (pos < len) {
                                size = g.MeasureString(this.text.ToString(pos, 1), tag.font, 10000, string_format);
 
                                w = size.Width;
 
-                               tag.width += w;
+                               if (Char.IsWhiteSpace(text[pos])) {
+                                       wrap_pos = pos + 1;
+                                       wrap_width = tag.width + w;
+                               }
 
-                               pos++;
+                               if (doc.wrap) {
+                                       if ((widths[pos] + w) + 27 > doc.viewport_width) {
+                                               pos = wrap_pos;
+                                               tag.width = wrap_width;
+                                               doc.Split(this, tag, pos, true);
+                                               len = this.text.Length;
+                                               retval = true;
+                                               wrapped = true;
+                                       }
+                               }
 
-                               widths[pos] = widths[pos-1] + w;
+                               // Contract all soft lines that follow back into our line
+                               if (!wrapped) {
+                                       tag.width += w;
+
+                                       pos++;
+
+                                       widths[pos] = widths[pos-1] + w;
+
+                                       if (pos == len) {
+                                               line = doc.GetLine(this.line_no + 1);
+                                               if ((line != null) && (line.soft_break)) {
+                                                       // Pull the previous line back into this one
+                                                       doc.Combine(this.line_no, this.line_no + 1);
+                                                       len = this.text.Length;
+                                                       retval = true;
+                                               }
+                                       }
+                               }
 
                                if (pos == (tag.start-1 + tag.length)) {
                                        // We just found the end of our current tag
@@ -366,6 +408,8 @@ namespace System.Windows.Forms {
                                        if (tag != null) {
                                                tag.width = 0;
                                                tag.shift = 0;
+                                               wrap_pos = pos;
+                                               wrap_width = tag.width;
                                        }
                                }
                        }
@@ -376,9 +420,9 @@ namespace System.Windows.Forms {
                        }
 
                        if (prev_height != this.height) {
-                               return true;
+                               retval = true;
                        }
-                       return false;
+                       return retval;
                }
                #endregion      // Internal Methods
 
@@ -488,6 +532,8 @@ namespace System.Windows.Forms {
 
                internal int            viewport_x;
                internal int            viewport_y;             // The visible area of the document
+               internal int            viewport_width;
+               internal int            viewport_height;
 
                internal int            document_x;             // Width of the document
                internal int            document_y;             // Height of the document
@@ -560,6 +606,12 @@ namespace System.Windows.Forms {
                        }
                }
 
+               internal Point Caret {
+                       get {
+                               return new Point((int)caret.tag.line.widths[caret.pos] + caret.line.align_shift, caret.line.Y + caret.tag.shift);
+                       }
+               }
+
                internal LineTag CaretTag {
                        get {
                                return caret.tag;
@@ -586,6 +638,27 @@ namespace System.Windows.Forms {
                        }
                }
 
+               internal int ViewPortWidth {
+                       get {
+                               return viewport_width;
+                       }
+
+                       set {
+                               viewport_width = value;
+                       }
+               }
+
+               internal int ViewPortHeight {
+                       get {
+                               return viewport_height;
+                       }
+
+                       set {
+                               viewport_height = value;
+                       }
+               }
+
+
                internal int Width {
                        get {
                                return this.document_x;
@@ -598,6 +671,17 @@ namespace System.Windows.Forms {
                        }
                }
 
+               internal bool Wrap {
+                       get {
+                               return wrap;
+                       }
+
+                       set {
+                               wrap = value;
+                               // FIXME - force recalc/redisplay
+                       }
+               }
+
                #endregion      // Internal Properties
 
                #region Private Methods
@@ -849,13 +933,13 @@ namespace System.Windows.Forms {
                                // Lineheight changed, invalidate the rest of the document
                                if ((line.Y - viewport_y) >=0 ) {
                                        // We formatted something that's in view, only draw parts of the screen
-                                       owner.Invalidate(new Rectangle(0, line.Y - viewport_y, owner.Width, owner.Height - line.Y - viewport_y));
+                                       owner.Invalidate(new Rectangle(0, line.Y - viewport_y, viewport_width, owner.Height - line.Y - viewport_y));
                                } else {
                                        // The tag was above the visible area, draw everything
                                        owner.Invalidate();
                                }
                        } else {
-                               owner.Invalidate(new Rectangle((int)line.widths[pos] - viewport_x - 1, line.Y - viewport_y, (int)owner.Width, line.height));
+                               owner.Invalidate(new Rectangle((int)line.widths[pos] - viewport_x - 1, line.Y - viewport_y, viewport_width, line.height));
                        }
                }
 
@@ -866,7 +950,7 @@ namespace System.Windows.Forms {
                                // Lineheight changed, invalidate the rest of the document
                                if ((line.Y - viewport_y) >=0 ) {
                                        // We formatted something that's in view, only draw parts of the screen
-                                       owner.Invalidate(new Rectangle(0, line.Y - viewport_y, owner.Width, owner.Height - line.Y - viewport_y));
+                                       owner.Invalidate(new Rectangle(0, line.Y - viewport_y, viewport_width, owner.Height - line.Y - viewport_y));
                                } else {
                                        // The tag was above the visible area, draw everything
                                        owner.Invalidate();
@@ -903,8 +987,8 @@ namespace System.Windows.Forms {
                        selection_end.line = this.document;
                        selection_end.pos = 0;
 
-                       viewport_x = -2;
-                       viewport_y = -2;
+                       viewport_x = 0;
+                       viewport_y = 0;
 
                        document_x = 0;
                        document_y = 0;
@@ -919,6 +1003,8 @@ namespace System.Windows.Forms {
                        XplatUI.DestroyCaret(owner.Handle);
                        XplatUI.CreateCaret(owner.Handle, 2, caret.height);
                        XplatUI.SetCaretPos(owner.Handle, (int)caret.tag.line.widths[caret.pos] + caret.line.align_shift - viewport_x, caret.line.Y + caret.tag.shift - viewport_y);
+
+                       if (CaretMoved != null) CaretMoved(this, EventArgs.Empty);
                }
 
                internal void PositionCaret(int x, int y) {
@@ -929,6 +1015,8 @@ namespace System.Windows.Forms {
                        XplatUI.DestroyCaret(owner.Handle);
                        XplatUI.CreateCaret(owner.Handle, 2, caret.height);
                        XplatUI.SetCaretPos(owner.Handle, (int)caret.tag.line.widths[caret.pos] + caret.line.align_shift - viewport_x, caret.line.Y + caret.tag.shift - viewport_y);
+
+                       if (CaretMoved != null) CaretMoved(this, EventArgs.Empty);
                }
 
                internal void CaretHasFocus() {
@@ -950,6 +1038,8 @@ namespace System.Windows.Forms {
                        XplatUI.CreateCaret(owner.Handle, 2, caret.height);
                        XplatUI.SetCaretPos(owner.Handle, (int)caret.tag.line.widths[caret.pos] + caret.line.align_shift - viewport_x, caret.line.Y + caret.tag.shift - viewport_y);
                        XplatUI.CaretVisible(owner.Handle, true);
+
+                       if (CaretMoved != null) CaretMoved(this, EventArgs.Empty);
                }
 
                internal void UpdateCaret() {
@@ -959,6 +1049,8 @@ namespace System.Windows.Forms {
                        }
                        XplatUI.SetCaretPos(owner.Handle, (int)caret.tag.line.widths[caret.pos] + caret.line.align_shift - viewport_x, caret.line.Y + caret.tag.shift - viewport_y);
                        XplatUI.CaretVisible(owner.Handle, true);
+
+                       if (CaretMoved != null) CaretMoved(this, EventArgs.Empty);
                }
 
                internal void DisplayCaret() {
@@ -1542,23 +1634,41 @@ namespace System.Windows.Forms {
 
                        line = GetLine(LineNo);
                        tag = LineTag.FindTag(line, pos);
-                       Split(line, tag, pos);
+                       Split(line, tag, pos, false);
                }
 
                internal void Split(Line line, int pos) {
                        LineTag tag;
 
                        tag = LineTag.FindTag(line, pos);
-                       Split(line, tag, pos);
+                       Split(line, tag, pos, false);
                }
 
-               internal void Split(Line line, LineTag tag, int pos) {
+               internal void Split(Line line, LineTag tag, int pos, bool soft) {
                        LineTag new_tag;
                        Line    new_line;
+                       bool    move_caret;
+
+                       move_caret = false;
+
+                       // Adjust selection and cursors
+                       if (soft && (caret.line == line) && (caret.pos >= pos)) {
+                               move_caret = true;
+                       }
 
                        // cover the easy case first
                        if (pos == line.text.Length) {
                                Add(line.line_no + 1, "", line.alignment, tag.font, tag.color);
+                               if (soft) {
+                                       if (move_caret) {
+                                               caret.line = GetLine(line.line_no + 1);
+                                               caret.line.soft_break = true;
+                                               caret.tag = selection_start.line.tags;
+                                               caret.pos = 0;
+                                       } else {
+                                               GetLine(line.line_no + 1).soft_break = true;
+                                       }
+                               }
                                return;
                        }
 
@@ -1619,6 +1729,16 @@ namespace System.Windows.Forms {
 
                                }
                        }
+
+                       if (soft) {
+                               if (move_caret) {
+                                       caret.line = new_line;
+                                       caret.pos = caret.pos - pos;
+                                       caret.tag = caret.line.FindTag(caret.pos);
+                               }
+                               new_line.soft_break = true;
+                       }
+
                        line.text.Remove(pos, line.text.Length - pos);
                }
 
@@ -1744,6 +1864,7 @@ namespace System.Windows.Forms {
                                line1.text = line3.text;
                                line1.widths = line3.widths;
                                line1.Y = line3.Y;
+                               line1.soft_break = line3.soft_break;
 
                                tag = line1.tags;
                                while (tag != null) {
@@ -1801,18 +1922,18 @@ namespace System.Windows.Forms {
 
                        // Three invalidates:
                        // First line from start
-                       owner.Invalidate(new Rectangle((int)l1.widths[p1] - viewport_x, l1.Y - viewport_y, owner.Width, l1.height));
+                       owner.Invalidate(new Rectangle((int)l1.widths[p1] - viewport_x, l1.Y - viewport_y, viewport_width, l1.height));
 
                        // lines inbetween
                        if ((l1.line_no + 1) < l2.line_no) {
                                int     y;
 
                                y = GetLine(l1.line_no + 1).Y;
-                               owner.Invalidate(new Rectangle(0 - viewport_x, y - viewport_y, owner.Width, GetLine(l2.line_no - 1).Y - y - viewport_y));
+                               owner.Invalidate(new Rectangle(0 - viewport_x, y - viewport_y, viewport_width, GetLine(l2.line_no - 1).Y - y - viewport_y));
                        }
 
                        // Last line to end
-                       owner.Invalidate(new Rectangle((int)l1.widths[p1] - viewport_x, l1.Y - viewport_y, owner.Width, l1.height));
+                       owner.Invalidate(new Rectangle((int)l1.widths[p1] - viewport_x, l1.Y - viewport_y, viewport_width, l1.height));
 
 
                }
@@ -2201,7 +2322,7 @@ if (end != null) {
                }
 
 
-               // Give it a Line number and it returns the Line object at with that line number
+               /// <summary>Give it a Line number and it returns the Line object at with that line number</summary>
                internal Line GetLine(int LineNo) {
                        Line    line = document;
 
@@ -2218,8 +2339,51 @@ if (end != null) {
                        return null;
                }
 
-               // Give it a Y pixel coordinate and it returns the Line covering that Y coordinate
-               ///
+               /// <summary>Retrieve the previous tag; walks line boundaries</summary>\r
+               internal LineTag PreviousTag(LineTag tag) {\r
+                       Line l; \r
+\r
+                       if (tag.previous != null) {\r
+                               return tag.previous;\r
+                       }\r
+\r
+                       // Next line \r
+                       if (tag.line.line_no == 1) {\r
+                               return null;\r
+                       }\r
+\r
+                       l = GetLine(tag.line.line_no - 1);\r
+                       if (l != null) {\r
+                               LineTag t;\r
+\r
+                               t = l.tags;\r
+                               while (t.next != null) {\r
+                                       t = t.next;\r
+                               }\r
+                               return t;\r
+                       }\r
+\r
+                       return null;\r
+               }\r
+\r
+               /// <summary>Retrieve the next tag; walks line boundaries</summary>\r
+               internal LineTag NextTag(LineTag tag) {\r
+                       Line l;\r
+\r
+                       if (tag.next != null) {\r
+                               return tag.next;\r
+                       }\r
+\r
+                       // Next line\r
+                       l = GetLine(tag.line.line_no + 1);\r
+                       if (l != null) {\r
+                               return l.tags;\r
+                       }\r
+\r
+                       return null;\r
+               }\r
+
+               /// <summary>Give it a Y pixel coordinate and it returns the Line covering that Y coordinate</summary>
                internal Line GetLineByPixel(int y, bool exact) {
                        Line    line = document;
                        Line    last = null;
@@ -2322,6 +2486,24 @@ if (end != null) {
                        }
                }
 
+               internal void FormatText(Line start_line, int start_pos, Line end_line, int end_pos, Font font, Brush color) {\r
+                       Line    l;\r
+\r
+                       // First, format the first line\r
+                       LineTag.FormatText(start_line, start_pos, start_line.text.Length - start_pos, font, color);\r
+\r
+                       // Format last line\r
+                       if (end_line != start_line) {\r
+                               LineTag.FormatText(end_line, 0, end_pos, font, color);\r
+                       }\r
+\r
+                       // Now all the lines inbetween\r
+                       for (int i = start_line.line_no + 1; i < end_line.line_no - 1; i++) {\r
+                               l = GetLine(i);\r
+                               LineTag.FormatText(l, 0, l.text.Length, font, color);\r
+                       }\r
+               }\r
+
                internal void RecalculateAlignments() {
                        Line    line;
                        int     line_no;
@@ -2333,9 +2515,9 @@ if (end != null) {
 
                                if (line.alignment != HorizontalAlignment.Left) {
                                        if (line.alignment == HorizontalAlignment.Center) {
-                                               line.align_shift = (document_x - (int)line.widths[line.text.Length]) / 2;
+                                               line.align_shift = (viewport_width - (int)line.widths[line.text.Length]) / 2;
                                        } else {
-                                               line.align_shift = document_x - (int)line.widths[line.text.Length];
+                                               line.align_shift = viewport_width - (int)line.widths[line.text.Length];
                                        }
                                }
 
@@ -2344,22 +2526,22 @@ if (end != null) {
                        return;
                }
 
-               // Calculate formatting for the whole document
+               /// <summary>Calculate formatting for the whole document</summary>
                internal bool RecalculateDocument(Graphics g) {
                        return RecalculateDocument(g, 1, this.lines, false);
                }
 
-               // Calculate formatting starting at a certain line
+               /// <summary>Calculate formatting starting at a certain line</summary>
                internal bool RecalculateDocument(Graphics g, int start) {
                        return RecalculateDocument(g, start, this.lines, false);
                }
 
-               // Calculate formatting within two given line numbers
+               /// <summary>Calculate formatting within two given line numbers</summary>
                internal bool RecalculateDocument(Graphics g, int start, int end) {
                        return RecalculateDocument(g, start, end, false);
                }
 
-               // With optimize on, returns true if line heights changed
+               /// <summary>With optimize on, returns true if line heights changed</summary>
                internal bool RecalculateDocument(Graphics g, int start, int end, bool optimize) {
                        Line    line;
                        int     line_no;
@@ -2372,13 +2554,13 @@ if (end != null) {
                                bool    alignment_recalc;
 
                                changed = false;
-                               alignment_recalc = false;
+                               alignment_recalc = true;
 
                                while (line_no <= end) {
                                        line = GetLine(line_no++);
                                        line.Y = Y;
                                        if (line.recalc) {
-                                               if (line.RecalculateLine(g)) {
+                                               if (line.RecalculateLine(g, this)) {
                                                        changed = true;
                                                        // If the height changed, all subsequent lines change
                                                        end = this.lines;
@@ -2392,26 +2574,45 @@ if (end != null) {
                                                // Calculate alignment
                                                if (line.alignment != HorizontalAlignment.Left) {
                                                        if (line.alignment == HorizontalAlignment.Center) {
-                                                               line.align_shift = (document_x - (int)line.widths[line.text.Length]) / 2;
+                                                               line.align_shift = (viewport_width - (int)line.widths[line.text.Length]) / 2;
                                                        } else {
-                                                               line.align_shift = document_x - (int)line.widths[line.text.Length];
+                                                               line.align_shift = viewport_width - (int)line.widths[line.text.Length];
                                                        }
                                                }
                                        }
 
                                        Y += line.height;
+
+                                       if (line_no > lines) {
+                                               break;
+                                       }
                                }
 
                                if (alignment_recalc) {
                                        RecalculateAlignments();
                                }
 
+                               line = GetLine(lines);
+                               document_y = line.Y + line.height;
+
                                return changed;
                        } else {
-                               while (line_no <= end) {
+                               int     shift;
+
+                               shift = 0;
+
+                               while (line_no <= (end + shift)) {
                                        line = GetLine(line_no++);
                                        line.Y = Y;
-                                       line.RecalculateLine(g);
+
+                                       shift = this.lines;
+                                       line.RecalculateLine(g, this);
+                                       if (this.lines > shift) {
+                                               shift = this.lines - shift;
+                                       } else {
+                                               shift = 0;
+                                       }
+
                                        if (line.widths[line.text.Length] > this.document_x) {
                                                this.document_x = (int)line.widths[line.text.Length];
                                        }
@@ -2419,15 +2620,23 @@ if (end != null) {
                                        // Calculate alignment
                                        if (line.alignment != HorizontalAlignment.Left) {
                                                if (line.alignment == HorizontalAlignment.Center) {
-                                                       line.align_shift = (document_x - (int)line.widths[line.text.Length]) / 2;
+                                                       line.align_shift = (viewport_width - (int)line.widths[line.text.Length]) / 2;
                                                } else {
-                                                       line.align_shift = document_x - (int)line.widths[line.text.Length];
+                                                       line.align_shift = viewport_width - (int)line.widths[line.text.Length];
                                                }
                                        }
 
                                        Y += line.height;
+
+                                       if (line_no > lines) {
+                                               break;
+                                       }
                                }
                                RecalculateAlignments();
+
+                               line = GetLine(lines);
+                               document_y = line.Y + line.height;
+
                                return true;
                        }
                }
@@ -2441,6 +2650,10 @@ if (end != null) {
                }
                #endregion      // Internal Methods
 
+               #region Events
+               internal event EventHandler CaretMoved;
+               #endregion      // Events
+
                #region Administrative
                public IEnumerator GetEnumerator() {
                        // FIXME
@@ -2474,7 +2687,6 @@ if (end != null) {
                public override string ToString() {
                        return "document " + this.document_id;
                }
-
                #endregion      // Administrative
        }
 
@@ -2496,8 +2708,6 @@ if (end != null) {
                internal int            ascent;         // Ascent of the font for this tag
                internal int            shift;          // Shift down for this tag, to stay on baseline
 
-               internal int            soft_break;     // Tag is 'broken soft' and continues in the next line
-
                // Administrative
                internal Line           line;           // The line we're on
                internal LineTag        next;           // Next tag on the same line
@@ -2515,11 +2725,9 @@ if (end != null) {
                #endregion      // Constructors
 
                #region Internal Methods
-               //
-               // Applies 'font' to characters starting at 'start' for 'length' chars
-               // Removes any previous tags overlapping the same area
-               // returns true if lineheight has changed
-               //
+               /// <summary>Applies 'font' to characters starting at 'start' for 'length' chars; 
+               /// Removes any previous tags overlapping the same area; 
+               /// returns true if lineheight has changed</summary>
                internal static bool FormatText(Line line, int start, int length, Font font, Brush color) {
                        LineTag tag;
                        LineTag start_tag;
@@ -2615,9 +2823,7 @@ if (end != null) {
                }
 
 
-               //
-               // Finds the tag that describes the character at position 'pos' on 'line'
-               //
+               /// <summary>Finds the tag that describes the character at position 'pos' on 'line'</summary>
                internal static LineTag FindTag(Line line, int pos) {
                        LineTag tag = line.tags;
 
@@ -2637,9 +2843,7 @@ if (end != null) {
                        return null;
                }
 
-               //
-               // Combines 'this' tag with 'other' tag.
-               //
+               /// <summary>Combines 'this' tag with 'other' tag</summary>
                internal bool Combine(LineTag other) {
                        if (!this.Equals(other)) {
                                return false;
@@ -2656,9 +2860,7 @@ if (end != null) {
                }
 
 
-               //
-               // Remove 'this' tag ; to be called when formatting is to be removed
-               //
+               /// <summary>Remove 'this' tag ; to be called when formatting is to be removed</summary>
                internal bool Remove() {
                        if ((this.start == 1) && (this.next == null)) {
                                // We cannot remove the only tag
@@ -2680,9 +2882,7 @@ if (end != null) {
                }
 
 
-               //
-               // Checks if 'this' tag describes the same formatting options as 'obj'
-               //
+               /// <summary>Checks if 'this' tag describes the same formatting options as 'obj'</summary>
                public override bool Equals(object obj) {
                        LineTag other;