I've attached some patches to the textbox/richtextbox that I have been
working on. I am hoping some people can do some testing on windows and
tell me if they notice any problems, specifically with line endings.
I've been working on making carriage returns work a little better with
our text controls, but i have a feeling this is going to busticate
things on windows.
Love,
Jackson
Index: System.Windows.Forms/TextBoxBase.cs
===================================================================
--- System.Windows.Forms/TextBoxBase.cs (revision 68864)
+++ System.Windows.Forms/TextBoxBase.cs (working copy)
@@ -34,6 +34,7 @@
using System.Drawing.Text;
using System.Text;
using System.Runtime.InteropServices;
+using System.Collections;
namespace System.Windows.Forms {
[DefaultEvent("TextChanged")]
@@ -252,7 +253,7 @@
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool CanUndo {
get {
- return undo;
+ return document.undo.UndoLevels != 0;
}
}
@@ -294,24 +295,32 @@
[MWFCategory("Appearance")]
public string[] Lines {
get {
- string[] lines;
- int i;
- int l;
+ int count;
+ ArrayList lines;
- l = document.Lines;
+ count = document.Lines;
// Handle empty document
- if ((l == 1) && (document.GetLine(1).text.Length == 0)) {
- return new string[0];
+ if ((count == 1) && (document.GetLine (1).text.Length == 0)) {
+ return new string [0];
}
- lines = new string[l];
+ lines = new ArrayList ();
- for (i = 1; i <= l; i++) {
- lines[i - 1] = document.GetLine(i).text.ToString();
+ int i = 1;
+ while (i <= count) {
+ Line line;
+ StringBuilder lt = new StringBuilder ();
+
+ do {
+ line = document.GetLine (i++);
+ lt.Append (line.text.ToString ());
+ } while (line.soft_break && i < count);
+
+ lines.Add (lt.ToString ());
}
- return lines;
+ return (string []) lines.ToArray (typeof (string));
}
set {
@@ -324,10 +333,30 @@
l = value.Length;
brush = ThemeEngine.Current.ResPool.GetSolidBrush(this.ForeColor);
+ document.NoRecalc = true;
for (i = 0; i < l; i++) {
+
+ // Don't add the last line if it is just an empty line feed
+ // the line feed is reflected in the previous line's soft_break = false
+ if (i == l - 1 && value [i].Length == 0)
+ break;
+
+ bool carriage_return = false;
+ if (value [i].EndsWith ("\r")) {
+ value [i] = value [i].Substring (0, value [i].Length - 1);
+ carriage_return = true;
+ }
+
document.Add(i+1, CaseAdjust(value[i]), alignment, Font, brush);
+ if (carriage_return) {
+ Line line = document.GetLine (i + 1);
+ line.carriage_return = true;
+ }
}
- CalculateDocument();
+
+ document.NoRecalc = false;
+
+ // CalculateDocument();
OnTextChanged(EventArgs.Empty);
}
}
@@ -520,6 +549,8 @@
sb.Append (Environment.NewLine);
line = document.GetLine (i);
sb.Append(line.text.ToString());
+ if (line.carriage_return)
+ sb.Append ("\r");
}
sb.Append(document.GetLine(document.Lines).text.ToString());
return sb.ToString();
@@ -538,13 +569,8 @@
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;
-
+
document.PositionCaret (document.GetLine (1), 0);
document.SetSelectionToCaret (true);
@@ -628,14 +654,9 @@
#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);
+ document.MoveCaret(CaretDirection.CtrlEnd);
+ document.Insert (document.caret.line, document.caret.tag, document.caret.pos, false, text);
CalculateDocument();
} else {
document.MoveCaret(CaretDirection.CtrlEnd);
@@ -645,9 +666,7 @@
}
document.MoveCaret(CaretDirection.CtrlEnd);
- document.SetSelectionStart(document.CaretLine, document.CaretPosition);
- document.SetSelectionEnd(document.CaretLine, document.CaretPosition);
- selection_length = -1;
+ document.SetSelectionToCaret (true);
OnTextChanged(EventArgs.Empty);
}
Index: System.Windows.Forms/TextControl.cs
===================================================================
--- System.Windows.Forms/TextControl.cs (revision 68864)
+++ System.Windows.Forms/TextControl.cs (working copy)
@@ -117,6 +117,7 @@
internal int indent; // Left indent for the first line
internal int hanging_indent; // Hanging indent (left indent for all but the first line)
internal int right_indent; // Right indent for all lines
+ internal bool carriage_return;
// Stuff that's important for the tree
@@ -501,8 +502,8 @@
if (pos == len) {
line = doc.GetLine(this.line_no + 1);
- if ((line != null) && (line.soft_break)) {
- // Pull the previous line back into this one
+ if ((line != null) && soft_break) {
+ // Pull the two lines together
doc.Combine(this.line_no, this.line_no + 1);
len = this.text.Length;
retval = true;
@@ -1021,7 +1022,7 @@
total = 1;
- Console.Write("Line {0} [# {1}], Y: {2}, soft break: {3}, Text {4}",
+ Console.Write("Line {0} [# {1}], Y: {2}, soft: {3}, Text {4}",
line.line_no, line.GetHashCode(), line.Y, line.soft_break,
line.text != null ? line.text.ToString() : "undefined");
@@ -2080,6 +2081,7 @@
string[] ins;
int insert_lines;
int old_line_count;
+ bool carriage_return = false;
NoRecalc = true;
@@ -2092,27 +2094,41 @@
ins = s.Split(new char[] {'\n'});
- for (int j = 0; j < ins.Length; j++) {
- if (ins[j].EndsWith("\r")) {
- ins[j] = ins[j].Substring(0, ins[j].Length - 1);
- }
- }
-
insert_lines = ins.Length;
old_line_count = lines;
-
+
// Bump the text at insertion point a line down if we're inserting more than one line
if (insert_lines > 1) {
Split(line, pos);
+ line.soft_break = false;
// Remainder of start line is now in base_line + 1
}
+ if (ins [0].EndsWith ("\r")) {
+ ins [0] = ins[0].Substring (0, ins[0].Length - 1);
+ carriage_return = true;
+ }
+
// Insert the first line
InsertString(tag, pos, ins[0]);
+ if (carriage_return) {
+ Line l = GetLine (base_line);
+ l.carriage_return = true;
+ }
+
if (insert_lines > 1) {
for (i = 1; i < insert_lines; i++) {
+ carriage_return = false;
+ if (ins [i].EndsWith ("\r")) {
+ ins [i] = ins[i].Substring (0, ins[i].Length - 1);
+ carriage_return = true;
+ }
Add(base_line + i, ins[i], line.alignment, tag.font, tag.color);
+ if (carriage_return) {
+ Line l = GetLine (base_line + i);
+ l.carriage_return = true;
+ }
}
if (!s.EndsWith("\n\n")) {
this.Combine(base_line + (lines - old_line_count) - 1, base_line + lines - old_line_count);
@@ -2132,7 +2148,6 @@
}
DisplayCaret ();
}
-
}
// Inserts a character at the given position
@@ -2153,6 +2168,7 @@
line.text.Insert(pos, s);
tag.length += len;
+ // TODO: sometimes getting a null tag here when pasting ???
tag = tag.next;
while (tag != null) {
tag.start += len;
@@ -2248,6 +2264,43 @@
}
}
+ internal void DeleteMultiline (Line start_line, int pos, int length)
+ {
+ Marker start = new Marker ();
+ Marker end = new Marker ();
+ int start_index = LineTagToCharIndex (start_line, pos);
+
+ start.line = start_line;
+ start.pos = pos;
+ start.tag = LineTag.FindTag (start_line, pos);
+
+ CharIndexToLineTag (start_index + length, out end.line,
+ out end.tag, out end.pos);
+
+ if (start.line == end.line) {
+ DeleteChars (start.tag, pos, end.pos - pos);
+ } else {
+
+ // Delete first and last lines
+ DeleteChars (start.tag, start.pos, start.line.text.Length - start.pos);
+ DeleteChars (end.line.tags, 0, end.pos);
+
+ int current = start.line.line_no + 1;
+ if (current < end.line.line_no) {
+ for (int i = end.line.line_no - 1; i >= current; i--) {
+ Delete (i);
+ }
+ }
+
+ // BIG FAT WARNING - selection_end.line might be stale due
+ // to the above Delete() call. DONT USE IT before hitting the end of this method!
+
+ // Join start and end
+ Combine (start.line.line_no, current);
+ }
+ }
+
+
// Deletes n characters at the given position; it will not delete past line limits
// pos is 0-based
internal void DeleteChars(LineTag tag, int pos, int count) {
@@ -2535,6 +2588,9 @@
new_line = GetLine(line.line_no + 1);
+ line.carriage_return = false;
+ new_line.carriage_return = line.carriage_return;
+
if (soft) {
if (move_caret) {
caret.line = new_line;
@@ -2565,6 +2621,10 @@
// Now transfer our tags from this line to the next
new_line = GetLine(line.line_no + 1);
+
+ line.carriage_return = false;
+ new_line.carriage_return = line.carriage_return;
+
line.recalc = true;
new_line.recalc = true;
@@ -3303,6 +3363,8 @@
internal void ReplaceSelection(string s, bool select_new) {
int i;
+ undo.BeginCompoundAction ();
+
int selection_start_pos = LineTagToCharIndex (selection_start.line, selection_start.pos);
// First, delete any selected text
if ((selection_start.pos != selection_end.pos) || (selection_start.line != selection_end.line)) {
@@ -3344,7 +3406,8 @@
}
Insert(selection_start.line, null, selection_start.pos, true, s);
-
+ undo.RecordInsertString (selection_start.line, selection_start.pos, s);
+
if (!select_new) {
CharIndexToLineTag(selection_start_pos + s.Length, out selection_start.line,
out selection_start.tag, out selection_start.pos);
@@ -3370,6 +3433,8 @@
SetSelectionVisible (true);
}
+
+ undo.EndCompoundAction ();
}
internal void CharIndexToLineTag(int index, out Line line_out, out LineTag tag_out, out int pos) {
@@ -4564,6 +4629,8 @@
DeleteChars,
CursorMove,
Mark,
+ CompoundBegin,
+ CompoundEnd,
}
internal class Action {
@@ -4653,23 +4720,40 @@
internal void Undo() {
Action action;
+ int compound_stack = 0;
if (undo_actions.Count == 0) {
return;
}
- action = (Action)undo_actions.Pop();
+
- // Put onto redo stack
- redo_actions.Push(action);
+ do {
+ action = (Action)undo_actions.Pop();
- // Do the thing
- switch(action.type) {
+ // Put onto redo stack
+ redo_actions.Push(action);
+
+ // Do the thing
+ switch(action.type) {
+ case ActionType.CompoundEnd:
+ compound_stack++;
+ break;
+
+ case ActionType.CompoundBegin:
+ compound_stack--;
+ break;
+
+ case ActionType.InsertString:
+ document.DeleteMultiline (document.GetLine (action.line_no),
+ action.pos, ((string) action.data).Length + 1);
+ break;
+
case ActionType.InsertChar: {
// FIXME - implement me
break;
}
-
+
case ActionType.DeleteChars: {
this.Insert(document.GetLine(action.line_no), action.pos, (Line)action.data);
Undo(); // Grab the cursor location
@@ -4699,7 +4783,8 @@
//if (document.CaretMoved != null) document.CaretMoved(this, EventArgs.Empty);
break;
}
- }
+ }
+ } while (compound_stack > 0);
}
internal void Redo() {
@@ -4710,6 +4795,23 @@
#endregion // Internal Methods
#region Private Methods
+
+ public void BeginCompoundAction ()
+ {
+ Action cb = new Action ();
+ cb.type = ActionType.CompoundBegin;
+
+ undo_actions.Push (cb);
+ }
+
+ public void EndCompoundAction ()
+ {
+ Action ce = new Action ();
+ ce.type = ActionType.CompoundEnd;
+
+ undo_actions.Push (ce);
+ }
+
// pos = 1-based
public void RecordDeleteChars(Line line, int pos, int length) {
RecordDelete(line, pos, line, pos + length - 1);
@@ -4733,6 +4835,18 @@
undo_actions.Push(a);
}
+ public void RecordInsertString (Line line, int pos, string str)
+ {
+ Action a = new Action ();
+
+ a.type = ActionType.InsertString;
+ a.data = str;
+ a.line_no = line.line_no;
+ a.pos = pos;
+
+ undo_actions.Push (a);
+ }
+
public void RecordCursor() {
if (document.caret.line == null) {
return;
_______________________________________________
Mono-winforms-list maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-winforms-list