internal bool auto_word_select;
internal int bullet_indent;
internal bool detect_urls;
+ private bool reuse_line; // Sometimes we are loading text with already available lines
internal int margin_right;
internal float zoom;
private StringBuilder rtf_line;
sel_start = document.LineTagToCharIndex(document.selection_start.line, document.selection_start.pos);
data = new MemoryStream(Encoding.ASCII.GetBytes(value), false);
- InsertRTFFromStream(data, document.selection_start.pos, document.selection_start.line.line_no, out x, out y, out chars);
+ int cursor_x = document.selection_start.pos;
+ int cursor_y = document.selection_start.line.line_no;
+
+ // 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)
+ 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;
}
}
}
for (i = 1; i < document.Lines; i++) {
- bytes = encoding.GetBytes(document.GetLine(i).text.ToString());
+ // Normalize the new lines to the system ones
+ string line_text = document.GetLine (i).TextWithoutEnding () + Environment.NewLine;
+ bytes = encoding.GetBytes(line_text);
data.Write(bytes, 0, bytes.Length);
}
bytes = encoding.GetBytes(document.GetLine(document.Lines).text.ToString());
rtf_chars += rtf_line.Length;
-
-
- if (rtf_cursor_x == 0) {
+ // Try to re-use if we are told so - this usually happens when we are inserting a flow of rtf text
+ // with an already alive line.
+ if (rtf_cursor_x == 0 && !reuse_line) {
if (newline && rtf_line.ToString ().EndsWith (Environment.NewLine) == false)
rtf_line.Append (Environment.NewLine);
if (line.Text.EndsWith (Environment.NewLine) == false)
line.Text += Environment.NewLine;
}
+
+ reuse_line = false; // sanity assignment - in this case we have already re-used one line.
}
if (newline) {
}
}
- [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