//------------------------------------------------------ // // Constructors // //------------------------------------------------------ #region Constructors // Creates a TextTreeRootTextBlock instance. internal TextTreeRootTextBlock() { TextTreeTextBlock block; // Allocate an initial block with just two characters -- one for // each edge of the root node. The block will grow when/if // additional content is added. block = new TextTreeTextBlock(2); block.InsertAtNode(this, ElementEdge.AfterStart); }
// Splits this block at the current gap offset. // Only called during a text insert, when the block is full. // If GapOffset < TextTreeTextBlock.MaxBlockSize / 2, returns // a new block with the left text, otherwise returns a new // block with the right text. internal TextTreeTextBlock SplitBlock() { TextTreeTextBlock newBlock; bool insertBefore; Invariant.Assert(_gapSize == 0, "Splitting non-full block!"); Invariant.Assert(_text.Length == MaxBlockSize, "Splitting non-max sized block!"); newBlock = new TextTreeTextBlock(MaxBlockSize); if (_gapOffset < MaxBlockSize / 2) { // Copy the left text over to the new block. Array.Copy(_text, 0, newBlock._text, 0, _gapOffset); newBlock._gapOffset = _gapOffset; newBlock._gapSize = MaxBlockSize - _gapOffset; // Remove the left text from this block. _gapSize += _gapOffset; _gapOffset = 0; // New node preceeds this one. insertBefore = true; } else { // Copy the right text over to the new block. Array.Copy(_text, _gapOffset, newBlock._text, _gapOffset, MaxBlockSize - _gapOffset); Invariant.Assert(newBlock._gapOffset == 0); newBlock._gapSize = _gapOffset; // Remove the left text from this block. _gapSize = MaxBlockSize - _gapOffset; // New node follows this one. insertBefore = false; } // Add the new node to the splay tree. newBlock.InsertAtNode(this, insertBefore); return(newBlock); }
// Token: 0x06003DAD RID: 15789 RVA: 0x0011C690 File Offset: 0x0011A890 private static TextTreeTextBlock FindBlock(TextTreeRootTextBlock rootTextBlock, int offset, out int localOffset) { int num; TextTreeTextBlock textTreeTextBlock = (TextTreeTextBlock)rootTextBlock.ContainedNode.GetSiblingAtOffset(offset, out num); if (textTreeTextBlock.LeftSymbolCount == offset) { TextTreeTextBlock textTreeTextBlock2 = (TextTreeTextBlock)textTreeTextBlock.GetPreviousNode(); if (textTreeTextBlock2 != null) { textTreeTextBlock = textTreeTextBlock2; num -= textTreeTextBlock.SymbolCount; Invariant.Assert(num >= 0); } } localOffset = offset - num; Invariant.Assert(localOffset >= 0 && localOffset <= textTreeTextBlock.Count); return(textTreeTextBlock); }
// Removes a run of nodes from a tree. internal static void Remove(TextTreeTextBlock firstNode, TextTreeTextBlock lastNode) { SplayTreeNode leftTree; SplayTreeNode rightTree; SplayTreeNode rootNode; SplayTreeNode containerNode; // // Break the tree into three subtrees. // leftTree = firstNode.GetPreviousNode(); if (leftTree != null) { // Splitting moves leftTree to local root. leftTree.Split(); containerNode = leftTree.ParentNode; leftTree.ParentNode = null; // We'll fixup leftTree.ParentNode.ContainedNode below. // Join requires that leftTree has a null ParentNode. } else { // There are no preceeding nodes. containerNode = firstNode.GetContainingNode(); } rightTree = lastNode.Split(); // // Recombine the two outer trees. // rootNode = SplayTreeNode.Join(leftTree, rightTree); if (containerNode != null) { containerNode.ContainedNode = rootNode; } if (rootNode != null) { rootNode.ParentNode = containerNode; } }
// Token: 0x06003DA9 RID: 15785 RVA: 0x0011C5B8 File Offset: 0x0011A7B8 internal static void ReadText(TextTreeRootTextBlock rootTextBlock, int offset, int count, char[] chars, int startIndex) { if (count > 0) { int logicalOffset; TextTreeTextBlock textTreeTextBlock = TextTreeText.FindBlock(rootTextBlock, offset, out logicalOffset); for (;;) { Invariant.Assert(textTreeTextBlock != null, "Caller asked for too much text!"); int num = textTreeTextBlock.ReadText(logicalOffset, count, chars, startIndex); logicalOffset = 0; count -= num; if (count == 0) { break; } startIndex += num; textTreeTextBlock = (TextTreeTextBlock)textTreeTextBlock.GetNextNode(); } } }
// Token: 0x06003DAF RID: 15791 RVA: 0x0011C7F8 File Offset: 0x0011A9F8 private static void InsertTextRight(TextTreeTextBlock leftBlock, object text, int textOffset) { int num = TextContainer.GetTextLength(text); if (leftBlock.GapOffset == leftBlock.Count) { TextTreeTextBlock textTreeTextBlock = (TextTreeTextBlock)leftBlock.GetNextNode(); if (textTreeTextBlock != null) { int num2 = Math.Min(textTreeTextBlock.FreeCapacity, num - textOffset); textTreeTextBlock.InsertText(0, text, num - num2, num); num -= num2; } } if (textOffset < num) { int num3 = 1; TextTreeTextBlock textTreeTextBlock2 = leftBlock.SplitBlock(); int num2 = Math.Min(textTreeTextBlock2.FreeCapacity, num - textOffset); textTreeTextBlock2.InsertText(0, text, num - num2, num); num -= num2; if (textOffset < num) { textOffset += leftBlock.InsertText(leftBlock.Count, text, textOffset, num); if (textOffset < num) { num3 += (num - textOffset + 4096 - 1) / 4096; } } for (int i = 0; i < num3 - 1; i++) { TextTreeTextBlock textTreeTextBlock3 = new TextTreeTextBlock(4096); textOffset += textTreeTextBlock3.InsertText(0, text, textOffset, num); textTreeTextBlock3.InsertAtNode(leftBlock, false); leftBlock = textTreeTextBlock3; } Invariant.Assert(textOffset == num, "Not all text copied!"); } }
// Token: 0x06003DAE RID: 15790 RVA: 0x0011C700 File Offset: 0x0011A900 private static void InsertTextLeft(TextTreeTextBlock rightBlock, object text, int textOffset) { int num = -1; int textLength = TextContainer.GetTextLength(text); if (rightBlock.GapOffset == 0) { TextTreeTextBlock textTreeTextBlock = (TextTreeTextBlock)rightBlock.GetPreviousNode(); if (textTreeTextBlock != null) { textOffset += textTreeTextBlock.InsertText(textTreeTextBlock.Count, text, textOffset, textLength); } } if (textOffset < textLength) { int num2 = 1; TextTreeTextBlock textTreeTextBlock2 = rightBlock.SplitBlock(); textOffset += textTreeTextBlock2.InsertText(textTreeTextBlock2.Count, text, textOffset, textLength); if (textOffset < textLength) { int num3 = Math.Min(rightBlock.FreeCapacity, textLength - textOffset); num = textLength - num3; rightBlock.InsertText(0, text, num, textLength); if (textOffset < num) { num2 += (num - textOffset + 4096 - 1) / 4096; } } for (int i = 1; i < num2; i++) { TextTreeTextBlock textTreeTextBlock3 = new TextTreeTextBlock(4096); textOffset += textTreeTextBlock3.InsertText(0, text, textOffset, num); textTreeTextBlock3.InsertAtNode(textTreeTextBlock2, false); textTreeTextBlock2 = textTreeTextBlock3; } Invariant.Assert(num2 == 1 || textOffset == num, "Not all text copied!"); } }
//------------------------------------------------------ // // Private Methods // //------------------------------------------------------ #region Private Methods // Finds the TextTreeTextBlock that contains the specified char offset. // Returns the lower block for offsets that border two blocks. private static TextTreeTextBlock FindBlock(TextTreeRootTextBlock rootTextBlock, int offset, out int localOffset) { TextTreeTextBlock node; int nodeOffset; node = (TextTreeTextBlock)rootTextBlock.ContainedNode.GetSiblingAtOffset(offset, out nodeOffset); // If offset is between two blocks, make sure we return the lower of the two. if (node.LeftSymbolCount == offset) { TextTreeTextBlock previousBlock = (TextTreeTextBlock)node.GetPreviousNode(); if (previousBlock != null) { node = previousBlock; nodeOffset -= node.SymbolCount; Invariant.Assert(nodeOffset >= 0); } } localOffset = offset - nodeOffset; Invariant.Assert(localOffset >= 0 && localOffset <= node.Count); return(node); }
// Splits this block at the current gap offset. // Only called during a text insert, when the block is full. // If GapOffset < TextTreeTextBlock.MaxBlockSize / 2, returns // a new block with the left text, otherwise returns a new // block with the right text. internal TextTreeTextBlock SplitBlock() { TextTreeTextBlock newBlock; bool insertBefore; Invariant.Assert(_gapSize == 0, "Splitting non-full block!"); Invariant.Assert(_text.Length == MaxBlockSize, "Splitting non-max sized block!"); newBlock = new TextTreeTextBlock(MaxBlockSize); if (_gapOffset < MaxBlockSize / 2) { // Copy the left text over to the new block. Array.Copy(_text, 0, newBlock._text, 0, _gapOffset); newBlock._gapOffset = _gapOffset; newBlock._gapSize = MaxBlockSize - _gapOffset; // Remove the left text from this block. _gapSize += _gapOffset; _gapOffset = 0; // New node preceeds this one. insertBefore = true; } else { // Copy the right text over to the new block. Array.Copy(_text, _gapOffset, newBlock._text, _gapOffset, MaxBlockSize - _gapOffset); Invariant.Assert(newBlock._gapOffset == 0); newBlock._gapSize = _gapOffset; // Remove the left text from this block. _gapSize = MaxBlockSize - _gapOffset; // New node follows this one. insertBefore = false; } // Add the new node to the splay tree. newBlock.InsertAtNode(this, insertBefore); return newBlock; }
// Helper for InsertText. Inserts text to the right of an existing block. private static void InsertTextRight(TextTreeTextBlock leftBlock, object text, int textOffset) { int newBlockCount; TextTreeTextBlock rightBlock; TextTreeTextBlock neighborBlock; TextTreeTextBlock newBlock; int count; int textEndOffset; int i; textEndOffset = TextContainer.GetTextLength(text); if (leftBlock.GapOffset == leftBlock.Count) { // Try to fill neighbor block. neighborBlock = (TextTreeTextBlock)leftBlock.GetNextNode(); if (neighborBlock != null) { count = Math.Min(neighborBlock.FreeCapacity, textEndOffset - textOffset); neighborBlock.InsertText(0, text, textEndOffset - count, textEndOffset); textEndOffset -= count; } } if (textOffset < textEndOffset) { // Try adding just one block. newBlockCount = 1; rightBlock = leftBlock.SplitBlock(); // Fill up the right block. count = Math.Min(rightBlock.FreeCapacity, textEndOffset - textOffset); rightBlock.InsertText(0, text, textEndOffset - count, textEndOffset); textEndOffset -= count; if (textOffset < textEndOffset) { // Fill up the larger block. // We need to copy from the end of the text here. textOffset += leftBlock.InsertText(leftBlock.Count, text, textOffset, textEndOffset); if (textOffset < textEndOffset) { // We've filled both blocks, and there's still more text to copy. // Prepare to allocate some more blocks. newBlockCount += (textEndOffset - textOffset + TextTreeTextBlock.MaxBlockSize - 1) / TextTreeTextBlock.MaxBlockSize; } } for (i=0; i<newBlockCount-1; i++) { newBlock = new TextTreeTextBlock(TextTreeTextBlock.MaxBlockSize); textOffset += newBlock.InsertText(0, text, textOffset, textEndOffset); newBlock.InsertAtNode(leftBlock, false /* insertBefore */); leftBlock = newBlock; } Invariant.Assert(textOffset == textEndOffset, "Not all text copied!"); } }
// Token: 0x06003DB1 RID: 15793 RVA: 0x0011C95C File Offset: 0x0011AB5C internal TextTreeRootTextBlock() { TextTreeTextBlock textTreeTextBlock = new TextTreeTextBlock(2); textTreeTextBlock.InsertAtNode(this, ElementEdge.AfterStart); }