Rope
The document: a flat table of TextBlock leaves with indexes over chars, codepoints, paragraph separators, heights and line widths. Every position query — char↔codepoint, char↔paragraph, Y↔block, X↔block — is O(log blocks); an edit costs O(edited block) plus O(log blocks), or O(blocks) when it changes the block count. Blocks lent to workers through Lease are immutable for the lease's lifetime: an edit clones a shared block instead of mutating it.
Remarks
public ScanProfile Profile{ get; set }The scan profile blocks are classified with; changing it re-summarizes every block.
Logical length in UTF-16 units; the same value as CharCount.
[ctor]public Rope(ScanProfile profile = null)Creates an empty document.
public static Rope FromChars(ReadOnlySpan<char> text, ScanProfile profile = null)Builds a document from UTF-16 text, cutting blocks at paragraph boundaries where possible.
public TextBlockFlags BlockFlags(int block)public int CopyChars(int start, int count, Span<char> destination)Copies logical chars [start, start+count); returns the number copied (clamped to the document and the destination).
public int CopyCodepointRange(int startCodepoint, int codepointCount, Span<char> destination)public int CopyTo(Span<char> destination)Copies the whole content; returns the number of chars written.
public int CopyTo(int start, int count, Span<char> destination)Copies logical chars [start, start+count); returns the number written.
public bool ContentEquals(ReadOnlySpan<char> other)True when the content equals other unit for unit; compares block by block without allocating.
public EditShape Insert(int charIndex, ReadOnlySpan<char> text)public EditShape Delete(int charIndex, int charCount)public EditShape InsertAtCodepoint(int cpIndex, ReadOnlySpan<char> text)public EditShape DeleteAtCodepoint(int cpIndex, int cpCount)public EditShape SetText(ReadOnlySpan<char> text)Replaces the whole content; the returned shape excludes the common prefix and suffix.
public EditShape Replace(int start, int removeCount, ReadOnlySpan<char> text)The one mutation: removes removeCount chars at start and inserts text there. Boundaries may not split a surrogate pair.
public void ResetLayout(in LayoutEstimate newEstimate)Resets every block's extent to an estimate under new layout parameters.
public void RefineEstimate(in LayoutEstimate newEstimate)Updates the estimation parameters without discarding measured blocks; estimated blocks are re-estimated, and edited blocks re-estimate their height.
Records a block's measured extent until the layout is reset. An edit of the block returns its height to an estimate and leaves its widths at this measurement until the block is measured again. A measurement taken with the block's paragraph cut at a window edge is exact = false: it replaces an estimate or an earlier inexact measurement, never an exact one.
public BlockLease Lease(int first, int count)Pins blocks [first, first+count) for a worker: their content stays immutable until BlockLease.Dispose (main thread). Reads through the lease are safe from any thread.
