/// <summary> /// Finds the next new line character starting at offset. /// </summary> /// <param name="text">The text source to search in.</param> /// <param name="offset">The starting offset for the search.</param> /// <param name="newLineType">The string representing the new line that was found, or null if no new line was found.</param> /// <returns> /// The position of the first new line starting at or after <paramref name="offset" />, /// or -1 if no new line was found. /// </returns> public static int FindNextNewLine(ITextSource text, int offset, out string newLineType) { if (text == null) { throw new ArgumentNullException("text"); } if (offset < 0 || offset > text.TextLength) { throw new ArgumentOutOfRangeException("offset", offset, "offset is outside of text source"); } var s = NewLineFinder.NextNewLine(text, offset); if (s == SimpleSegment.Invalid) { newLineType = null; return(-1); } if (s.Length == 2) { newLineType = "\r\n"; } else if (text.GetCharAt(s.Offset) == '\n') { newLineType = "\n"; } else { newLineType = "\r"; } return(s.Offset); }
/// <summary> /// Normalizes all new lines in <paramref name="input" /> to be <paramref name="newLine" />. /// </summary> public static string NormalizeNewLines(string input, string newLine) { if (input == null) { return(null); } if (!IsNewLine(newLine)) { throw new ArgumentException("newLine must be one of the known newline sequences"); } var ds = NewLineFinder.NextNewLine(input, 0); if (ds == SimpleSegment.Invalid) // text does not contain any new lines { return(input); } var b = new StringBuilder(input.Length); var lastEndOffset = 0; do { b.Append(input, lastEndOffset, ds.Offset - lastEndOffset); b.Append(newLine); lastEndOffset = ds.EndOffset; ds = NewLineFinder.NextNewLine(input, lastEndOffset); } while (ds != SimpleSegment.Invalid); // remaining string (after last newline) b.Append(input, lastEndOffset, input.Length - lastEndOffset); return(b.ToString()); }
public void Rebuild() { // keep the first document line var ls = documentLineTree.GetByNumber(1); // but mark all other lines as deleted, and detach them from the other nodes for (var line = ls.NextLine; line != null; line = line.NextLine) { line.isDeleted = true; line.parent = line.left = line.right = null; } // Reset the first line to detach it from the deleted lines ls.ResetLine(); var ds = NewLineFinder.NextNewLine(document, 0); var lines = new List <DocumentLine>(); var lastDelimiterEnd = 0; while (ds != SimpleSegment.Invalid) { ls.TotalLength = ds.Offset + ds.Length - lastDelimiterEnd; ls.DelimiterLength = ds.Length; lastDelimiterEnd = ds.Offset + ds.Length; lines.Add(ls); ls = new DocumentLine(document); ds = NewLineFinder.NextNewLine(document, lastDelimiterEnd); } ls.TotalLength = document.TextLength - lastDelimiterEnd; lines.Add(ls); documentLineTree.RebuildTree(lines); foreach (var lineTracker in lineTrackers) { lineTracker.RebuildDocument(); } }
public void Insert(int offset, ITextSource text) { var line = documentLineTree.GetByOffset(offset); var lineOffset = line.Offset; Debug.Assert(offset <= lineOffset + line.TotalLength); if (offset > lineOffset + line.Length) { Debug.Assert(line.DelimiterLength == 2); // we are inserting in the middle of a delimiter // shorten line SetLineLength(line, line.TotalLength - 1); // add new line line = InsertLineAfter(line, 1); line = SetLineLength(line, 1); } var ds = NewLineFinder.NextNewLine(text, 0); if (ds == SimpleSegment.Invalid) { // no newline is being inserted, all text is inserted in a single line //line.InsertedLinePart(offset - line.Offset, text.Length); SetLineLength(line, line.TotalLength + text.TextLength); return; } //DocumentLine firstLine = line; //firstLine.InsertedLinePart(offset - firstLine.Offset, ds.Offset); var lastDelimiterEnd = 0; while (ds != SimpleSegment.Invalid) { // split line segment at line delimiter var lineBreakOffset = offset + ds.Offset + ds.Length; lineOffset = line.Offset; var lengthAfterInsertionPos = lineOffset + line.TotalLength - (offset + lastDelimiterEnd); line = SetLineLength(line, lineBreakOffset - lineOffset); var newLine = InsertLineAfter(line, lengthAfterInsertionPos); newLine = SetLineLength(newLine, lengthAfterInsertionPos); line = newLine; lastDelimiterEnd = ds.Offset + ds.Length; ds = NewLineFinder.NextNewLine(text, lastDelimiterEnd); } //firstLine.SplitTo(line); // insert rest after last delimiter if (lastDelimiterEnd != text.TextLength) { //line.InsertedLinePart(0, text.Length - lastDelimiterEnd); SetLineLength(line, line.TotalLength + text.TextLength - lastDelimiterEnd); } }