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);
Exemple #7
0
 public static TextBuffer FromText(string text, bool normalizeEndMarkers = false)
 {
     return(new TextBuffer(TextData.FromString(text, normalizeEndMarkers)));
 }