示例#1
0
        //------------------------------------------------------
        //
        //  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);
        }
示例#2
0
        // 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);
        }
示例#3
0
        // 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);
        }
示例#4
0
        // 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;
            }
        }
示例#5
0
 // 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();
         }
     }
 }
示例#6
0
        // 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!");
            }
        }
示例#7
0
        // 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!");
            }
        }
示例#8
0
        //------------------------------------------------------
        //
        //  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);
        }
示例#9
0
        // 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;
        } 
示例#10
0
        // 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;
            }
        }
示例#11
0
        // 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);
        }