public TextLineList(TextData owner) { this.owner = owner; }
public static TextData ApplyEdit(TextData previous, TextLocation start, TextLocation end, TextData replacement) { // Optimized for the vast majority of text edits -- an edit (single-line, typically single-character) on the active line if (replacement.Lines.Count == 1 && start.Line == previous.ActiveLineIndex && end.Line == start.Line) { Debug.Assert(replacement.Lines[0].EndMarker == EndMarker.EOB); string editedLineText = previous.activeLine.Text.Substring(0, start.Index) + replacement.lines[0].Text + previous.activeLine.Text.Substring(end.Index); TextLine editedLine = new TextLine(editedLineText, previous.activeLine.EndMarker); return(new TextData(previous.beforeBlock, editedLine, previous.afterBlock, previous.TextLength + editedLine.Length - previous.activeLine.Length)); } // All other cases require reconstruction of the before/after blocks (in the current implementation -- more intelligent // mechanisms could be built to increase memory reuse). This is still not terrible, as the untouched lines are reused; only the // blocks (arrays of line references) are recreated. // After this edit, we assume that the *end* of the inserted text is the active line. int linesAdded = replacement.Lines.Count - 1; int linesRemoved = end.Line - start.Line; int totalLines = previous.Lines.Count + linesAdded - linesRemoved; int beforeLines = start.Line + replacement.Lines.Count - 1; int afterLines = totalLines - beforeLines - 1; Debug.Assert(totalLines == beforeLines + afterLines + 1, "Miscalculation in line totals"); var before = new TextLine[beforeLines]; var after = new TextLine[afterLines]; TextLine newActiveLine; string editLineText; int newLength = 0; // There are two cases -- the replacement is only one line (so we only end up creating one new TextLine), or it is more than one // (so we end up creating 2 new TextLines). There are other opportunities for optimization in the latter (inserting at index 0, or // the last line of the replacement being empty) to consider later. if (replacement.Lines.Count == 1) { for (int i = 0; i < beforeLines; i++) { before[i] = previous.Lines[i]; newLength += before[i].LengthWithEndMarker; } editLineText = previous.Lines[start.Line].Text.Substring(0, start.Index) + replacement.Lines[0].Text + previous.Lines[end.Line].Text.Substring(end.Index); newActiveLine = new TextLine(editLineText, previous.Lines[end.Line].EndMarker); newLength += newActiveLine.LengthWithEndMarker; for (int i = 0; i < afterLines; i++) { after[i] = previous.Lines[end.Line + i + 1]; newLength += after[i].LengthWithEndMarker; } } else { for (int i = 0; i < start.Line; i++) { before[i] = previous.Lines[i]; newLength += before[i].LengthWithEndMarker; } editLineText = previous.Lines[start.Line].Text.Substring(0, start.Index) + replacement.Lines[0].Text; before[start.Line] = new TextLine(editLineText, replacement.Lines[0].EndMarker); newLength += before[start.Line].LengthWithEndMarker; for (int i = 1; i < replacement.Lines.Count - 1; i++) { before[start.Line + i] = replacement.Lines[i]; newLength += before[start.Line + i].LengthWithEndMarker; } editLineText = replacement.Lines[replacement.Lines.Count - 1].Text + previous.Lines[end.Line].Text.Substring(end.Index); newActiveLine = new TextLine(editLineText, previous.Lines[end.Line].EndMarker); newLength += newActiveLine.LengthWithEndMarker; for (int i = 0; i < afterLines; i++) { after[i] = previous.Lines[end.Line + i + 1]; newLength += after[i].LengthWithEndMarker; } } return(new TextData(before, newActiveLine, after, newLength)); }
static TextData() { Empty = TextData.FromString(null); }
public TextData GetSubrange(TextLocation start, TextLocation end) { return(TextData.FromString(this.ToString(start, end))); }
public abstract bool Write(TextLocation start, TextLocation end, TextData replacement);
protected abstract List <TextFormatInfo> Parse(TextData textData, Func <bool> isCanceled);
public static TextBuffer FromText(string text, bool normalizeEndMarkers = false) { return(new TextBuffer(TextData.FromString(text, normalizeEndMarkers))); }