// Increments the position reference counts on nodes immediately // preceding and following a delete operation on a single TextElementNode. // This is similar to AdjustRefCountsForContentDelete, except that // in this case we deleting a single node, and positions at the // BeforeStart/AfterEnd edges may move into contained content, which // is still live in the tree. // // Whenever we delete a span of content, we have to worry about any // positions still referencing the deleted content. They have enough // information to find their way back to the surrounding nodes, but // we need to increment the ref count on those nodes now so that they'll // still be around when the positions need them. // // Because incrementing a ref count on a text node edge may involve // splitting the text node, this method takes refs to nodes and will // update the refs if a node is split. // // Called by ExtractElementFromSiblingTree. private void AdjustRefCountsForShallowDelete(ref TextTreeNode previousNode, ElementEdge previousEdge, ref TextTreeNode nextNode,ElementEdge nextEdge, ref TextTreeNode firstContainedNode, ref TextTreeNode lastContainedNode, TextTreeTextElementNode extractedElementNode) { previousNode = previousNode.IncrementReferenceCount(previousEdge, extractedElementNode.AfterStartReferenceCount); nextNode = nextNode.IncrementReferenceCount(nextEdge, extractedElementNode.BeforeEndReferenceCount); if (firstContainedNode != null) { firstContainedNode = firstContainedNode.IncrementReferenceCount(ElementEdge.BeforeStart, extractedElementNode.BeforeStartReferenceCount); } else { nextNode = nextNode.IncrementReferenceCount(nextEdge, extractedElementNode.BeforeStartReferenceCount); } if (lastContainedNode != null) { lastContainedNode = lastContainedNode.IncrementReferenceCount(ElementEdge.AfterEnd, extractedElementNode.AfterEndReferenceCount); } else { previousNode = previousNode.IncrementReferenceCount(previousEdge, extractedElementNode.AfterEndReferenceCount); } }
// Inc/decs the position ref counts on TextTreeTextNodes as the navigator // is repositioned. // If the new ref is to a TextTreeTextNode, the node may be split. // Returns the actual node referenced, which will always be newNode, // unless newNode is a TextTreeTextNode that gets split. The caller // should use the returned node to position navigators. private TextTreeNode AdjustRefCounts(TextTreeNode newNode, ElementEdge newNodeEdge, TextTreeNode oldNode, ElementEdge oldNodeEdge) { TextTreeNode node; // This test should walk the tree upwards to catch all errors...probably not worth the slowdown though. Invariant.Assert(oldNode.ParentNode == null || oldNode.IsChildOfNode(oldNode.ParentNode), "Trying to add ref a dead node!"); Invariant.Assert(newNode.ParentNode == null || newNode.IsChildOfNode(newNode.ParentNode), "Trying to add ref a dead node!"); node = newNode; if (newNode != oldNode || newNodeEdge != oldNodeEdge) { node = newNode.IncrementReferenceCount(newNodeEdge); oldNode.DecrementReferenceCount(oldNodeEdge); } return node; }
// Increments the position reference counts on nodes immediately // preceding and following a delete operation. // // Whenever we delete a span of content, we have to worry about any // positions still referencing the deleted content. They have enough // information to find their way back to the surrounding nodes, but // we need to increment the ref count on those nodes now so that they'll // still be around when the positions need them. // // Because incrementing a ref count on a text node edge may involve // splitting the text node, this method takes refs to nodes and will // update the refs if a node is split. // // Called by DeleteContentFromSiblingTree and ExtractElementInternal. private void AdjustRefCountsForContentDelete(ref TextTreeNode previousNode, ElementEdge previousEdge, ref TextTreeNode nextNode, ElementEdge nextEdge, TextTreeNode middleSubTree) { bool leftEdgeReferenceCount; bool rightEdgeReferenceCount; leftEdgeReferenceCount = false; rightEdgeReferenceCount = false; // Get the count of all positions referencing text node edges across the deleted content. GetReferenceCounts((TextTreeNode)middleSubTree.GetMinSibling(), ref leftEdgeReferenceCount, ref rightEdgeReferenceCount); previousNode = previousNode.IncrementReferenceCount(previousEdge, rightEdgeReferenceCount); nextNode = nextNode.IncrementReferenceCount(nextEdge, leftEdgeReferenceCount); }
// Called by the TextPointer ctor. Initializes this instance. private void Initialize(TextContainer tree, TextTreeNode node, ElementEdge edge, LogicalDirection gravity, uint generation, bool caretUnitBoundaryCache, bool isCaretUnitBoundaryCacheValid, uint layoutGeneration) { _tree = tree; // Fixup of the target node based on gravity. // Positions always cling to a node edge that matches their gravity, // so that insert ops never affect the position. RepositionForGravity(ref node, ref edge, gravity); SetNodeAndEdge(node.IncrementReferenceCount(edge), edge); _generation = generation; this.CaretUnitBoundaryCache = caretUnitBoundaryCache; this.IsCaretUnitBoundaryCacheValid = isCaretUnitBoundaryCacheValid; _layoutGeneration = layoutGeneration; VerifyFlags(); tree.AssertTree(); AssertState(); }