// Token: 0x060035C1 RID: 13761 RVA: 0x000F43D0 File Offset: 0x000F25D0
        internal int GetSymbolOffset(uint treeGeneration)
        {
            int           num           = 0;
            SplayTreeNode splayTreeNode = this;

            while (splayTreeNode.Generation != treeGeneration || splayTreeNode.SymbolOffsetCache < 0)
            {
                splayTreeNode.Splay();
                num += splayTreeNode.LeftSymbolCount;
                num++;
                splayTreeNode = splayTreeNode.ParentNode;
            }
            num                   += splayTreeNode.SymbolOffsetCache;
            this.Generation        = treeGeneration;
            this.SymbolOffsetCache = num;
            return(num);
        }
Beispiel #2
0
        // Dumps a node and all following nodes "flat" -- in notation similar to xaml.
        internal static void DumpNodeFlatRecursive(SplayTreeNode node)
        {
            for (; node != null; node = node.GetNextNode())
            {
                Debug.Write("<" + GetFlatPrefix(node) + node.DebugId);

                if (node.ContainedNode != null)
                {
                    Debug.Write(">");
                    DumpNodeFlatRecursive(node.GetFirstContainedNode());
                    Debug.Write("</" + GetFlatPrefix(node) + node.DebugId + ">");
                }
                else
                {
                    Debug.Write("/>");
                }
            }
        }
Beispiel #3
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;
            }
        }
 // Token: 0x060035C6 RID: 13766 RVA: 0x000F460C File Offset: 0x000F280C
 internal static void Join(SplayTreeNode root, SplayTreeNode leftSubTree, SplayTreeNode rightSubTree)
 {
     root.LeftChildNode  = leftSubTree;
     root.RightChildNode = rightSubTree;
     Invariant.Assert(root.Role == SplayTreeNodeRole.LocalRoot);
     if (leftSubTree != null)
     {
         leftSubTree.ParentNode = root;
         root.LeftSymbolCount   = leftSubTree.LeftSymbolCount + leftSubTree.SymbolCount;
         root.LeftCharCount     = leftSubTree.LeftCharCount + leftSubTree.IMECharCount;
     }
     else
     {
         root.LeftSymbolCount = 0;
         root.LeftCharCount   = 0;
     }
     if (rightSubTree != null)
     {
         rightSubTree.ParentNode = root;
     }
 }
Beispiel #5
0
        // Inserts a node at a specified position.
        internal void InsertAtNode(SplayTreeNode positionNode, ElementEdge edge)
        {
            SplayTreeNode locationNode;
            bool          insertBefore;

            if (edge == ElementEdge.BeforeStart || edge == ElementEdge.AfterEnd)
            {
                // Insert to this node's tree.
                InsertAtNode(positionNode, edge == ElementEdge.BeforeStart /* insertBefore */);
            }
            else
            {
                // Insert to this node's contained tree.

                if (edge == ElementEdge.AfterStart)
                {
                    locationNode = positionNode.GetFirstContainedNode();
                    insertBefore = true;
                }
                else // ElementEdge == BeforeEnd
                {
                    locationNode = positionNode.GetLastContainedNode();
                    insertBefore = false;
                }

                if (locationNode == null)
                {
                    // Inserting the first contained node.
                    positionNode.ContainedNode = this;
                    this.ParentNode            = positionNode;
                    Invariant.Assert(this.LeftChildNode == null);
                    Invariant.Assert(this.RightChildNode == null);
                    Invariant.Assert(this.LeftSymbolCount == 0);
                }
                else
                {
                    InsertAtNode(locationNode, insertBefore);
                }
            }
        }
        // Token: 0x060035C2 RID: 13762 RVA: 0x000F442C File Offset: 0x000F262C
        internal int GetIMECharOffset()
        {
            int           num           = 0;
            SplayTreeNode splayTreeNode = this;

            for (;;)
            {
                splayTreeNode.Splay();
                num          += splayTreeNode.LeftCharCount;
                splayTreeNode = splayTreeNode.ParentNode;
                if (splayTreeNode == null)
                {
                    break;
                }
                TextTreeTextElementNode textTreeTextElementNode = splayTreeNode as TextTreeTextElementNode;
                if (textTreeTextElementNode != null)
                {
                    num += textTreeTextElementNode.IMELeftEdgeCharCount;
                }
            }
            return(num);
        }
        // Token: 0x060035C0 RID: 13760 RVA: 0x000F4378 File Offset: 0x000F2578
        internal SplayTreeNode GetNextNode()
        {
            SplayTreeNode splayTreeNode = this.RightChildNode;

            if (splayTreeNode != null)
            {
                for (;;)
                {
                    SplayTreeNode leftChildNode = splayTreeNode.LeftChildNode;
                    if (leftChildNode == null)
                    {
                        break;
                    }
                    splayTreeNode = leftChildNode;
                }
            }
            else
            {
                SplayTreeNodeRole role = this.Role;
                splayTreeNode = this.ParentNode;
                while (role != SplayTreeNodeRole.LocalRoot)
                {
                    if (role == SplayTreeNodeRole.LeftChild)
                    {
                        goto IL_41;
                    }
                    role          = splayTreeNode.Role;
                    splayTreeNode = splayTreeNode.ParentNode;
                }
                splayTreeNode = null;
            }
IL_41:
            if (splayTreeNode != null)
            {
                splayTreeNode.Splay();
            }
            return(splayTreeNode);
        }
Beispiel #8
0
        // Combines two trees.  Every node in leftSubTree will precede every node
        // in rightSubTree.
        // leftSubTree and/or rightSubTree may be null, returns null if both
        // trees are null.
        internal static SplayTreeNode Join(SplayTreeNode leftSubTree, SplayTreeNode rightSubTree)
        {
            SplayTreeNode maxNode;

            Invariant.Assert(leftSubTree == null || leftSubTree.ParentNode == null);
            Invariant.Assert(rightSubTree == null || rightSubTree.ParentNode == null);

            if (leftSubTree != null)
            {
                // Get max of leftSubTree, and splay it.
                maxNode = leftSubTree.GetMaxSibling();

                maxNode.Splay();
                Invariant.Assert(maxNode.Role == SplayTreeNodeRole.LocalRoot);
                Invariant.Assert(maxNode.RightChildNode == null);

                // Then merge the two trees.
                // No change to any LeftSymbolCounts.
                maxNode.RightChildNode = rightSubTree;
                if (rightSubTree != null)
                {
                    rightSubTree.ParentNode = maxNode;
                }
            }
            else if (rightSubTree != null)
            {
                maxNode = rightSubTree;
                Invariant.Assert(maxNode.Role == SplayTreeNodeRole.LocalRoot);
            }
            else
            {
                maxNode = null;
            }

            return(maxNode);
        }
Beispiel #9
0
 // Returns true if this node is the left/right/contained node of parentNode. 
 internal bool IsChildOfNode(SplayTreeNode parentNode)
 { 
     return (parentNode.LeftChildNode == this ||
             parentNode.RightChildNode == this ||
             parentNode.ContainedNode == this);
 } 
Beispiel #10
0
        // Combines two trees.  Every node in leftSubTree will precede every node
        // in rightSubTree. 
        // leftSubTree and/or rightSubTree may be null, returns null if both 
        // trees are null.
        internal static SplayTreeNode Join(SplayTreeNode leftSubTree, SplayTreeNode rightSubTree) 
        {
            SplayTreeNode maxNode;

            Invariant.Assert(leftSubTree == null || leftSubTree.ParentNode == null); 
            Invariant.Assert(rightSubTree == null || rightSubTree.ParentNode == null);
 
            if (leftSubTree != null) 
            {
                // Get max of leftSubTree, and splay it. 
                maxNode = leftSubTree.GetMaxSibling();

                maxNode.Splay();
                Invariant.Assert(maxNode.Role == SplayTreeNodeRole.LocalRoot); 
                Invariant.Assert(maxNode.RightChildNode == null);
 
                // Then merge the two trees. 
                // No change to any LeftSymbolCounts.
                maxNode.RightChildNode = rightSubTree; 
                if (rightSubTree != null)
                {
                    rightSubTree.ParentNode = maxNode;
                } 
            }
            else if (rightSubTree != null) 
            { 
                maxNode = rightSubTree;
                Invariant.Assert(maxNode.Role == SplayTreeNodeRole.LocalRoot); 
            }
            else
            {
                maxNode = null; 
            }
 
            return maxNode; 
        }
Beispiel #11
0
        // Parents leftSubTree and rightSubTree to root.  Either leftSubTree and/or
        // rightSubTree may be null. 
        internal static void Join(SplayTreeNode root, SplayTreeNode leftSubTree, SplayTreeNode rightSubTree) 
        {
            root.LeftChildNode = leftSubTree; 
            root.RightChildNode = rightSubTree;

            Invariant.Assert(root.Role == SplayTreeNodeRole.LocalRoot);
 
            if (leftSubTree != null)
            { 
                leftSubTree.ParentNode = root; 
                root.LeftSymbolCount = leftSubTree.LeftSymbolCount + leftSubTree.SymbolCount;
                root.LeftCharCount = leftSubTree.LeftCharCount + leftSubTree.IMECharCount; 
            }
            else
            {
                root.LeftSymbolCount = 0; 
                root.LeftCharCount = 0;
            } 
 
            if (rightSubTree != null)
            { 
                rightSubTree.ParentNode = root;
            }
        }
Beispiel #12
0
        // Inserts a node before or after an existing node. 
        // The new node becomes the local root.
        internal void InsertAtNode(SplayTreeNode location, bool insertBefore)
        {
            SplayTreeNode leftSubTree; 
            SplayTreeNode rightSubTree;
            SplayTreeNode containingNode; 
 
            Invariant.Assert(this.ParentNode == null, "Can't insert child node!");
            Invariant.Assert(this.LeftChildNode == null, "Can't insert node with left children!"); 
            Invariant.Assert(this.RightChildNode == null, "Can't insert node with right children!");

            leftSubTree = insertBefore ? location.GetPreviousNode() : location;
            if (leftSubTree != null) 
            {
                rightSubTree = leftSubTree.Split(); 
                containingNode = leftSubTree.ParentNode; 
            }
            else 
            {
                rightSubTree = location;

                location.Splay(); 
                Invariant.Assert(location.Role == SplayTreeNodeRole.LocalRoot, "location should be local root!");
                containingNode = location.ParentNode; 
            } 

            // Merge everything into a new tree. 
            Join(this, leftSubTree, rightSubTree);

            // Hook up the new tree to the containing node.
            this.ParentNode = containingNode; 
            if (containingNode != null)
            { 
                containingNode.ContainedNode = this; 
            }
        } 
Beispiel #13
0
        // Inserts a node at a specified position.
        internal void InsertAtNode(SplayTreeNode positionNode, ElementEdge edge) 
        {
            SplayTreeNode locationNode; 
            bool insertBefore; 

            if (edge == ElementEdge.BeforeStart || edge == ElementEdge.AfterEnd) 
            {
                // Insert to this node's tree.
                InsertAtNode(positionNode, edge == ElementEdge.BeforeStart /* insertBefore */);
            } 
            else
            { 
                // Insert to this node's contained tree. 

                if (edge == ElementEdge.AfterStart) 
                {
                    locationNode = positionNode.GetFirstContainedNode();
                    insertBefore = true;
                } 
                else // ElementEdge == BeforeEnd
                { 
                    locationNode = positionNode.GetLastContainedNode(); 
                    insertBefore = false;
                } 

                if (locationNode == null)
                {
                    // Inserting the first contained node. 
                    positionNode.ContainedNode = this;
                    this.ParentNode = positionNode; 
                    Invariant.Assert(this.LeftChildNode == null); 
                    Invariant.Assert(this.RightChildNode == null);
                    Invariant.Assert(this.LeftSymbolCount == 0); 
                }
                else
                {
                    InsertAtNode(locationNode, insertBefore); 
                }
            } 
        } 
Beispiel #14
0
        // Removes nodes from a sibling tree.  containingNode must scope start/end.
        // Returns the combined symbol count of all the removed nodes. 
        private int DeleteContentFromSiblingTree(SplayTreeNode containingNode, TextPointer startPosition, TextPointer endPosition, bool newFirstIMEVisibleNode, out int charCount) 
        {
            SplayTreeNode leftSubTree; 
            SplayTreeNode middleSubTree;
            SplayTreeNode rightSubTree;
            SplayTreeNode rootNode;
            TextTreeNode previousNode; 
            ElementEdge previousEdge;
            TextTreeNode nextNode; 
            ElementEdge nextEdge; 
            int symbolCount;
            int symbolOffset; 

            // Early out in the no-op case. CutContent can't handle an empty content span.
            if (startPosition.CompareTo(endPosition) == 0)
            { 
                if (newFirstIMEVisibleNode)
                { 
                    UpdateContainerSymbolCount(containingNode, /* symbolCount */ 0, /* charCount */ -1); 
                }
                charCount = 0; 
                return 0;
            }

            // Get the symbol offset now before the CutContent call invalidates startPosition. 
            symbolOffset = startPosition.GetSymbolOffset();
 
            // Do the cut.  middleSubTree is what we want to remove. 
            symbolCount = CutContent(startPosition, endPosition, out charCount, out leftSubTree, out middleSubTree, out rightSubTree);
 
            // We need to remember the original previous/next node for the span
            // we're about to drop, so any orphaned positions can find their way
            // back.
            if (middleSubTree != null) 
            {
                if (leftSubTree != null) 
                { 
                    previousNode = (TextTreeNode)leftSubTree.GetMaxSibling();
                    previousEdge = ElementEdge.AfterEnd; 
                }
                else
                {
                    previousNode = (TextTreeNode)containingNode; 
                    previousEdge = ElementEdge.AfterStart;
                } 
                if (rightSubTree != null) 
                {
                    nextNode = (TextTreeNode)rightSubTree.GetMinSibling(); 
                    nextEdge = ElementEdge.BeforeStart;
                }
                else
                { 
                    nextNode = (TextTreeNode)containingNode;
                    nextEdge = ElementEdge.BeforeEnd; 
                } 

                // Increment previous/nextNode reference counts. This may involve 
                // splitting a text node, so we use refs.
                AdjustRefCountsForContentDelete(ref previousNode, previousEdge, ref nextNode, nextEdge, (TextTreeNode)middleSubTree);

                // Make sure left/rightSubTree stay local roots, we might 
                // have inserted new elements in the AdjustRefCountsForContentDelete call.
                if (leftSubTree != null) 
                { 
                    leftSubTree.Splay();
                } 
                if (rightSubTree != null)
                {
                    rightSubTree.Splay();
                } 
                // Similarly, middleSubtree might not be a local root any more,
                // so splay it too. 
                middleSubTree.Splay(); 

                // Note TextContainer now has no references to middleSubTree, if there are 
                // no orphaned positions this allocation won't be kept around.
                Invariant.Assert(middleSubTree.ParentNode == null, "Assigning fixup node to parented child!");
                middleSubTree.ParentNode = new TextTreeFixupNode(previousNode, previousEdge, nextNode, nextEdge);
            } 

            // Put left/right sub trees back into the TextContainer. 
            rootNode = TextTreeNode.Join(leftSubTree, rightSubTree); 
            containingNode.ContainedNode = rootNode;
            if (rootNode != null) 
            {
                rootNode.ParentNode = containingNode;
            }
 
            if (symbolCount > 0)
            { 
                int nextNodeCharDelta = 0; 
                if (newFirstIMEVisibleNode)
                { 
                    // The following node is the new first ime visible sibling.
                    // It just moved, and loses an edge character.
                    nextNodeCharDelta = -1;
                } 

                UpdateContainerSymbolCount(containingNode, -symbolCount, -charCount + nextNodeCharDelta); 
                TextTreeText.RemoveText(_rootNode.RootTextBlock, symbolOffset, symbolCount); 
                NextGeneration(true /* deletedContent */);
 
                // Notify the TextElement of a content change. Note that any full TextElements
                // between startPosition and endPosition will be handled by CutTopLevelLogicalNodes,
                // which will move them from this tree to their own private trees without changing
                // their contents. 
                Invariant.Assert(startPosition.Parent == endPosition.Parent);
                TextElement textElement = startPosition.Parent as TextElement; 
                if (textElement != null) 
                {
                    textElement.OnTextUpdated(); 
                }
            }

            return symbolCount; 
        }
Beispiel #15
0
        // Debug only.  Walks a node and all its children to get a brute force
        // symbol count.
        private static int GetNodeSymbolCountSlow(SplayTreeNode node)
        {
            SplayTreeNode child;
            int count;

            if (node is TextTreeRootNode || node is TextTreeTextElementNode)
            {
                count = 2;
                for (child = node.GetFirstContainedNode(); child != null; child = child.GetNextNode())
                {
                    count += GetNodeSymbolCountSlow(child);
                }
            }
            else
            {
                Invariant.Assert(node.ContainedNode == null, "Expected leaf node!");
                count = node.SymbolCount;
            }

            return count;
        }
Beispiel #16
0
        // Finds a node/edge pair matching a given symbol offset in the tree.
        // If the pair matches a character within a text node, the text node is split. 
        internal void GetNodeAndEdgeAtOffset(int offset, bool splitNode, out SplayTreeNode node, out ElementEdge edge)
        { 
            int nodeOffset; 
            int siblingTreeOffset;
            bool checkZeroWidthNode; 

            // Offset zero/SymbolCount-1 are before/after the root node, which
            // is an illegal position -- you can't add or remove content there
            // and it's never exposed publicly. 
            Invariant.Assert(offset >= 1 && offset <= this.InternalSymbolCount - 1, "Bogus symbol offset!");
 
            // If this flag is set true on exit, we need to consider the case 
            // where we've found a "zero-width" (SymbolCount == 0) text node.
            // Zero width nodes needs special handling, since they are logically 
            // part of a following or preceding node.
            checkZeroWidthNode = false;

            // Find the node. 
            node = _rootNode;
            nodeOffset = 0; 
 
            // Each iteration walks through one tree.
            while (true) 
            {
                // While we're at it, fix up the node's SymbolOffsetCache,
                // since we're doing the work already.
                Invariant.Assert(node.Generation != _rootNode.Generation || 
                             node.SymbolOffsetCache == -1 ||
                             node.SymbolOffsetCache == nodeOffset, "Bad node offset cache!"); 
 
                node.Generation = _rootNode.Generation;
                node.SymbolOffsetCache = nodeOffset; 

                if (offset == nodeOffset)
                {
                    edge = ElementEdge.BeforeStart; 
                    checkZeroWidthNode = true;
                    break; 
                } 
                if (node is TextTreeRootNode || node is TextTreeTextElementNode)
                { 
                    if (offset == nodeOffset + 1)
                    {
                        edge = ElementEdge.AfterStart;
                        break; 
                    }
                    if (offset == nodeOffset + node.SymbolCount - 1) 
                    { 
                        edge = ElementEdge.BeforeEnd;
                        break; 
                    }
                }
                if (offset == nodeOffset + node.SymbolCount)
                { 
                    edge = ElementEdge.AfterEnd;
                    checkZeroWidthNode = true; 
                    break; 
                }
 
                // No child node?  That means we're inside a TextTreeTextNode.
                if (node.ContainedNode == null)
                {
                    Invariant.Assert(node is TextTreeTextNode); 
                    // Need to split the TextTreeTextNode.
                    // Here we want a character buried inside a single node, split 
                    // the node open.... 
                    if (splitNode)
                    { 
                        node = ((TextTreeTextNode)node).Split(offset - nodeOffset, ElementEdge.AfterEnd);
                    }
                    edge = ElementEdge.BeforeStart;
                    break; 
                }
 
                // Need to look into one of the child nodes. 
                node = node.ContainedNode;
                nodeOffset += 1; // Skip over the parent element start edge. 

                // Walk down the sibling tree.
                node = node.GetSiblingAtOffset(offset - nodeOffset, out siblingTreeOffset);
                nodeOffset += siblingTreeOffset; 
            }
 
            // If we're on a zero-width TextTreeTextNode we need some special handling. 
            if (checkZeroWidthNode)
            { 
                node = AdjustForZeroWidthNode(node, edge);
            }
        }
Beispiel #17
0
        //----------------------------------------------------- 
        //
        //  Private Methods 
        //
        //------------------------------------------------------

        #region Private Methods 

        // Scans all the immediate contained nodes of a TextElementNode, and 
        // calls AddLogicalChild methods if supported to alert the children 
        // about a new parent.
        private void ReparentLogicalChildren(SplayTreeNode containerNode, DependencyObject newParentLogicalNode, DependencyObject oldParentLogicalNode) 
        {
            ReparentLogicalChildren(containerNode.GetFirstContainedNode(), null, newParentLogicalNode, oldParentLogicalNode);
        }
Beispiel #18
0
        // Scans all the immediate contained nodes of a TextElementNode, and
        // calls AddLogicalChild methods if supported to alert the children 
        // about a new parent. 
        private void ReparentLogicalChildren(SplayTreeNode firstChildNode, SplayTreeNode lastChildNode, DependencyObject newParentLogicalNode, DependencyObject oldParentLogicalNode)
        { 
            SplayTreeNode node;
            DependencyObject logicalTreeNode;
            TextTreeTextElementNode elementNode;
            TextTreeObjectNode uiElementNode; 

            Invariant.Assert(!(newParentLogicalNode == null && oldParentLogicalNode == null), "Both new and old parents should not be null"); 
 
            for (node = firstChildNode; node != null; node = node.GetNextNode())
            { 
                logicalTreeNode = null;

                elementNode = node as TextTreeTextElementNode;
                if (elementNode != null) 
                {
                    logicalTreeNode = elementNode.TextElement; 
                } 
                else
                { 
                    uiElementNode = node as TextTreeObjectNode;
                    if (uiElementNode != null)
                    {
                        logicalTreeNode = uiElementNode.EmbeddedElement; 
                    }
                } 
 
                TextElement textElement = logicalTreeNode as TextElement;
                if (textElement != null) 
                {
                    textElement.BeforeLogicalTreeChange();
                }
 
                try
                { 
                    if (oldParentLogicalNode != null) 
                    {
                        LogicalTreeHelper.RemoveLogicalChild(oldParentLogicalNode, logicalTreeNode); 
                    }

                    if (newParentLogicalNode != null)
                    { 
                        LogicalTreeHelper.AddLogicalChild(newParentLogicalNode, logicalTreeNode);
                    } 
                } 
                finally
                { 
                    if (textElement != null)
                    {
                        textElement.AfterLogicalTreeChange();
                    } 
                }
 
                if (node == lastChildNode) 
                    break;
            } 
        }
Beispiel #19
0
 // Updates the SymbolCount for node's container nodes -- all the way to the TextTree root.
 private void UpdateContainerSymbolCount(SplayTreeNode containingNode, int symbolCount, int charCount) 
 { 
     do
     { 
         containingNode.Splay();
         containingNode.SymbolCount += symbolCount;
         containingNode.IMECharCount += charCount;
         containingNode = containingNode.ParentNode; 
     }
     while (containingNode != null); 
 } 
Beispiel #20
0
        // Removes an element node from its sibling tree.
        //
        // If deep == true, then this method also removes any contained nodes
        // and returns a deep copy of them. 
        //
        // If deep == false, any contained nodes are inserted into the original 
        // node's sibling tree. 
        private void ExtractElementFromSiblingTree(SplayTreeNode containingNode, TextTreeTextElementNode elementNode, bool deep)
        { 
            TextTreeNode previousNode;
            ElementEdge previousEdge;
            TextTreeNode nextNode;
            ElementEdge nextEdge; 
            SplayTreeNode childNode;
            SplayTreeNode minChildNode; 
            SplayTreeNode maxChildNode; 
            SplayTreeNode localRootNode;
            TextTreeNode firstContainedNode; 
            TextTreeNode lastContainedNode;

            // Remember the nodes surrounding the one we're going to remove.
            previousNode = (TextTreeNode)elementNode.GetPreviousNode(); 
            previousEdge = ElementEdge.AfterEnd;
            if (previousNode == null) 
            { 
                previousNode = (TextTreeNode)containingNode;
                previousEdge = ElementEdge.AfterStart; 
            }
            nextNode = (TextTreeNode)elementNode.GetNextNode();
            nextEdge = ElementEdge.BeforeStart;
            if (nextNode == null) 
            {
                nextNode = (TextTreeNode)containingNode; 
                nextEdge = ElementEdge.BeforeEnd; 
            }
 
            // Remove the element node.
            elementNode.Remove();
            Invariant.Assert(elementNode.Role == SplayTreeNodeRole.LocalRoot);
 
            if (deep)
            { 
                // Increment previous/nextNode reference counts. This may involve 
                // splitting a text node, so we use refs.
                AdjustRefCountsForContentDelete(ref previousNode, previousEdge, ref nextNode, nextEdge, elementNode); 

                // Reparent the removed node with a FixupNode, so that any orphaned
                // positions can find their way back to the tree.
                // We have to do this after the AdjustRefCountsForContentDelete call, because the fixup 
                // node doesn't act like a regular node.
                elementNode.ParentNode = new TextTreeFixupNode(previousNode, previousEdge, nextNode, nextEdge); 
 
                DeepCopy(elementNode);
            } 
            else
            {
                // Reparent contained nodes to elementNode's parent.
                childNode = elementNode.ContainedNode; 
                elementNode.ContainedNode = null;
                if (childNode != null) 
                { 
                    childNode.ParentNode = null;
                    firstContainedNode = (TextTreeNode)childNode.GetMinSibling(); 
                    lastContainedNode = (TextTreeNode)childNode.GetMaxSibling();
                }
                else
                { 
                    firstContainedNode = null;
                    lastContainedNode = null; 
                } 

                // Increment previous/nextNode reference counts. This may involve 
                // splitting a text node, so we use refs.
                AdjustRefCountsForShallowDelete(ref previousNode, previousEdge, ref nextNode, nextEdge, ref firstContainedNode, ref lastContainedNode, elementNode);

                // Reparent the removed node with a FixupNode, so that any orphaned 
                // positions can find their way back to the tree.
                // We have to do this after the AdjustRefCountsForContentDelete call, because the fixup 
                // node doesn't act like a regular node. 
                elementNode.ParentNode = new TextTreeFixupNode(previousNode, previousEdge, nextNode, nextEdge, firstContainedNode, lastContainedNode);
 
                if (childNode != null)
                {
                    // Get previous/next nodes into roots of individual trees.
                    // Then merge them with the element's children. 

                    // We need to splay childNode because it may no longer be a local root. 
                    // The addrefs in AdjustRefCountsForShallowDelete may have created new nodes 
                    // and shuffled the tree.
                    childNode.Splay(); 
                    localRootNode = childNode;

                    if (previousNode != containingNode)
                    { 
                        previousNode.Split();
                        Invariant.Assert(previousNode.Role == SplayTreeNodeRole.LocalRoot); 
                        Invariant.Assert(previousNode.RightChildNode == null); 

                        minChildNode = childNode.GetMinSibling(); 
                        minChildNode.Splay();

                        previousNode.RightChildNode = minChildNode;
                        minChildNode.ParentNode = previousNode; 

                        localRootNode = previousNode; 
                    } 

                    if (nextNode != containingNode) 
                    {
                        nextNode.Splay();
                        Invariant.Assert(nextNode.Role == SplayTreeNodeRole.LocalRoot);
                        Invariant.Assert(nextNode.LeftChildNode == null); 

                        maxChildNode = childNode.GetMaxSibling(); 
                        maxChildNode.Splay(); 

                        nextNode.LeftChildNode = maxChildNode; 
                        nextNode.LeftSymbolCount += maxChildNode.LeftSymbolCount + maxChildNode.SymbolCount;
                        nextNode.LeftCharCount += maxChildNode.LeftCharCount + maxChildNode.IMECharCount;
                        maxChildNode.ParentNode = nextNode;
 
                        localRootNode = nextNode;
                    } 
 
                    containingNode.ContainedNode = localRootNode;
                    if (localRootNode != null) 
                    {
                        localRootNode.ParentNode = containingNode;
                    }
                } 
            }
        } 
Beispiel #21
0
        // Splits a sibling tree into three sub trees -- a tree with content before startPosition,
        // a tree with content between startPosition/endPosition, and a tree with content following endPosition. 
        // Any of the subtrees may be null on exit, if they contain no content (eg, if
        // startPosition == endPosition, middleSubTree will be null on exit, and so forth).
        //
        // All returned roots have null ParentNode pointers -- the caller MUST 
        // reparent all of them, even if deleting content, to ensure orphaned
        // TextPositions can find their way back to the original tree. 
        // 
        // Returns the symbol count of middleSubTree -- all the content between startPosition and endPosition.
        private int CutContent(TextPointer startPosition, TextPointer endPosition, out int charCount, out SplayTreeNode leftSubTree, out SplayTreeNode middleSubTree, out SplayTreeNode rightSubTree) 
        {
            SplayTreeNode childNode;
            int symbolCount;
 
            Invariant.Assert(startPosition.GetScopingNode() == endPosition.GetScopingNode(), "startPosition/endPosition not in same sibling tree!");
            Invariant.Assert(startPosition.CompareTo(endPosition) != 0, "CutContent doesn't expect empty span!"); 
 
            // Get the root of all nodes to the left of the split.
            switch (startPosition.Edge) 
            {
                case ElementEdge.BeforeStart:
                    leftSubTree = startPosition.Node.GetPreviousNode();
                    break; 

                case ElementEdge.AfterStart: 
                    leftSubTree = null; 
                    break;
 
                case ElementEdge.BeforeEnd:
                default:
                    Invariant.Assert(false, "Unexpected edge!"); // Should have gone to simple insert case.
                    leftSubTree = null; 
                    break;
 
                case ElementEdge.AfterEnd: 
                    leftSubTree = startPosition.Node;
                    break; 
            }

            // Get the root of all nodes to the right of the split.
            switch (endPosition.Edge) 
            {
                case ElementEdge.BeforeStart: 
                    rightSubTree = endPosition.Node; 
                    break;
 
                case ElementEdge.AfterStart:
                default:
                    Invariant.Assert(false, "Unexpected edge! (2)"); // Should have gone to simple insert case.
                    rightSubTree = null; 
                    break;
 
                case ElementEdge.BeforeEnd: 
                    rightSubTree = null;
                    break; 

                case ElementEdge.AfterEnd:
                    rightSubTree = endPosition.Node.GetNextNode();
                    break; 
            }
 
            // Get the root of all nodes covered by startPosition/endPosition. 
            if (rightSubTree == null)
            { 
                if (leftSubTree == null)
                {
                    middleSubTree = startPosition.GetScopingNode().ContainedNode;
                } 
                else
                { 
                    middleSubTree = leftSubTree.GetNextNode(); 
                }
            } 
            else
            {
                middleSubTree = rightSubTree.GetPreviousNode();
                if (middleSubTree == leftSubTree) 
                {
                    middleSubTree = null; 
                } 
            }
 
            // Split the tree into three sub trees matching the roots we've found.

            if (leftSubTree != null)
            { 
                leftSubTree.Split();
                Invariant.Assert(leftSubTree.Role == SplayTreeNodeRole.LocalRoot); 
                leftSubTree.ParentNode.ContainedNode = null; 
                leftSubTree.ParentNode = null;
            } 

            symbolCount = 0;
            charCount = 0;
 
            if (middleSubTree != null)
            { 
                if (rightSubTree != null) 
                {
                    // Split will move middleSubTree up to the root. 
                    middleSubTree.Split();
                }
                else
                { 
                    // Make sure middleSubTree is a root.
                    middleSubTree.Splay(); 
                } 
                Invariant.Assert(middleSubTree.Role == SplayTreeNodeRole.LocalRoot, "middleSubTree is not a local root!");
 
                if (middleSubTree.ParentNode != null)
                {
                    middleSubTree.ParentNode.ContainedNode = null;
                    middleSubTree.ParentNode = null; 
                }
 
                // Calc the symbol count of the middle tree. 
                for (childNode = middleSubTree; childNode != null; childNode = childNode.RightChildNode)
                { 
                    symbolCount += childNode.LeftSymbolCount + childNode.SymbolCount;
                    charCount += childNode.LeftCharCount + childNode.IMECharCount;
                }
            } 

            if (rightSubTree != null) 
            { 
                // Make sure rightSubTree is a root before returning.
                // We haven't done anything yet to ensure this. 
                rightSubTree.Splay();
            }

            Invariant.Assert(leftSubTree == null || leftSubTree.Role == SplayTreeNodeRole.LocalRoot); 
            Invariant.Assert(middleSubTree == null || middleSubTree.Role == SplayTreeNodeRole.LocalRoot);
            Invariant.Assert(rightSubTree == null || rightSubTree.Role == SplayTreeNodeRole.LocalRoot); 
 
            return symbolCount;
        } 
Beispiel #22
0
 internal void GetNodeAndEdgeAtOffset(int offset, out SplayTreeNode node, out ElementEdge edge) 
 {
     GetNodeAndEdgeAtOffset(offset, true /* splitNode */, out node, out edge); 
 }
Beispiel #23
0
        // Returns a string identifying the type of a given node.
        private static string GetFlatPrefix(SplayTreeNode node)
        {
            string prefix;

            if (node is TextTreeTextNode)
            {
                prefix = "t";
            }
            else if (node is TextTreeObjectNode)
            {
                prefix = "o";
            }
            else if (node is TextTreeTextElementNode)
            {
                prefix = "e";
            }
            else if (node is TextTreeRootNode)
            {
                prefix = "r";
            }
            else
            {
                prefix = "?";
            }

            return prefix;
        }
Beispiel #24
0
        // This method is called by GetNodeAndEdgeAtOffset to adjust a node
        // matching a symbol offset. 
        //
        // When text positions reference both sides of a text run 
        // we always split the run into a zero-width TextTreeTextNode 
        // followed by a non-zero-width node.  We do this so that
        // later we can safely split the non-zero node without disturbing 
        // existing text positions.
        //
        // Here, we have to be very careful never to reference a node
        // edge between the zero-width node and the non-zero width node. 
        //
        // A: <TextTreeTextNode SymbolCount=0/><TextTreeTextNode SymbolCount=1+/> 
        // B: <TextTreeTextNode SymbolCount=1+/><TextTreeTextNode SymbolCount=0/> 
        //
        // In case A, if we're searching for the first character in the second 
        // node, we want to return the first (zero-width) node.  A TextPointer
        // could be at node1/BeforeBegin but node2/BeforeBegin is invalid.
        //
        // In case B, if we're searching for the last character in the first 
        // node, we want to return the second (zero-width) node. A TextPointer
        // could be at node2/AfterEnd but not node1/AfterEnd is invalid. 
        private SplayTreeNode AdjustForZeroWidthNode(SplayTreeNode node, ElementEdge edge) 
        {
            TextTreeTextNode textNode; 
            SplayTreeNode nextNode;
            SplayTreeNode previousNode;

            textNode = node as TextTreeTextNode; 

            if (textNode == null) 
            { 
                Invariant.Assert(node.SymbolCount > 0, "Only TextTreeTextNodes may have zero symbol counts!");
                return node; 
            }

            if (textNode.SymbolCount == 0)
            { 
                // There are only ever at most two consectuative zero-width
                // text nodes (one for each possible position gravity).  Make sure 
                // we chose the following one.  This ensures consistency with 
                // the typical non-zero width case -- we return the node whose
                // start edge is closest to a character offset. 
                nextNode = textNode.GetNextNode();
                if (nextNode != null)
                {
                    if (Invariant.Strict) 
                    {
                        if (nextNode.SymbolCount == 0) 
                        { 
                            // Node and previousNode are logically one text run.
                            // <TextTreeTextNode SymbolCount=1+/><node SymbolCount=0/><TextTreeTextNode SymbolCount=0/><TextTreeTextNode SymbolCount=1+/> 
                            Invariant.Assert(nextNode is TextTreeTextNode);
                            Invariant.Assert(!textNode.BeforeStartReferenceCount);
                            Invariant.Assert(!((TextTreeTextNode)nextNode).AfterEndReferenceCount);
                            Invariant.Assert(textNode.GetPreviousNode() == null || textNode.GetPreviousNode().SymbolCount > 0, "Found three consecutive zero-width text nodes! (1)"); 
                            Invariant.Assert(nextNode.GetNextNode() == null || nextNode.GetNextNode().SymbolCount > 0, "Found three consecutive zero-width text nodes! (2)");
                        } 
                    } 

                    if (!textNode.BeforeStartReferenceCount) 
                    {
                        // Node and previousNode are logically one text run.
                        // <TextTreeTextNode SymbolCount=1+/><node SymbolCount=0/><AnyNode/>
                        node = nextNode; 
                    }
                } 
            } 
            else if (edge == ElementEdge.BeforeStart)
            { 
                if (textNode.AfterEndReferenceCount)
                {
                    // <TextTreeTextNode SymbolCount=0/><node SymbolCount=1+/>
                    // Case A.  Check for previous zero-width node. 
                    previousNode = textNode.GetPreviousNode();
                    if (previousNode != null && previousNode.SymbolCount == 0 && !((TextTreeNode)previousNode).AfterEndReferenceCount) 
                    { 
                        Invariant.Assert(previousNode is TextTreeTextNode);
                        node = previousNode; 
                    }
                }
            }
            else // edge == ElementEdge.AfterEnd 
            {
                if (textNode.BeforeStartReferenceCount) 
                { 
                    // B: <node SymbolCount=1+/><TextTreeTextNode SymbolCount=0/>
                    // Case B.  Check for following zero-width node. 
                    nextNode = textNode.GetNextNode();
                    if (nextNode != null && nextNode.SymbolCount == 0 && !((TextTreeNode)nextNode).BeforeStartReferenceCount)
                    {
                        Invariant.Assert(nextNode is TextTreeTextNode); 
                        node = nextNode;
                    } 
                } 
            }
 
            return node;
        }
 // Token: 0x060035CC RID: 13772 RVA: 0x000F4833 File Offset: 0x000F2A33
 internal bool IsChildOfNode(SplayTreeNode parentNode)
 {
     return(parentNode.LeftChildNode == this || parentNode.RightChildNode == this || parentNode.ContainedNode == this);
 }
Beispiel #26
0
        //------------------------------------------------------
        //
        //  Private Methods
        //
        //------------------------------------------------------

        #region Private Methods

        // Recursive worker to DumpNode.
        internal static void DumpNodeRecursive(SplayTreeNode node, int depth)
        {
            SplayTreeNode containedNode;
            string indent;

            indent = new string(' ', depth*2);

            Debug.Write("<");
            Debug.Write(node);

            if (node.ContainedNode == null)
            {
                Debug.WriteLine("/>");
            }
            else
            {
                Debug.WriteLine(">");
            }

            containedNode = node.ContainedNode;
            if (containedNode != null)
            {
                Debug.Write(indent + "C ");
                DumpNodeRecursive(containedNode, depth + 1);
            }

            if (node.LeftChildNode != null)
            {
                Debug.Write(indent + "L ");
                DumpNodeRecursive(node.LeftChildNode, depth + 1);
            }

            if (node.RightChildNode != null)
            {
                Debug.Write(indent + "R ");
                DumpNodeRecursive(node.RightChildNode, depth + 1);
            }

            if (containedNode != null)
            {
                if (node is TextTreeRootNode)
                {
                    Debug.WriteLine(indent + "</RootNode>");
                }
                else if (node is TextTreeTextElementNode)
                {
                    Debug.WriteLine(indent + "</TextElementNode>");
                }
                else
                {
                    Debug.WriteLine(indent + "</UnknownNode>");
                }
            }
        }
Beispiel #27
0
        // Dumps a node and all following nodes "flat" -- in notation similar to xaml.
        internal static void DumpNodeFlatRecursive(SplayTreeNode node)
        {
            for (; node != null; node = node.GetNextNode())
            {
                Debug.Write("<" + GetFlatPrefix(node) + node.DebugId);

                if (node.ContainedNode != null)
                {
                    Debug.Write(">");
                    DumpNodeFlatRecursive(node.GetFirstContainedNode());
                    Debug.Write("</" + GetFlatPrefix(node) + node.DebugId + ">");
                }
                else
                {
                    Debug.Write("/>");
                }
            }

        }
Beispiel #28
0
        // This test is so slow we can't afford to run it even with Invariant.Strict.
        // It grinds execution to a halt.
        private static void DebugWalkTree(SplayTreeNode node)
        {
            SplayTreeNode previousNode;
            SplayTreeNode previousPreviousNode;

            previousNode = null;
            previousPreviousNode = null;

            for (; node != null; node = node.GetNextNode())
            {
                if (node.SymbolCount == 0 &&
                    previousNode != null && previousNode.SymbolCount == 0 &&
                    previousPreviousNode != null && previousPreviousNode.SymbolCount == 0)
                {
                    Invariant.Assert(false, "Found three consecuative zero length nodes!");
                }

                previousPreviousNode = previousNode;
                previousNode = node;

                if (node.ContainedNode != null)
                {
                    DebugWalkTree(node.ContainedNode.GetMinSibling());
                }
            }
        }