Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'mcs/class/Managed.Windows.Forms/System.Windows.Forms/TextBoxBase.cs')
-rw-r--r--mcs/class/Managed.Windows.Forms/System.Windows.Forms/TextBoxBase.cs1669
1 files changed, 1669 insertions, 0 deletions
diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/TextBoxBase.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/TextBoxBase.cs
new file mode 100644
index 00000000000..442649c7a6a
--- /dev/null
+++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/TextBoxBase.cs
@@ -0,0 +1,1669 @@
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// 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-2006 Novell, Inc. (http://www.novell.com)
+//
+// Authors:
+// Peter Bartok pbartok@novell.com
+//
+//
+
+// NOT COMPLETE
+#undef Debug
+#undef DebugClick
+
+using System.ComponentModel;
+using System.ComponentModel.Design;
+using System.Drawing;
+using System.Drawing.Text;
+using System.Text;
+using System.Runtime.InteropServices;
+
+namespace System.Windows.Forms {
+ [DefaultEvent("TextChanged")]
+ [Designer("System.Windows.Forms.Design.TextBoxBaseDesigner, " + Consts.AssemblySystem_Design)]
+ public abstract class TextBoxBase : Control {
+ #region Local Variables
+ internal HorizontalAlignment alignment;
+ internal bool accepts_tab;
+ internal bool accepts_return;
+ internal bool auto_size;
+ internal CharacterCasing character_casing;
+ internal bool undo;
+ internal bool hide_selection;
+ internal int max_length;
+ internal bool modified;
+ internal bool multiline;
+ internal char password_char;
+ internal bool read_only;
+ internal bool word_wrap;
+ 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 ImplicitHScrollBar hscroll;
+ internal ImplicitVScrollBar vscroll;
+ internal RichTextBoxScrollBars scrollbars;
+ internal bool richtext;
+ internal int requested_height;
+ internal int canvas_width;
+ internal int canvas_height;
+ static internal int track_width = 20;
+ static internal int track_border = 5;
+ internal DateTime click_last;
+ internal CaretSelection click_mode;
+ internal Bitmap bmp;
+ #if Debug
+ internal static bool draw_lines = false;
+ #endif
+
+ #endregion // Local Variables
+
+ #region Internal Constructor
+ // Constructor will go when complete, only for testing - pdb
+ internal TextBoxBase() {
+ alignment = HorizontalAlignment.Left;
+ accepts_return = false;
+ accepts_tab = false;
+ auto_size = true;
+ border_style = BorderStyle.Fixed3D;
+ character_casing = CharacterCasing.Normal;
+ undo = false;
+ hide_selection = true;
+ max_length = 32767;
+ modified = false;
+ multiline = false;
+ password_char = '\0';
+ read_only = false;
+ word_wrap = true;
+ richtext = false;
+ document = new Document(this);
+ document.WidthChanged += new EventHandler(document_WidthChanged);
+ document.HeightChanged += new EventHandler(document_HeightChanged);
+ //document.CaretMoved += new EventHandler(CaretMoved);
+ document.Wrap = false;
+ requested_height = -1;
+ click_last = DateTime.Now;
+ click_mode = CaretSelection.Position;
+ bmp = new Bitmap(1, 1, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
+
+ MouseDown += new MouseEventHandler(TextBoxBase_MouseDown);
+ MouseUp += new MouseEventHandler(TextBoxBase_MouseUp);
+ MouseMove += new MouseEventHandler(TextBoxBase_MouseMove);
+ SizeChanged += new EventHandler(TextBoxBase_SizeChanged);
+ FontChanged += new EventHandler(TextBoxBase_FontOrColorChanged);
+ ForeColorChanged += new EventHandler(TextBoxBase_FontOrColorChanged);
+ MouseWheel += new MouseEventHandler(TextBoxBase_MouseWheel);
+
+ scrollbars = RichTextBoxScrollBars.None;
+
+ hscroll = new ImplicitHScrollBar();
+ hscroll.ValueChanged += new EventHandler(hscroll_ValueChanged);
+ hscroll.control_style &= ~ControlStyles.Selectable;
+ hscroll.Enabled = false;
+ hscroll.Visible = false;
+
+ vscroll = new ImplicitVScrollBar();
+ vscroll.ValueChanged += new EventHandler(vscroll_ValueChanged);
+ vscroll.control_style &= ~ControlStyles.Selectable;
+ vscroll.Enabled = false;
+ vscroll.Visible = false;
+
+ SuspendLayout ();
+ this.Controls.AddImplicit (hscroll);
+ this.Controls.AddImplicit (vscroll);
+ ResumeLayout ();
+
+ //SetStyle(ControlStyles.ResizeRedraw, true);
+ SetStyle(ControlStyles.UserPaint | ControlStyles.StandardClick, false);
+
+ canvas_width = ClientSize.Width;
+ canvas_height = ClientSize.Height;
+
+ CalculateScrollBars();
+ }
+ #endregion // Internal Constructor
+
+ #region Private and Internal Methods
+ internal string CaseAdjust(string s) {
+ if (character_casing == CharacterCasing.Normal) {
+ return s;
+ }
+ if (character_casing == CharacterCasing.Lower) {
+ return s.ToLower();
+ } else {
+ return s.ToUpper();
+ }
+ }
+ #endregion // Private and Internal Methods
+
+ #region Public Instance Properties
+ [DefaultValue(false)]
+ public bool AcceptsTab {
+ get {
+ return accepts_tab;
+ }
+
+ set {
+ if (value != accepts_tab) {
+ accepts_tab = value;
+ OnAcceptsTabChanged(EventArgs.Empty);
+ }
+ }
+ }
+
+ [DefaultValue(true)]
+ [Localizable(true)]
+ [RefreshProperties(RefreshProperties.Repaint)]
+ public virtual bool AutoSize {
+ get {
+ return auto_size;
+ }
+
+ set {
+ if (value != auto_size) {
+ auto_size = value;
+ if (auto_size) {
+ if (PreferredHeight != ClientSize.Height) {
+ ClientSize = new Size(ClientSize.Width, PreferredHeight);
+ }
+ }
+ OnAutoSizeChanged(EventArgs.Empty);
+ }
+ }
+ }
+
+ [DispId(-501)]
+ public override System.Drawing.Color BackColor {
+ get {
+ return base.BackColor;
+ }
+ set {
+ base.BackColor = value;
+ }
+ }
+
+ [Browsable(false)]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public override System.Drawing.Image BackgroundImage {
+ get {
+ return base.BackgroundImage;
+ }
+ set {
+ base.BackgroundImage = value;
+ }
+ }
+
+ [DefaultValue(BorderStyle.Fixed3D)]
+ [DispId(-504)]
+ public BorderStyle BorderStyle {
+ get { return InternalBorderStyle; }
+ set {
+ InternalBorderStyle = value;
+ OnBorderStyleChanged(EventArgs.Empty);
+ }
+ }
+
+ [Browsable(false)]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public bool CanUndo {
+ get {
+ return undo;
+ }
+ }
+
+ [DispId(-513)]
+ public override System.Drawing.Color ForeColor {
+ get {
+ return base.ForeColor;
+ }
+ set {
+ base.ForeColor = value;
+ }
+ }
+
+ [DefaultValue(true)]
+ public bool HideSelection {
+ get {
+ return hide_selection;
+ }
+
+ set {
+ if (value != hide_selection) {
+ hide_selection = value;
+ OnHideSelectionChanged(EventArgs.Empty);
+ }
+ if (hide_selection) {
+ document.selection_visible = false;
+ } else {
+ document.selection_visible = true;
+ }
+ document.InvalidateSelectionArea();
+
+ }
+ }
+
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ [Editor("System.Windows.Forms.Design.StringArrayEditor, " + Consts.AssemblySystem_Design, typeof(System.Drawing.Design.UITypeEditor))]
+ [Localizable(true)]
+ public string[] Lines {
+ get {
+ string[] lines;
+ int i;
+ int l;
+
+ l = document.Lines;
+ lines = new string[l];
+
+ for (i = 1; i <= l; i++) {
+ lines[i - 1] = document.GetLine(i).text.ToString();
+ }
+
+ return lines;
+ }
+
+ set {
+ int i;
+ int l;
+ Brush brush;
+
+ document.Empty();
+
+ l = value.Length;
+ brush = ThemeEngine.Current.ResPool.GetSolidBrush(this.ForeColor);
+
+ for (i = 0; i < l; i++) {
+ document.Add(i+1, CaseAdjust(value[i]), alignment, Font, brush);
+ }
+ CalculateDocument();
+ OnTextChanged(EventArgs.Empty);
+ }
+ }
+
+ [DefaultValue(32767)]
+ [Localizable(true)]
+ public virtual int MaxLength {
+ get {
+ if (max_length == 2147483646) { // We don't distinguish between single and multi-line limits
+ return 0;
+ }
+ return max_length;
+ }
+
+ set {
+ if (value != max_length) {
+ max_length = value;
+ }
+ }
+ }
+
+ [Browsable(false)]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public bool Modified {
+ get {
+ return modified;
+ }
+
+ set {
+ if (value != modified) {
+ modified = value;
+ OnModifiedChanged(EventArgs.Empty);
+ }
+ }
+ }
+
+ [DefaultValue(false)]
+ [Localizable(true)]
+ [RefreshProperties(RefreshProperties.All)]
+ public virtual bool Multiline {
+ get {
+ return multiline;
+ }
+
+ set {
+ if (value != multiline) {
+ multiline = value;
+ // Make sure we update our size; the user may have already set the size before going to multiline
+ if (multiline && requested_height != -1) {
+ Height = requested_height;
+ requested_height = -1;
+ }
+
+ OnMultilineChanged(EventArgs.Empty);
+ }
+
+ document.multiline = multiline;
+
+ if (multiline) {
+ document.Wrap = word_wrap;
+ document.PasswordChar = "";
+
+ } else {
+ document.Wrap = false;
+ if (this.password_char != '\0') {
+ document.PasswordChar = password_char.ToString();
+ } else {
+ document.PasswordChar = "";
+ }
+ }
+ }
+ }
+
+ [Browsable(false)]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ [EditorBrowsable(EditorBrowsableState.Advanced)]
+ public int PreferredHeight {
+ get {
+ return this.Font.Height + 7; // FIXME - consider border style as well
+ }
+ }
+
+ [DefaultValue(false)]
+ public bool ReadOnly {
+ get {
+ return read_only;
+ }
+
+ set {
+ if (value != read_only) {
+ read_only = value;
+ OnReadOnlyChanged(EventArgs.Empty);
+ }
+ }
+ }
+
+ [Browsable(false)]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public virtual string SelectedText {
+ get {
+ return document.GetSelection();
+ }
+
+ set {
+ if (!read_only) {
+ document.ReplaceSelection(CaseAdjust(value));
+ ScrollToCaret();
+ OnTextChanged(EventArgs.Empty);
+ }
+ }
+ }
+
+ [Browsable(false)]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public virtual int SelectionLength {
+ get {
+ return document.SelectionLength();
+ }
+
+ set {
+ if (value != 0) {
+ int start;
+ Line line;
+ LineTag tag;
+ int pos;
+
+ start = document.LineTagToCharIndex(document.selection_start.line, document.selection_start.pos);
+
+ document.CharIndexToLineTag(start + value, out line, out tag, out pos);
+ document.SetSelectionEnd(line, pos);
+ document.PositionCaret(line, pos);
+ } else {
+ document.SetSelectionEnd(document.selection_start.line, document.selection_start.pos);
+ document.PositionCaret(document.selection_start.line, document.selection_start.pos);
+ }
+ }
+ }
+
+ [Browsable(false)]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public int SelectionStart {
+ get {
+ int index;
+
+ index = document.LineTagToCharIndex(document.selection_start.line, document.selection_start.pos);
+
+ return index;
+ }
+
+ set {
+ Line line;
+ LineTag tag;
+ int pos;
+
+ document.CharIndexToLineTag(value, out line, out tag, out pos);
+ document.SetSelectionStart(line, pos);
+ ScrollToCaret();
+ }
+ }
+
+ [Localizable(true)]
+ public override string Text {
+ get {
+ if (document == null || document.Root == null || document.Root.text == null) {
+ return string.Empty;
+ }
+
+ if (!multiline) {
+ return document.Root.text.ToString();
+ } else {
+ StringBuilder sb;
+ int i;
+
+ sb = new StringBuilder();
+
+ for (i = 1; i < document.Lines; i++) {
+ sb.Append(document.GetLine(i).text.ToString() + Environment.NewLine);
+ }
+ sb.Append(document.GetLine(document.Lines).text.ToString());
+ return sb.ToString();
+ }
+ }
+
+ set {
+ if (value == base.Text) {
+ return;
+ }
+
+ if ((value != null) && (value != "")) {
+ Line line;
+
+ if (multiline) {
+ string[] lines;
+
+ lines = value.Split(new char[] {'\n'});
+
+ for (int i = 0; i < lines.Length; i++) {
+ if (lines[i].EndsWith("\r")) {
+ lines[i] = lines[i].Substring(0, lines[i].Length - 1);
+ }
+ }
+ this.Lines = lines;
+
+ line = document.GetLine(1);
+ document.SetSelectionStart(line, 0);
+
+ line = document.GetLine(document.Lines);
+ document.SetSelectionEnd(line, line.text.Length);
+ document.PositionCaret(line, line.text.Length);
+ } else {
+ document.Clear();
+ document.Add(1, CaseAdjust(value), alignment, Font, ThemeEngine.Current.ResPool.GetSolidBrush(ForeColor));
+ CalculateDocument();
+ line = document.GetLine(1);
+ document.SetSelectionStart(line, 0);
+ document.SetSelectionEnd(line, value.Length);
+ document.PositionCaret(line, value.Length);
+ }
+ } else {
+ document.Empty();
+ CalculateDocument();
+ }
+ base.Text = value;
+ // Not needed, base.Text already fires it
+ // OnTextChanged(EventArgs.Empty);
+ }
+ }
+
+ [Browsable(false)]
+ public virtual int TextLength {
+ get {
+ if (document == null || document.Root == null || document.Root.text == null) {
+ return 0;
+ }
+
+ if (!multiline) {
+ return document.Root.text.Length;
+ } else {
+ int total;
+ int i;
+
+ total = 0;
+ for (i = 1; i < document.Lines; i++) {
+ total += document.GetLine(i).text.Length + Environment.NewLine.Length;
+ }
+ total += document.GetLine(i).text.Length;
+
+ return total;
+ }
+ }
+ }
+
+ [DefaultValue(true)]
+ [Localizable(true)]
+ public bool WordWrap {
+ get {
+ return word_wrap;
+ }
+
+ set {
+ if (value != word_wrap) {
+ if (multiline) {
+ word_wrap = value;
+ document.Wrap = value;
+ }
+ }
+ }
+ }
+ #endregion // Public Instance Properties
+
+ #region Protected Instance Properties
+ protected override CreateParams CreateParams {
+ get {
+ return base.CreateParams;
+ }
+ }
+
+ protected override System.Drawing.Size DefaultSize {
+ get {
+ return new Size(100, 20);
+ }
+ }
+ #endregion // Protected Instance Properties
+
+ #region Public Instance Methods
+ public void AppendText(string text) {
+ if (multiline) {
+ // Grab the formatting for the last element
+ document.MoveCaret(CaretDirection.CtrlEnd);
+ // grab the end tag
+ if (document.CaretTag.next != null) {
+ document.CaretTag = document.CaretTag.next;
+ }
+ document.Insert(document.CaretLine, document.CaretTag, document.CaretPosition, false, text);
+
+ CalculateDocument();
+ } else {
+ document.MoveCaret(CaretDirection.CtrlEnd);
+ document.InsertStringAtCaret(text, true);
+
+ Invalidate();
+ }
+
+ document.MoveCaret(CaretDirection.CtrlEnd);
+ document.SetSelectionStart(document.CaretLine, document.CaretPosition);
+ document.SetSelectionEnd(document.CaretLine, document.CaretPosition);
+
+ OnTextChanged(EventArgs.Empty);
+ }
+
+ public void Clear() {
+ Text = null;
+ }
+
+ public void ClearUndo() {
+ document.undo.Clear();
+ }
+
+ public void Copy() {
+ DataObject o;
+
+ o = new DataObject(DataFormats.Text, SelectedText);
+ if (this is RichTextBox) {
+ o.SetData(DataFormats.Rtf, ((RichTextBox)this).SelectedRtf);
+ }
+ Clipboard.SetDataObject(o);
+ }
+
+ public void Cut() {
+ DataObject o;
+
+ o = new DataObject(DataFormats.Text, SelectedText);
+ if (this is RichTextBox) {
+ o.SetData(DataFormats.Rtf, ((RichTextBox)this).SelectedRtf);
+ }
+ Clipboard.SetDataObject(o);
+ document.ReplaceSelection("");
+ }
+
+ public void Paste() {
+ Paste(null, false);
+ }
+
+ public void ScrollToCaret() {
+ this.CaretMoved(this, EventArgs.Empty);
+ }
+
+ public void Select(int start, int length) {
+ SelectionStart = start;
+ SelectionLength = length;
+ }
+
+
+ public void SelectAll() {
+ Line last;
+
+ last = document.GetLine(document.Lines);
+ document.SetSelectionStart(document.GetLine(1), 0);
+ document.SetSelectionEnd(last, last.text.Length);
+ }
+
+ public override string ToString() {
+ return Text;
+ }
+
+ public void Undo() {
+ document.undo.Undo();
+ }
+ #endregion // Public Instance Methods
+
+ #region Protected Instance Methods
+ protected override void CreateHandle() {
+ base.CreateHandle ();
+ }
+
+ protected override bool IsInputKey(Keys keyData) {
+ if ((keyData & Keys.Alt) != 0) {
+ return base.IsInputKey(keyData);
+ }
+
+ switch (keyData & Keys.KeyCode) {
+ case Keys.Enter: {
+ if (multiline && accepts_return) {
+ return true;
+ }
+ return false;
+ }
+
+ case Keys.Tab: {
+ if (accepts_tab && multiline) {
+ if ((keyData & Keys.Control) == 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ case Keys.Left:
+ case Keys.Right:
+ case Keys.Up:
+ case Keys.Down:
+ case Keys.PageUp:
+ case Keys.PageDown:
+ case Keys.Home:
+ case Keys.End: {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ protected virtual void OnAcceptsTabChanged(EventArgs e) {
+ if (AcceptsTabChanged != null) {
+ AcceptsTabChanged(this, e);
+ }
+ }
+
+ protected virtual void OnAutoSizeChanged(EventArgs e) {
+ if (AutoSizeChanged != null) {
+ AutoSizeChanged(this, e);
+ }
+ }
+
+ protected virtual void OnBorderStyleChanged(EventArgs e) {
+ if (BorderStyleChanged != null) {
+ BorderStyleChanged(this, e);
+ }
+ }
+
+ protected override void OnFontChanged(EventArgs e) {
+ base.OnFontChanged (e);
+
+ if (auto_size) {
+ if (PreferredHeight != ClientSize.Height) {
+ Height = PreferredHeight;
+ }
+ }
+ }
+
+ protected override void OnHandleCreated(EventArgs e) {
+ base.OnHandleCreated (e);
+ }
+
+ protected override void OnHandleDestroyed(EventArgs e) {
+ base.OnHandleDestroyed (e);
+ }
+
+ protected virtual void OnHideSelectionChanged(EventArgs e) {
+ if (HideSelectionChanged != null) {
+ HideSelectionChanged(this, e);
+ }
+ }
+
+ protected virtual void OnModifiedChanged(EventArgs e) {
+ if (ModifiedChanged != null) {
+ ModifiedChanged(this, e);
+ }
+ }
+
+ protected virtual void OnMultilineChanged(EventArgs e) {
+ if (MultilineChanged != null) {
+ MultilineChanged(this, e);
+ }
+ }
+
+ protected virtual void OnReadOnlyChanged(EventArgs e) {
+ if (ReadOnlyChanged != null) {
+ ReadOnlyChanged(this, e);
+ }
+ }
+
+ protected override bool ProcessDialogKey(Keys keyData) {
+ return base.ProcessDialogKey(keyData);
+ }
+
+ private bool ProcessKey(Keys keyData) {
+ bool control;
+ bool shift;
+
+ control = (Control.ModifierKeys & Keys.Control) != 0;
+ shift = (Control.ModifierKeys & Keys.Shift) != 0;
+
+ switch (keyData & Keys.KeyCode) {
+ case Keys.X: { // Cut (Ctrl-X)
+ if (control) {
+ Cut();
+ return true;
+ }
+ return false;
+ }
+
+ case Keys.C: { // Copy (Ctrl-C)
+ if (control) {
+ Copy();
+ return true;
+ }
+ return false;
+ }
+
+ case Keys.V: { // Paste (Ctrl-V)
+ if (control) {
+ return Paste(null, true);
+ }
+ return false;
+ }
+
+ case Keys.Z: { // Undo (Ctrl-Z)
+ if (control) {
+ Undo();
+ return true;
+ }
+ return false;
+ }
+
+ case Keys.Left: {
+ if (control) {
+ document.MoveCaret(CaretDirection.WordBack);
+ } else {
+ if (!document.selection_visible || shift) {
+ document.MoveCaret(CaretDirection.CharBack);
+ } else {
+ document.MoveCaret(CaretDirection.SelectionStart);
+ }
+ }
+
+ if (!shift) {
+ document.SetSelectionToCaret(true);
+ } else {
+ document.SetSelectionToCaret(false);
+ }
+
+ CaretMoved(this, null);
+ return true;
+ }
+
+ case Keys.Right: {
+ if (control) {
+ document.MoveCaret(CaretDirection.WordForward);
+ } else {
+ if (!document.selection_visible || shift) {
+ document.MoveCaret(CaretDirection.CharForward);
+ } else {
+ document.MoveCaret(CaretDirection.SelectionEnd);
+ }
+ }
+ if (!shift) {
+ document.SetSelectionToCaret(true);
+ } else {
+ document.SetSelectionToCaret(false);
+ }
+
+ CaretMoved(this, null);
+ return true;
+ }
+
+ case Keys.Up: {
+ if (control) {
+ if (document.CaretPosition == 0) {
+ document.MoveCaret(CaretDirection.LineUp);
+ } else {
+ document.MoveCaret(CaretDirection.Home);
+ }
+ } else {
+ document.MoveCaret(CaretDirection.LineUp);
+ }
+
+ if ((Control.ModifierKeys & Keys.Shift) == 0) {
+ document.SetSelectionToCaret(true);
+ } else {
+ document.SetSelectionToCaret(false);
+ }
+
+ CaretMoved(this, null);
+ return true;
+ }
+
+ case Keys.Down: {
+ if (control) {
+ if (document.CaretPosition == document.CaretLine.Text.Length) {
+ document.MoveCaret(CaretDirection.LineDown);
+ } else {
+ document.MoveCaret(CaretDirection.End);
+ }
+ } else {
+ document.MoveCaret(CaretDirection.LineDown);
+ }
+
+ if ((Control.ModifierKeys & Keys.Shift) == 0) {
+ document.SetSelectionToCaret(true);
+ } else {
+ document.SetSelectionToCaret(false);
+ }
+
+ CaretMoved(this, null);
+ return true;
+ }
+
+ case Keys.Home: {
+ if ((Control.ModifierKeys & Keys.Control) != 0) {
+ document.MoveCaret(CaretDirection.CtrlHome);
+ } else {
+ document.MoveCaret(CaretDirection.Home);
+ }
+
+ if ((Control.ModifierKeys & Keys.Shift) == 0) {
+ document.SetSelectionToCaret(true);
+ } else {
+ document.SetSelectionToCaret(false);
+ }
+
+ CaretMoved(this, null);
+ return true;
+ }
+
+ case Keys.End: {
+ if ((Control.ModifierKeys & Keys.Control) != 0) {
+ document.MoveCaret(CaretDirection.CtrlEnd);
+ } else {
+ document.MoveCaret(CaretDirection.End);
+ }
+
+ if ((Control.ModifierKeys & Keys.Shift) == 0) {
+ document.SetSelectionToCaret(true);
+ } else {
+ document.SetSelectionToCaret(false);
+ }
+
+ CaretMoved(this, null);
+ return true;
+ }
+
+ case Keys.Enter: {
+ // ignoring accepts_return, fixes bug #76355
+ if (!read_only && multiline && (accepts_return || (FindForm() != null && FindForm().AcceptButton == null) || ((Control.ModifierKeys & Keys.Control) != 0))) {
+ Line line;
+
+ if (document.selection_visible) {
+ document.ReplaceSelection("");
+ }
+ document.SetSelectionToCaret(true);
+
+ line = document.CaretLine;
+
+ document.Split(document.CaretLine, document.CaretTag, document.CaretPosition, false);
+ OnTextChanged(EventArgs.Empty);
+ document.UpdateView(line, 2, 0);
+ document.MoveCaret(CaretDirection.CharForward);
+ CaretMoved(this, null);
+ return true;
+ }
+ break;
+ }
+
+ case Keys.Tab: {
+ if (!read_only && accepts_tab && multiline) {
+ document.InsertChar(document.CaretLine, document.CaretPosition, '\t');
+ if (document.selection_visible) {
+ document.ReplaceSelection("");
+ }
+ document.SetSelectionToCaret(true);
+
+ OnTextChanged(EventArgs.Empty);
+ CaretMoved(this, null);
+ return true;
+ }
+ break;
+ }
+
+
+ case Keys.Back: {
+ if (read_only) {
+ break;
+ }
+
+ // delete only deletes on the line, doesn't do the combine
+ if (document.selection_visible) {
+ document.ReplaceSelection("");
+ }
+ document.SetSelectionToCaret(true);
+
+ if (document.CaretPosition == 0) {
+ if (document.CaretLine.LineNo > 1) {
+ Line line;
+ int new_caret_pos;
+
+ line = document.GetLine(document.CaretLine.LineNo - 1);
+ new_caret_pos = line.text.Length;
+
+ document.Combine(line, document.CaretLine);
+ document.UpdateView(line, 1, 0);
+ document.PositionCaret(line, new_caret_pos);
+ //document.MoveCaret(CaretDirection.CharForward);
+ document.UpdateCaret();
+ OnTextChanged(EventArgs.Empty);
+ }
+ } else {
+ if (!control || document.CaretPosition == 0) {
+ document.DeleteChar(document.CaretTag, document.CaretPosition, false);
+ document.MoveCaret(CaretDirection.CharBack);
+ } else {
+ int start_pos;
+
+ start_pos = document.CaretPosition - 1;
+
+ while ((start_pos > 0) && !Document.IsWordSeparator(document.CaretLine.Text[start_pos - 1])) {
+ start_pos--;
+ }
+ document.DeleteChars(document.CaretTag, start_pos, document.CaretPosition - start_pos);
+ document.PositionCaret(document.CaretLine, start_pos);
+ }
+ document.UpdateCaret();
+ OnTextChanged(EventArgs.Empty);
+ }
+ CaretMoved(this, null);
+ return true;
+ }
+
+ case Keys.Insert: {
+ if (shift) {
+ Paste(null, true);
+ return true;
+ }
+
+ if (control) {
+ Copy();
+ return true;
+ }
+
+ // FIXME - need overwrite/insert toggle?
+ return false;
+ }
+
+ case Keys.Delete: {
+ if (shift) {
+ Cut();
+ return true;
+ }
+
+ if (read_only) {
+ break;
+ }
+
+ if (document.selection_visible) {
+ document.ReplaceSelection("");
+ } else {
+ // DeleteChar only deletes on the line, doesn't do the combine
+ if (document.CaretPosition == document.CaretLine.Text.Length) {
+ if (document.CaretLine.LineNo < document.Lines) {
+ Line line;
+
+ line = document.GetLine(document.CaretLine.LineNo + 1);
+ document.Combine(document.CaretLine, line);
+ document.UpdateView(document.CaretLine, 2, 0);
+
+ #if not_Debug
+ Line check_first;
+ Line check_second;
+
+ check_first = document.GetLine(document.CaretLine.LineNo);
+ check_second = document.GetLine(check_first.line_no + 1);
+
+ Console.WriteLine("Post-UpdateView: Y of first line: {0}, second line: {1}", check_first.Y, check_second.Y);
+ #endif
+
+ // Caret doesn't move
+ }
+ } else {
+ if (!control) {
+ document.DeleteChar(document.CaretTag, document.CaretPosition, true);
+ } else {
+ int end_pos;
+
+ end_pos = document.CaretPosition;
+
+ while ((end_pos < document.CaretLine.Text.Length) && !Document.IsWordSeparator(document.CaretLine.Text[end_pos])) {
+ end_pos++;
+ }
+
+ if (end_pos < document.CaretLine.Text.Length) {
+ end_pos++;
+ }
+ document.DeleteChars(document.CaretTag, document.CaretPosition, end_pos - document.CaretPosition);
+ }
+ }
+ }
+
+ OnTextChanged(EventArgs.Empty);
+ document.AlignCaret();
+ document.UpdateCaret();
+ CaretMoved(this, null);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified) {
+ // Make sure we don't get sized bigger than we want to be
+ if (!richtext) {
+ if (!multiline) {
+ if (height != PreferredHeight) {
+ requested_height = height;
+ height = PreferredHeight;
+ specified |= BoundsSpecified.Height;
+ }
+ }
+ }
+
+ base.SetBoundsCore (x, y, width, height, specified);
+
+ TextBoxBase_SizeChanged(this, EventArgs.Empty);
+ CalculateDocument();
+ }
+
+ protected override void WndProc(ref Message m) {
+ switch ((Msg)m.Msg) {
+ case Msg.WM_PAINT: {
+ PaintEventArgs paint_event;
+
+ paint_event = XplatUI.PaintEventStart(Handle, true);
+
+ PaintControl(paint_event);
+ XplatUI.PaintEventEnd(Handle, true);
+ DefWndProc(ref m);
+ return;
+ }
+
+ case Msg.WM_SETFOCUS: {
+ // Set caret
+ document.CaretHasFocus();
+ base.WndProc(ref m);
+ return;
+ }
+
+ case Msg.WM_KILLFOCUS: {
+ // Kill caret
+ document.CaretLostFocus();
+ base.WndProc(ref m);
+ return;
+ }
+
+ case Msg.WM_KEYDOWN: {
+ if (ProcessKeyMessage(ref m) || ProcessKey((Keys)m.WParam.ToInt32() | XplatUI.State.ModifierKeys)) {
+ m.Result = IntPtr.Zero;
+ return;
+ }
+ DefWndProc (ref m);
+ return;
+ }
+
+ case Msg.WM_CHAR: {
+ if (ProcessKeyMessage(ref m)) {
+ m.Result = IntPtr.Zero;
+ return;
+ }
+
+ // Ctrl-Backspace generates a real char, whack it
+ if (m.WParam.ToInt32() == 127) {
+ base.WndProc(ref m);
+ return;
+ }
+
+ if (!read_only && (m.WParam.ToInt32() >= 32)) { // FIXME, tabs should probably go through
+ if (document.selection_visible) {
+ document.ReplaceSelection("");
+ }
+
+ switch (character_casing) {
+ case CharacterCasing.Normal: {
+ if (document.Length < max_length) {
+ document.InsertCharAtCaret((char)m.WParam, true);
+ OnTextChanged(EventArgs.Empty);
+ CaretMoved(this, null);
+ } else {
+ XplatUI.AudibleAlert();
+ }
+ return;
+ }
+
+ case CharacterCasing.Lower: {
+ if (document.Length < max_length) {
+ document.InsertCharAtCaret(Char.ToLower((char)m.WParam), true);
+ OnTextChanged(EventArgs.Empty);
+ CaretMoved(this, null);
+ } else {
+ XplatUI.AudibleAlert();
+ }
+ return;
+ }
+
+ case CharacterCasing.Upper: {
+ if (document.Length < max_length) {
+ document.InsertCharAtCaret(Char.ToUpper((char)m.WParam), true);
+ OnTextChanged(EventArgs.Empty);
+ CaretMoved(this, null);
+ } else {
+ XplatUI.AudibleAlert();
+ }
+ return;
+ }
+ }
+ }
+ return;
+ }
+
+ default: {
+ base.WndProc(ref m);
+ return;
+ }
+ }
+ }
+
+ #endregion // Protected Instance Methods
+
+ #region Events
+ public event EventHandler AcceptsTabChanged;
+ public event EventHandler AutoSizeChanged;
+ [Browsable(false)]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public new event EventHandler BackgroundImageChanged {
+ add { base.BackgroundImageChanged += value; }
+ remove { base.BackgroundImageChanged -= value; }
+ }
+ public event EventHandler BorderStyleChanged;
+ [Browsable(false)]
+ [EditorBrowsable(EditorBrowsableState.Advanced)]
+ public event EventHandler Click;
+ public event EventHandler HideSelectionChanged;
+ public event EventHandler ModifiedChanged;
+ public event EventHandler MultilineChanged;
+ [Browsable(false)]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public event PaintEventHandler Paint;
+ public event EventHandler ReadOnlyChanged;
+
+ internal event EventHandler HScrolled;
+ internal event EventHandler VScrolled;
+ #endregion // Events
+
+ #region Private Methods
+ internal Document Document {
+ get {
+ return document;
+ }
+
+ set {
+ document = value;
+ }
+ }
+
+ internal Graphics CreateGraphicsInternal() {
+ if (IsHandleCreated) {
+ return base.CreateGraphics();
+ }
+
+ return Graphics.FromImage(bmp);
+ }
+
+ #if Debug
+ static int current;
+ #endif
+
+ private void PaintControl(PaintEventArgs pevent) {
+ // Fill background
+ pevent.Graphics.FillRectangle(ThemeEngine.Current.ResPool.GetSolidBrush(BackColor), pevent.ClipRectangle);
+ pevent.Graphics.TextRenderingHint=TextRenderingHint.AntiAlias;
+
+ // Draw the viewable document
+ document.Draw(pevent.Graphics, pevent.ClipRectangle);
+
+ Rectangle rect = ClientRectangle;
+ rect.Width--;
+ rect.Height--;
+ //pevent.Graphics.DrawRectangle(ThemeEngine.Current.ResPool.GetPen(ThemeEngine.Current.ColorControlDark), rect);
+
+ #if Debug
+ int start;
+ int end;
+ Line line;
+ int line_no;
+ Pen p;
+
+ 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 - 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));
+
+ line_no = start;
+ while (line_no <= end) {
+ line = document.GetLine(line_no);
+
+ if (draw_lines) {
+ for (int i = 0; i < line.text.Length; i++) {
+ pevent.Graphics.DrawLine(p, (int)line.widths[i] - document.ViewPortX, line.Y - document.ViewPortY, (int)line.widths[i] - document.ViewPortX, line.Y + line.height - document.ViewPortY);
+ }
+ }
+
+ line_no++;
+ }
+ #endif
+ }
+
+ private void TextBoxBase_MouseDown(object sender, MouseEventArgs e) {
+ if (e.Button == MouseButtons.Left) {
+ TimeSpan interval;
+
+ interval = DateTime.Now - click_last;
+ document.PositionCaret(e.X + document.ViewPortX, e.Y + document.ViewPortY);
+
+ // Handle place caret/select word/select line behaviour
+ if (e.Clicks == 1) {
+ if (SystemInformation.DoubleClickTime < interval.TotalMilliseconds) {
+ #if DebugClick
+ Console.WriteLine("Single Click Invalidating from char {0} to char {1} ({2})", document.selection_start.pos, document.selection_end.pos, document.selection_start.line.text.ToString(document.selection_start.pos, document.selection_end.pos - document.selection_start.pos));
+ #endif
+ document.SetSelectionToCaret(true);
+ click_mode = CaretSelection.Position;
+ } else {
+ #if DebugClick
+ Console.WriteLine("Tripple Click Selecting line");
+ #endif
+ document.ExpandSelection(CaretSelection.Line, false);
+ click_mode = CaretSelection.Line;
+ }
+ } else {
+ // We select the line if the word is already selected, and vice versa
+ if (click_mode != CaretSelection.Word) {
+ if (click_mode == CaretSelection.Line) {
+ document.Invalidate(document.selection_start.line, 0, document.selection_start.line, document.selection_start.line.text.Length);
+ }
+ click_mode = CaretSelection.Word;
+ document.ExpandSelection(CaretSelection.Word, false); // Setting initial selection
+ } else {
+ click_mode = CaretSelection.Line;
+ document.ExpandSelection(CaretSelection.Line, false); // Setting initial selection
+ }
+ }
+
+ // Reset
+ click_last = DateTime.Now;
+ return;
+ }
+
+ #if Debug
+ LineTag tag;
+ Line line;
+ int pos;
+
+ if (e.Button == MouseButtons.Right) {
+ draw_lines = !draw_lines;
+ this.Invalidate();
+ Console.WriteLine("SelectedText: {0}, length {1}", this.SelectedText, this.SelectionLength);
+ Console.WriteLine("Selection start: {0}", this.SelectionStart);
+
+ this.SelectionStart = 10;
+ this.SelectionLength = 5;
+
+ return;
+ }
+
+ 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;
+ switch(current) {
+ case 4: LineTag.FormatText(tag.line, pos, (pos+10)<line.Text.Length ? 10 : line.Text.Length - pos+1, new Font("impact", 20, FontStyle.Bold, GraphicsUnit.Pixel), ThemeEngine.Current.ResPool.GetSolidBrush(Color.Red)); break;
+ case 1: LineTag.FormatText(tag.line, pos, (pos+10)<line.Text.Length ? 10 : line.Text.Length - pos+1, new Font("arial unicode ms", 24, FontStyle.Italic, GraphicsUnit.Pixel), ThemeEngine.Current.ResPool.GetSolidBrush(Color.DarkGoldenrod)); break;
+ case 2: LineTag.FormatText(tag.line, pos, (pos+10)<line.Text.Length ? 10 : line.Text.Length - pos+1, new Font("arial", 10, FontStyle.Regular, GraphicsUnit.Pixel), ThemeEngine.Current.ResPool.GetSolidBrush(Color.Aquamarine)); break;
+ case 3: LineTag.FormatText(tag.line, pos, (pos+10)<line.Text.Length ? 10 : line.Text.Length - pos+1, new Font("times roman", 16, FontStyle.Underline, GraphicsUnit.Pixel), ThemeEngine.Current.ResPool.GetSolidBrush(Color.Turquoise)); break;
+ case 0: LineTag.FormatText(tag.line, pos, (pos+10)<line.Text.Length ? 10 : line.Text.Length - pos+1, new Font("times roman", 64, FontStyle.Italic | FontStyle.Bold, GraphicsUnit.Pixel), ThemeEngine.Current.ResPool.GetSolidBrush(Color.LightSeaGreen)); break;
+ case 5: LineTag.FormatText(tag.line, pos, (pos+10)<line.Text.Length ? 10 : line.Text.Length - pos+1, ((TextBoxBase)sender).Font, ThemeEngine.Current.ResPool.GetSolidBrush(ForeColor)); break;
+ }
+ current++;
+ if (current==6) {
+ current=0;
+ }
+
+ // Update/Recalculate what we see
+ document.UpdateView(line, 0);
+
+ // Make sure our caret is properly positioned and sized
+ document.AlignCaret();
+ #endif
+ }
+
+ private void TextBoxBase_MouseUp(object sender, MouseEventArgs e) {
+ if (e.Button == MouseButtons.Left) {
+ document.PositionCaret(e.X + document.ViewPortX, e.Y + document.ViewPortY);
+ if (click_mode == CaretSelection.Position) {
+ document.SetSelectionToCaret(false);
+ document.DisplayCaret();
+ } else {
+ document.ExpandSelection(click_mode, true);
+ }
+ return;
+ }
+ }
+
+ private void TextBoxBase_SizeChanged(object sender, EventArgs e) {
+ canvas_width = ClientSize.Width;
+ canvas_height = ClientSize.Height;
+ document.ViewPortWidth = canvas_width;
+ document.ViewPortHeight = canvas_height;
+
+ // We always move them, they just might not be displayed
+ hscroll.Bounds = new Rectangle (ClientRectangle.Left, ClientRectangle.Bottom - hscroll.Height, ClientSize.Width - (vscroll.Visible ? SystemInformation.VerticalScrollBarWidth : 0), hscroll.Height);
+ vscroll.Bounds = new Rectangle (ClientRectangle.Right - vscroll.Width, ClientRectangle.Top, vscroll.Width, ClientSize.Height - (hscroll.Visible ? SystemInformation.HorizontalScrollBarHeight : 0));
+
+ }
+
+ private void TextBoxBase_MouseWheel(object sender, MouseEventArgs e) {
+ Line line;
+ int line_no;
+ int target;
+
+ if (!vscroll.Enabled) {
+ return;
+ }
+
+ if (e.Delta < 0) {
+ line_no = document.GetLineByPixel(document.ViewPortY, false).line_no + SystemInformation.MouseWheelScrollLines;
+ if (line_no > document.Lines) {
+ line_no = document.Lines;
+ }
+ } else {
+ line_no = document.GetLineByPixel(document.ViewPortY, false).line_no - SystemInformation.MouseWheelScrollLines;
+ if (line_no < 1) {
+ line_no = 1;
+ }
+ }
+
+ line = document.GetLine(line_no);
+ if (line.Y < vscroll.Maximum) {
+ vscroll.Value = line.Y;
+ } else {
+ vscroll.Value = vscroll.Maximum;
+ }
+ }
+
+ internal void CalculateDocument() {
+ if (!IsHandleCreated) {
+ return;
+ }
+ document.RecalculateDocument(CreateGraphicsInternal());
+ CalculateScrollBars();
+ Invalidate(); // FIXME - do we need this?
+ }
+
+ internal void CalculateScrollBars() {
+ // FIXME - need separate calculations for center and right alignment
+ // No scrollbars for a single line
+ if (document.Width >= ClientSize.Width) {
+ hscroll.Enabled = true;
+ hscroll.Minimum = 0;
+ hscroll.Maximum = document.Width - ClientSize.Width + track_border;
+ } else {
+ hscroll.Maximum = document.ViewPortWidth;
+ hscroll.Enabled = false;
+ }
+
+ if (document.Height >= ClientSize.Height) {
+ vscroll.Enabled = true;
+ vscroll.Minimum = 0;
+ vscroll.Maximum = document.Height - ClientSize.Height + 1;
+ } else {
+ vscroll.Maximum = document.ViewPortHeight;
+ vscroll.Enabled = false;
+ }
+
+
+ if (!multiline) {
+ return;
+ }
+
+ if (!WordWrap) {
+ 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;
+ canvas_height = ClientSize.Height - hscroll.Height;
+ }
+
+ if (vscroll.Visible) {
+ hscroll.Maximum += vscroll.Width * 2;
+ canvas_width = ClientSize.Width - vscroll.Width * 2;
+ }
+
+ TextBoxBase_SizeChanged(this, EventArgs.Empty);
+ }
+
+ private void document_WidthChanged(object sender, EventArgs e) {
+ CalculateScrollBars();
+ }
+
+ private void document_HeightChanged(object sender, EventArgs e) {
+ CalculateScrollBars();
+ }
+
+ 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();
+
+ if (HScrolled != null) {
+ HScrolled(this, EventArgs.Empty);
+ }
+ }
+
+ private void vscroll_ValueChanged(object sender, EventArgs e) {
+ XplatUI.ScrollWindow(this.Handle, 0, document.ViewPortY-this.vscroll.Value, false);
+ document.ViewPortY = this.vscroll.Value;
+ document.UpdateCaret();
+
+ if (VScrolled != null) {
+ VScrolled(this, EventArgs.Empty);
+ }
+ }
+
+ private void TextBoxBase_MouseMove(object sender, MouseEventArgs e) {
+ // FIXME - handle auto-scrolling if mouse is to the right/left of the window
+ if (Capture) {
+ document.PositionCaret(e.X + document.ViewPortX, e.Y + document.ViewPortY);
+ if (click_mode == CaretSelection.Position) {
+ document.SetSelectionToCaret(false);
+ document.DisplayCaret();
+ } else {
+ document.ExpandSelection(click_mode, true);
+ }
+ }
+ }
+
+ private void TextBoxBase_FontOrColorChanged(object sender, EventArgs e) {
+ if (!richtext) {
+ Line line;
+
+ // Font changes apply to the whole document
+ for (int i = 1; i <= document.Lines; i++) {
+ line = document.GetLine(i);
+ LineTag.FormatText(line, 1, line.text.Length, Font, ThemeEngine.Current.ResPool.GetSolidBrush(ForeColor));
+ document.UpdateView(line, 0);
+ }
+ // Make sure the caret height is matching the new font height
+ document.AlignCaret();
+ }
+ }
+
+ /// <summary>Ensure the caret is always visible</summary>
+ internal void CaretMoved(object sender, EventArgs e) {
+ Point pos;
+ int height;
+
+ pos = document.Caret;
+ //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);
+
+ // Handle horizontal scrolling
+ if (document.CaretLine.alignment == HorizontalAlignment.Left) {
+ if (pos.X < (document.ViewPortX + track_width)) {
+ do {
+ if ((hscroll.Value - track_width) >= hscroll.Minimum) {
+ hscroll.Value -= track_width;
+ } else {
+ hscroll.Value = hscroll.Minimum;
+ }
+ } while (hscroll.Value > pos.X);
+ }
+
+ if ((pos.X > (this.canvas_width + document.ViewPortX - track_width)) && (hscroll.Enabled && (hscroll.Value != hscroll.Maximum))) {
+ do {
+ if ((hscroll.Value + track_width) <= hscroll.Maximum) {
+ hscroll.Value += track_width;
+ } else {
+ hscroll.Value = hscroll.Maximum;
+ }
+ } while (pos.X > (hscroll.Value + this.canvas_width));
+ }
+ } else if (document.CaretLine.alignment == HorizontalAlignment.Right) {
+ if (pos.X < document.ViewPortX) {
+ if (pos.X > hscroll.Minimum) {
+ hscroll.Value = pos.X;
+ } else {
+ hscroll.Value = hscroll.Minimum;
+ }
+ }
+
+ if ((pos.X > (this.canvas_width + document.ViewPortX)) && (hscroll.Enabled && (hscroll.Value != hscroll.Maximum))) {
+ hscroll.Value = hscroll.Maximum;
+ }
+ } else {
+ }
+
+ if (!multiline) {
+ return;
+ }
+
+ // Handle vertical scrolling
+ height = document.CaretLine.Height + 1;
+
+ if (pos.Y < document.ViewPortY) {
+ vscroll.Value = pos.Y;
+ }
+
+ if ((pos.Y + height) > (document.ViewPortY + canvas_height)) {
+ vscroll.Value = pos.Y - canvas_height + height;
+ }
+ }
+
+ internal bool Paste(DataFormats.Format format, bool obey_length) {
+ IDataObject clip;
+ string s;
+
+ clip = Clipboard.GetDataObject();
+ if (clip == null)
+ return false;
+
+ if (format == null) {
+ if ((this is RichTextBox) && clip.GetDataPresent(DataFormats.Rtf)) {
+ format = DataFormats.GetFormat(DataFormats.Rtf);
+ } else if (clip.GetDataPresent(DataFormats.UnicodeText)) {
+ format = DataFormats.GetFormat(DataFormats.UnicodeText);
+ } else if (clip.GetDataPresent(DataFormats.Text)) {
+ format = DataFormats.GetFormat(DataFormats.Text);
+ } else {
+ return false;
+ }
+ } else {
+ if ((format.Name == DataFormats.Rtf) && !(this is RichTextBox)) {
+ return false;
+ }
+
+ if (!clip.GetDataPresent(format.Name)) {
+ return false;
+ }
+ }
+
+ if (format.Name == DataFormats.Rtf) {
+ ((RichTextBox)this).SelectedRtf = (string)clip.GetData(DataFormats.Rtf);
+ return true;
+ } else if (format.Name == DataFormats.UnicodeText) {
+ s = (string)clip.GetData(DataFormats.UnicodeText);
+ } else if (format.Name == DataFormats.Text) {
+ s = (string)clip.GetData(DataFormats.Text);
+ } else {
+ return false;
+ }
+
+ if (!obey_length) {
+ this.SelectedText = s;
+ } else {
+ if ((s.Length + document.Length) < max_length) {
+ this.SelectedText = s;
+ } else if (document.Length < max_length) {
+ this.SelectedText = s.Substring(0, max_length - document.Length);
+ }
+ }
+
+ return true;
+ }
+ #endregion // Private Methods
+ }
+}