int cursor_x = document.selection_start.pos;
int cursor_y = document.selection_start.line.line_no;
- // If we have an empty just added line, tell our code to re-use it
+ // The RFT parser by default, when finds our x cursor in 0, it thinks if needs to
+ // add a new line; but in *this* scenario the line is already created, so force it to reuse it.
// Hackish, but works without touching the heart of the buggy parser.
- if (cursor_x == 0 && document.GetLine (cursor_y).text.Length == 0)
+ if (cursor_x == 0)
reuse_line = true;
InsertRTFFromStream(data, cursor_x, cursor_y, out x, out y, out chars);
data.Close();
- document.CharIndexToLineTag(sel_start + chars + (y - document.selection_start.line.line_no) * 2, out line, out tag, out sel_start);
+ int nl_length = document.LineEndingLength (XplatUI.RunningOnUnix ? LineEnding.Rich : LineEnding.Hard);
+ document.CharIndexToLineTag(sel_start + chars + (y - document.selection_start.line.line_no) * nl_length,
+ out line, out tag, out sel_start);
+ if (sel_start >= line.text.Length)
+ sel_start = line.text.Length -1;
+
document.SetSelection(line, sel_start);
document.PositionCaret(line, sel_start);
document.DisplayCaret();
}
set {
+ // TextBox/TextBoxBase don't set Modified in this same property
+ Modified = true;
base.SelectedText = value;
}
}
}
}
- [MonoInternalNote ("Emit unicode and other special characters properly")]
+ static readonly char [] ReservedRTFChars = new char [] { '\\', '{', '}' };
+
private void EmitRTFText(StringBuilder rtf, string text) {
- rtf.Append(text);
+ int start = rtf.Length;
+ int count = text.Length;
+
+ // First emit simple unicode chars as escaped
+ EmitEscapedUnicode (rtf, text);
+
+ // This method emits user text *only*, so it's safe to escape any reserved rtf chars
+ // Escape '\' first, since it is used later to escape the other chars
+ if (text.IndexOfAny (ReservedRTFChars) > -1) {
+ rtf.Replace ("\\", "\\\\", start, count);
+ rtf.Replace ("{", "\\{", start, count);
+ rtf.Replace ("}", "\\}", start, count);
+ }
+ }
+
+ // The chars to be escaped use "\'" + its hexadecimal value.
+ private void EmitEscapedUnicode (StringBuilder sb, string text)
+ {
+ int pos;
+ int start = 0;
+
+ while ((pos = IndexOfNonAscii (text, start)) > -1) {
+ sb.Append (text, start, pos - start);
+
+ int n = (int)text [pos];
+ sb.Append ("\\'");
+ sb.Append (n.ToString ("X"));
+
+ start = pos + 1;
+ }
+
+ // Append remaining (maybe all) the text value.
+ if (start < text.Length)
+ sb.Append (text, start, text.Length - start);
+ }
+
+ // MS seems to be escaping values larger than 0x80
+ private int IndexOfNonAscii (string text, int startIndex)
+ {
+ for (int i = startIndex; i < text.Length; i++) {
+ int n = (int)text [i];
+ if (n < 0 || n >= 0x80)
+ return i;
+ }
+
+ return -1;
}
// start_pos and end_pos are 0-based