public void Replace(Int32 offset, Int32 length, String content) { if (content == null) { throw new ArgumentNullException("content"); } if (length <= 0 && content.Length <= 0) { return; } _isChanging = true; VerifyOffsetRange(offset); VerifyLengthRange(offset, length); if (Changing != null) { Changing(this, EventArgs.Empty); } var updates = new List <DocumentUpdate>(); DocumentUpdate update4insertion = null, update4deletion = null; if (length > 0) { update4deletion = GenerateUpdate(offset, length, String.Empty); updates.Add(update4deletion); } if (content.Length > 0) { update4insertion = GenerateUpdate(offset, 0, content); updates.Add(update4insertion); } if (length > 0) { _anchorTree.RemoveText(offset, length); _lineMgr.Remove(offset, length, update4deletion); } if (content.Length > 0) { _anchorTree.InsertText(offset, content.Length); _lineMgr.Insert(offset, content, update4insertion); } _rope.Replace(offset, length, content.ToArray()); var e = new DocumentUpdateEventArgs(updates); if (Changed != null) { Changed(this, e); } _undoStack.AddOperation(new DocumentEditingOperation(this, updates)); _isChanging = false; #if DEBUG _anchorTree.VerifySelf(); _lineTree.VerifySelf(); #endif }
private DocumentUpdate GenerateUpdate(Int32 offset, Int32 length, String content) { var docUpdate = new DocumentUpdate(); docUpdate.Offset = offset; docUpdate.InsertionLength = content.Length; docUpdate.RemovalLength = length; docUpdate.InsertionText = content; docUpdate.RemovalText = length > 0 ? GetTextAt(offset, length) : String.Empty; return(docUpdate); }
internal void Insert(Int32 offset, String text, DocumentUpdate update) { DocumentLine line = _lineTree.GetLineByOffset(offset); // 不允许在\r和\n之间插入文本 SimpleSegment seg = DocumentLineSeeker.NextLineDelimiter(text, 0); if (seg == SimpleSegment.Invalid) { update.LineNumberNeedUpdate = line.LineNumber; // 插入的文本没有新的行,直接加入当前行 SetLineLength(line, line._exactLength + text.Length); return; } update.LineNumberNeedUpdate = line.LineNumber; update.NewStartLineNumber = update.LineNumberNeedUpdate + 1; // 和前置行合并 Int32 lineOffset = line.StartOffset; Int32 lineBreakOffset = offset + seg.EndOffset; Int32 lengthAfterInsertion = lineOffset + line._exactLength - offset; Int32 delimiterLengthAfterInsertion = line._delimiterLength; line._delimiterLength = seg.Length; SetLineLength(line, lineBreakOffset - lineOffset); Int32 lastDelimeterEnd = seg.EndOffset; seg = DocumentLineSeeker.NextLineDelimiter(text, lastDelimeterEnd); // 中间行处理 while (seg != SimpleSegment.Invalid) { #if DEBUG var newLine = new DocumentLine(_doc); #else var newLine = new DocumentLine(); #endif ++update.NewLineCount; newLine._delimiterLength = seg.Length; newLine._exactLength = seg.EndOffset - lastDelimeterEnd; _lineTree.InsertLineAfter(line, newLine); line = newLine; lastDelimeterEnd = seg.EndOffset; seg = DocumentLineSeeker.NextLineDelimiter(text, lastDelimeterEnd); } // 和后置行合并 #if DEBUG var afterLine = new DocumentLine(_doc); #else var afterLine = new DocumentLine(); #endif ++update.NewLineCount; afterLine._delimiterLength = delimiterLengthAfterInsertion; afterLine._exactLength = lengthAfterInsertion + (text.Length - lastDelimeterEnd); _lineTree.InsertLineAfter(line, afterLine); }
public DocumentUpdateEventArgs(DocumentUpdate update) : this(new DocumentUpdate[] { update, }) { }
internal void Remove(Int32 offset, Int32 length, DocumentUpdate update) { if (offset == 0 && length == _doc.Length) { // 清除后会有空行 update.LineNumberNeedUpdate = 1; if (_lineTree.LineCount > 1) { update.RemovedStartLineNumber = 2; update.RemovedLineCount = _lineTree.LineCount - 1; } // 全删,直接重置 _lineTree.Clear(); return; } DocumentLine line = _lineTree.GetLineByOffset(offset); // 不允许在\r和\n之间删除文本 Int32 lineOffset = line.StartOffset; Int32 lengthAfterDeletion = lineOffset + line._exactLength - offset; if ((line._delimiterLength > 0 && length < lengthAfterDeletion) || (line._delimiterLength == 0 && length <= lengthAfterDeletion)) { update.LineNumberNeedUpdate = line.LineNumber; // 不需要删除行 SetLineLength(line, line._exactLength - length); return; } Int32 removedLineNum = -1, removedLineCnt = 0; DocumentLine firstLine = line; Int32 lengthBeforeDeletion = offset - lineOffset; DocumentLine nextLine = line.NextLine; removedLineNum = line.LineNumber; update.LineNumberNeedUpdate = removedLineNum; if (lengthBeforeDeletion == 0) { ++removedLineCnt; // 当前行需要删除 _lineTree.RemoveLine(line); firstLine = null; } else { ++removedLineNum; SetLineLength(line, line._exactLength - lengthAfterDeletion); line._delimiterLength = 0; } line = nextLine; length -= lengthAfterDeletion; // 删除中间行 while (length > 0) { if (length < line._exactLength) { break; } nextLine = line.NextLine; _lineTree.RemoveLine(line); ++removedLineCnt; length -= line._exactLength; line = nextLine; } if (line != null) { if (firstLine != null) { // 前置行没有删除,则合并这两行 SetLineLength(firstLine, firstLine._exactLength + (line._exactLength - length)); firstLine._delimiterLength = line._delimiterLength; _lineTree.RemoveLine(line); ++removedLineCnt; } else { update.LineNumberNeedUpdate += removedLineCnt; // 没有前置行了,保留该行 SetLineLength(line, line._exactLength - length); } } else { update.LineNumberNeedUpdate = -1; } if (removedLineCnt > 0) { update.RemovedStartLineNumber = removedLineNum; update.RemovedLineCount = removedLineCnt; } }