Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Framework / System / Windows / Documents / TextTreeNode.cs / 1 / TextTreeNode.cs
//---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // // Description: Base class for all nodes in the TextContainer. // // // History: // 02/18/2004 : benwest - Created // //--------------------------------------------------------------------------- using System; using MS.Internal; namespace System.Windows.Documents { #if INT_EDGE_REF_COUNT // A container for position reference counts on a node edge. // Since typically a node won't have any references, we // lazy allocate an EdgeReferenceCounts only when necessary // to save a little space on tree nodes. internal class EdgeReferenceCounts { internal int BeforeStartReferenceCount { get { return _beforeStartReferenceCount; } set { _beforeStartReferenceCount = value; } } internal virtual int AfterStartReferenceCount { get { return 0; } set { Invariant.Assert(false, "Text/Object nodes have no AfterStart edge!"); } } internal virtual int BeforeEndReferenceCount { get { return 0; } set { Invariant.Assert(false, "Text/Object nodes have no BeforeEnd edge!"); } } internal int AfterEndReferenceCount { get { return _afterEndReferenceCount; } set { _afterEndReferenceCount = value; } } private int _beforeStartReferenceCount; private int _afterEndReferenceCount; } // Element reference counts adds AfterStart/BeforeEnd counts. internal class ElementEdgeReferenceCounts : EdgeReferenceCounts { internal override int AfterStartReferenceCount { get { return _afterStartReferenceCount; } set { _afterStartReferenceCount = value; } } internal override int BeforeEndReferenceCount { get { return _beforeEndReferenceCount; } set { _beforeEndReferenceCount = value; } } private int _afterStartReferenceCount; private int _beforeEndReferenceCount; } #endif // INT_EDGE_REF_COUNT // This is the base class for all TextContainer nodes. It contains no state, // but has several abstract properties to derived class state. // // The vast majority of tree manipulations work with TextTreeNode rather // than derived classes. All splay tree balancing code lives in this class. // // Nodes in the TextContainer live within two hierarchies. Sibling nodes are // stored in splay trees, a type of balanced binary tree. Some nodes, // the TextTreeRootNode and TextTreeTextElementNodes, "contain" other nodes // which are themselves roots of splay trees. So an individual node is // always in a splay tree along with its siblings, and it may contain // a splay tree of its own children. // // For example, // //Hi! Fancy // // becomes // // [TextTreeRootNode] // || // [TextTreeTextElementNode] // || \ // || \ // || \ // [TextTreeTextNode "Hi!"] [TextTreeTextElementNode] // || // [TextTreeTextElementNode] // / || \ // / || \ // / || \ // / || \ // / || \ // / || \ // [TextTreeTextNode "Fancy "] [TextTreeTextNode "text"] [TextTreeTextNode "."] // // "||" is a link from tree to tree, "|" is a link between nodes in a single tree. // // The splay tree algorithm relies on a balancing operation, Splay(), performed // after each node access. It's very important to continue splaying the tree // as nodes are accessed, or we'll have an unbalanced binary tree. If you're // trying to figure out why the tree perf has regressed and you see deep trees, // read up on the splay tree algorithm in your reference book of choice and // then consider whether or not Splay() is being called appropriately from any // new code. internal abstract class TextTreeNode : SplayTreeNode { //----------------------------------------------------- // // Protected Methods // //----------------------------------------------------- #region Protected Methods #if INT_EDGE_REF_COUNT // Sets the count of TextPositions referencing the node's left // edge. // Since nodes don't usually have any references, we demand allocate // storage when needed. protected static void SetBeforeStartReferenceCount(ref EdgeReferenceCounts edgeReferenceCounts, int value) { if (edgeReferenceCounts != null) { if (value == 0 && edgeReferenceCounts.AfterStartReferenceCount == 0 && edgeReferenceCounts.BeforeEndReferenceCount == 0 && edgeReferenceCounts.AfterEndReferenceCount == 0) { edgeReferenceCounts = null; } else { edgeReferenceCounts.BeforeStartReferenceCount = value; } } else if (value != 0) { edgeReferenceCounts = new EdgeReferenceCounts(); edgeReferenceCounts.BeforeStartReferenceCount = value; } } // Sets the count of TextPositions referencing the node's AfterStart edge. // Since nodes don't usually have any references, we demand allocate // storage when needed. protected void SetAfterStartReferenceCount(ref EdgeReferenceCounts edgeReferenceCounts, int value) { EdgeReferenceCounts originalCounts; if (edgeReferenceCounts != null) { if (value == 0 && edgeReferenceCounts.BeforeStartReferenceCount == 0 && edgeReferenceCounts.BeforeEndReferenceCount == 0 && edgeReferenceCounts.AfterEndReferenceCount == 0) { edgeReferenceCounts = null; } else { if (!(edgeReferenceCounts is ElementEdgeReferenceCounts)) { // We need a slightly bigger object, which tracks the inner edges. Invariant.Assert(this is TextTreeTextElementNode, "Non-element nodes should never have inner edge references!"); originalCounts = edgeReferenceCounts; edgeReferenceCounts = new ElementEdgeReferenceCounts(); edgeReferenceCounts.BeforeStartReferenceCount = originalCounts.BeforeStartReferenceCount; edgeReferenceCounts.AfterEndReferenceCount = originalCounts.AfterEndReferenceCount; } edgeReferenceCounts.AfterStartReferenceCount = value; } } else if (value != 0) { edgeReferenceCounts = new ElementEdgeReferenceCounts(); edgeReferenceCounts.AfterStartReferenceCount = value; } } // Sets the count of TextPositions referencing the node's BeforeEnd edge. // Since nodes don't usually have any references, we demand allocate // storage when needed. protected void SetBeforeEndReferenceCount(ref EdgeReferenceCounts edgeReferenceCounts, int value) { EdgeReferenceCounts originalCounts; if (edgeReferenceCounts != null) { if (value == 0 && edgeReferenceCounts.BeforeStartReferenceCount == 0 && edgeReferenceCounts.AfterStartReferenceCount == 0 && edgeReferenceCounts.AfterEndReferenceCount == 0) { edgeReferenceCounts = null; } else { if (!(edgeReferenceCounts is ElementEdgeReferenceCounts)) { // We need a slightly bigger object, which tracks the inner edges. Invariant.Assert(this is TextTreeTextElementNode, "Non-element nodes should never have inner edge references!"); originalCounts = edgeReferenceCounts; edgeReferenceCounts = new ElementEdgeReferenceCounts(); edgeReferenceCounts.BeforeStartReferenceCount = originalCounts.BeforeStartReferenceCount; edgeReferenceCounts.AfterEndReferenceCount = originalCounts.AfterEndReferenceCount; } edgeReferenceCounts.BeforeEndReferenceCount = value; } } else if (value != 0) { edgeReferenceCounts = new ElementEdgeReferenceCounts(); edgeReferenceCounts.BeforeEndReferenceCount = value; } } // Sets the count of TextPositions referencing the node's right // edge. // Since nodes don't usually have any references, we demand allocate // storage when needed. protected static void SetAfterEndReferenceCount(ref EdgeReferenceCounts edgeReferenceCounts, int value) { if (edgeReferenceCounts != null) { if (value == 0 && edgeReferenceCounts.BeforeStartReferenceCount == 0 && edgeReferenceCounts.AfterStartReferenceCount == 0 && edgeReferenceCounts.BeforeEndReferenceCount == 0) { edgeReferenceCounts = null; } else { edgeReferenceCounts.AfterEndReferenceCount = value; } } else if (value != 0) { edgeReferenceCounts = new EdgeReferenceCounts(); edgeReferenceCounts.AfterEndReferenceCount = value; } } #endif // INT_EDGE_REF_COUNT #endregion Protected Methods //------------------------------------------------------ // // Internal Methods // //----------------------------------------------------- #region Internal Methods // Returns a shallow copy of this node. // The clone is a local root with no children. internal abstract TextTreeNode Clone(); // Returns the TextContainer containing this node. internal TextContainer GetTextTree() { SplayTreeNode node; SplayTreeNode containingNode; node = this; while (true) { containingNode = node.GetContainingNode(); if (containingNode == null) break; node = containingNode; } return ((TextTreeRootNode)node).TextContainer; } // Returns the closest DependencyObject scoping a given node. // This includes the node itself and TextContainer.Parent. internal DependencyObject GetDependencyParent() { SplayTreeNode node; DependencyObject parent; SplayTreeNode containingNode; TextTreeTextElementNode elementNode; node = this; while (true) { elementNode = node as TextTreeTextElementNode; if (elementNode != null) { parent = elementNode.TextElement; Invariant.Assert(parent != null, "TextElementNode has null TextElement!"); break; } containingNode = node.GetContainingNode(); if (containingNode == null) { parent = ((TextTreeRootNode)node).TextContainer.Parent; // This may be null. break; } node = containingNode; } return parent; } // Returns the closest Logical Tree Node to a given node, including the // node itself and TextContainer.Parent. internal DependencyObject GetLogicalTreeNode() { TextTreeObjectNode objectNode; TextTreeTextElementNode textElementNode; SplayTreeNode node; SplayTreeNode containingNode; DependencyObject logicalTreeNode; objectNode = this as TextTreeObjectNode; if (objectNode != null) { if (objectNode.EmbeddedElement is FrameworkElement) { return objectNode.EmbeddedElement; } } node = this; while (true) { textElementNode = node as TextTreeTextElementNode; if (textElementNode != null) { logicalTreeNode = textElementNode.TextElement; break; } containingNode = node.GetContainingNode(); if (containingNode == null) { logicalTreeNode = ((TextTreeRootNode)node).TextContainer.Parent; break; } node = containingNode; } return logicalTreeNode; } // Returns the TextPointerContext of the node. // If node is TextTreeTextElementNode, this method returns ElementStart // if direction == Forward, otherwise ElementEnd if direction == Backward. internal abstract TextPointerContext GetPointerContext(LogicalDirection direction); // Increments the reference count of TextPositions referencing a // particular edge of this node. // // If this node is a TextTreeTextNode, the increment may split the node // and the return value is guaranteed to be the node containing the referenced // edge (which may be a new node). Otherwise this method always returns // the original node. internal TextTreeNode IncrementReferenceCount(ElementEdge edge) { return IncrementReferenceCount(edge, +1); } internal virtual TextTreeNode IncrementReferenceCount(ElementEdge edge, bool delta) { return IncrementReferenceCount(edge, delta ? 1 : 0); } // Increments the reference count of TextPositions referencing a // particular edge of this node. // // If this node is a TextTreeTextNode, the increment may split the node // and the return value is guaranteed to be the node containing the referenced // edge (which may be a new node). Otherwise this method always returns // the original node. internal virtual TextTreeNode IncrementReferenceCount(ElementEdge edge, int delta) { Invariant.Assert(delta >= 0); if (delta > 0) { switch (edge) { case ElementEdge.BeforeStart: this.BeforeStartReferenceCount = true; break; case ElementEdge.AfterStart: this.AfterStartReferenceCount = true; break; case ElementEdge.BeforeEnd: this.BeforeEndReferenceCount = true; break; case ElementEdge.AfterEnd: this.AfterEndReferenceCount = true; break; default: Invariant.Assert(false, "Bad ElementEdge value!"); break; } } return this; } // Decrements the reference count of TextPositions referencing this // node. // // Be careful! If this node is a TextTreeTextNode, the decrement may // cause a merge, and this node may be removed from the tree. internal virtual void DecrementReferenceCount(ElementEdge edge) { #if INT_EDGE_REF_COUNT switch (edge) { case ElementEdge.BeforeStart: this.BeforeStartReferenceCount--; Invariant.Assert(this.BeforeStartReferenceCount >= 0, "Bad BeforeStart ref count!"); break; case ElementEdge.AfterStart: this.AfterStartReferenceCount--; Invariant.Assert(this.AfterStartReferenceCount >= 0, "Bad AfterStart ref count!"); break; case ElementEdge.BeforeEnd: this.BeforeEndReferenceCount--; Invariant.Assert(this.BeforeEndReferenceCount >= 0, "Bad BeforeEnd ref count!"); break; case ElementEdge.AfterEnd: this.AfterEndReferenceCount--; Invariant.Assert(this.AfterEndReferenceCount >= 0, "Bad AfterEnd ref count!"); break; default: Invariant.Assert(false, "Bad ElementEdge value!"); break; } #endif // INT_EDGE_REF_COUNT } // Inserts a node at a specified position. internal void InsertAtPosition(TextPointer position) { InsertAtNode(position.Node, position.Edge); } internal ElementEdge GetEdgeFromOffsetNoBias(int nodeOffset) { return GetEdgeFromOffset(nodeOffset, LogicalDirection.Forward); } internal ElementEdge GetEdgeFromOffset(int nodeOffset, LogicalDirection bias) { ElementEdge edge; if (this.SymbolCount == 0) { // If we're pointing at a zero-width TextTreeTextNode, we need to make // sure we get the right edge -- nodeOffset doesn't convey enough information // for GetEdgeFromOffset to compute a correct value. edge = (bias == LogicalDirection.Forward) ? ElementEdge.AfterEnd : ElementEdge.BeforeStart; } else if (nodeOffset == 0) { edge = ElementEdge.BeforeStart; } else if (nodeOffset == this.SymbolCount) { edge = ElementEdge.AfterEnd; } else if (nodeOffset == 1) { edge = ElementEdge.AfterStart; } else { Invariant.Assert(nodeOffset == this.SymbolCount - 1); edge = ElementEdge.BeforeEnd; } return edge; } internal int GetOffsetFromEdge(ElementEdge edge) { int offset; switch (edge) { case ElementEdge.BeforeStart: offset = 0; break; case ElementEdge.AfterStart: offset = 1; break; case ElementEdge.BeforeEnd: offset = this.SymbolCount - 1; break; case ElementEdge.AfterEnd: offset = this.SymbolCount; break; default: offset = 0; Invariant.Assert(false, "Bad ElementEdge value!"); break; } return offset; } #endregion Internal methods //------------------------------------------------------ // // Internal Properties // //------------------------------------------------------ #region Internal Properties // Count of TextPositions referencing the node's BeforeStart edge. internal abstract bool BeforeStartReferenceCount { get; set; } // Count of TextPositions referencing the node's AfterStart edge. internal abstract bool AfterStartReferenceCount { get; set; } // Count of TextPositions referencing the node's BeforeEnd edge. internal abstract bool BeforeEndReferenceCount { get; set; } // Count of TextPositions referencing the node's AfterEnd edge. internal abstract bool AfterEndReferenceCount { get; set; } #endregion Internal Properties } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //---------------------------------------------------------------------------- // //text .// Copyright (C) Microsoft Corporation. All rights reserved. // // // // Description: Base class for all nodes in the TextContainer. // // // History: // 02/18/2004 : benwest - Created // //--------------------------------------------------------------------------- using System; using MS.Internal; namespace System.Windows.Documents { #if INT_EDGE_REF_COUNT // A container for position reference counts on a node edge. // Since typically a node won't have any references, we // lazy allocate an EdgeReferenceCounts only when necessary // to save a little space on tree nodes. internal class EdgeReferenceCounts { internal int BeforeStartReferenceCount { get { return _beforeStartReferenceCount; } set { _beforeStartReferenceCount = value; } } internal virtual int AfterStartReferenceCount { get { return 0; } set { Invariant.Assert(false, "Text/Object nodes have no AfterStart edge!"); } } internal virtual int BeforeEndReferenceCount { get { return 0; } set { Invariant.Assert(false, "Text/Object nodes have no BeforeEnd edge!"); } } internal int AfterEndReferenceCount { get { return _afterEndReferenceCount; } set { _afterEndReferenceCount = value; } } private int _beforeStartReferenceCount; private int _afterEndReferenceCount; } // Element reference counts adds AfterStart/BeforeEnd counts. internal class ElementEdgeReferenceCounts : EdgeReferenceCounts { internal override int AfterStartReferenceCount { get { return _afterStartReferenceCount; } set { _afterStartReferenceCount = value; } } internal override int BeforeEndReferenceCount { get { return _beforeEndReferenceCount; } set { _beforeEndReferenceCount = value; } } private int _afterStartReferenceCount; private int _beforeEndReferenceCount; } #endif // INT_EDGE_REF_COUNT // This is the base class for all TextContainer nodes. It contains no state, // but has several abstract properties to derived class state. // // The vast majority of tree manipulations work with TextTreeNode rather // than derived classes. All splay tree balancing code lives in this class. // // Nodes in the TextContainer live within two hierarchies. Sibling nodes are // stored in splay trees, a type of balanced binary tree. Some nodes, // the TextTreeRootNode and TextTreeTextElementNodes, "contain" other nodes // which are themselves roots of splay trees. So an individual node is // always in a splay tree along with its siblings, and it may contain // a splay tree of its own children. // // For example, // //Hi! Fancy // // becomes // // [TextTreeRootNode] // || // [TextTreeTextElementNode] // || \ // || \ // || \ // [TextTreeTextNode "Hi!"] [TextTreeTextElementNode] // || // [TextTreeTextElementNode] // / || \ // / || \ // / || \ // / || \ // / || \ // / || \ // [TextTreeTextNode "Fancy "] [TextTreeTextNode "text"] [TextTreeTextNode "."] // // "||" is a link from tree to tree, "|" is a link between nodes in a single tree. // // The splay tree algorithm relies on a balancing operation, Splay(), performed // after each node access. It's very important to continue splaying the tree // as nodes are accessed, or we'll have an unbalanced binary tree. If you're // trying to figure out why the tree perf has regressed and you see deep trees, // read up on the splay tree algorithm in your reference book of choice and // then consider whether or not Splay() is being called appropriately from any // new code. internal abstract class TextTreeNode : SplayTreeNode { //----------------------------------------------------- // // Protected Methods // //----------------------------------------------------- #region Protected Methods #if INT_EDGE_REF_COUNT // Sets the count of TextPositions referencing the node's left // edge. // Since nodes don't usually have any references, we demand allocate // storage when needed. protected static void SetBeforeStartReferenceCount(ref EdgeReferenceCounts edgeReferenceCounts, int value) { if (edgeReferenceCounts != null) { if (value == 0 && edgeReferenceCounts.AfterStartReferenceCount == 0 && edgeReferenceCounts.BeforeEndReferenceCount == 0 && edgeReferenceCounts.AfterEndReferenceCount == 0) { edgeReferenceCounts = null; } else { edgeReferenceCounts.BeforeStartReferenceCount = value; } } else if (value != 0) { edgeReferenceCounts = new EdgeReferenceCounts(); edgeReferenceCounts.BeforeStartReferenceCount = value; } } // Sets the count of TextPositions referencing the node's AfterStart edge. // Since nodes don't usually have any references, we demand allocate // storage when needed. protected void SetAfterStartReferenceCount(ref EdgeReferenceCounts edgeReferenceCounts, int value) { EdgeReferenceCounts originalCounts; if (edgeReferenceCounts != null) { if (value == 0 && edgeReferenceCounts.BeforeStartReferenceCount == 0 && edgeReferenceCounts.BeforeEndReferenceCount == 0 && edgeReferenceCounts.AfterEndReferenceCount == 0) { edgeReferenceCounts = null; } else { if (!(edgeReferenceCounts is ElementEdgeReferenceCounts)) { // We need a slightly bigger object, which tracks the inner edges. Invariant.Assert(this is TextTreeTextElementNode, "Non-element nodes should never have inner edge references!"); originalCounts = edgeReferenceCounts; edgeReferenceCounts = new ElementEdgeReferenceCounts(); edgeReferenceCounts.BeforeStartReferenceCount = originalCounts.BeforeStartReferenceCount; edgeReferenceCounts.AfterEndReferenceCount = originalCounts.AfterEndReferenceCount; } edgeReferenceCounts.AfterStartReferenceCount = value; } } else if (value != 0) { edgeReferenceCounts = new ElementEdgeReferenceCounts(); edgeReferenceCounts.AfterStartReferenceCount = value; } } // Sets the count of TextPositions referencing the node's BeforeEnd edge. // Since nodes don't usually have any references, we demand allocate // storage when needed. protected void SetBeforeEndReferenceCount(ref EdgeReferenceCounts edgeReferenceCounts, int value) { EdgeReferenceCounts originalCounts; if (edgeReferenceCounts != null) { if (value == 0 && edgeReferenceCounts.BeforeStartReferenceCount == 0 && edgeReferenceCounts.AfterStartReferenceCount == 0 && edgeReferenceCounts.AfterEndReferenceCount == 0) { edgeReferenceCounts = null; } else { if (!(edgeReferenceCounts is ElementEdgeReferenceCounts)) { // We need a slightly bigger object, which tracks the inner edges. Invariant.Assert(this is TextTreeTextElementNode, "Non-element nodes should never have inner edge references!"); originalCounts = edgeReferenceCounts; edgeReferenceCounts = new ElementEdgeReferenceCounts(); edgeReferenceCounts.BeforeStartReferenceCount = originalCounts.BeforeStartReferenceCount; edgeReferenceCounts.AfterEndReferenceCount = originalCounts.AfterEndReferenceCount; } edgeReferenceCounts.BeforeEndReferenceCount = value; } } else if (value != 0) { edgeReferenceCounts = new ElementEdgeReferenceCounts(); edgeReferenceCounts.BeforeEndReferenceCount = value; } } // Sets the count of TextPositions referencing the node's right // edge. // Since nodes don't usually have any references, we demand allocate // storage when needed. protected static void SetAfterEndReferenceCount(ref EdgeReferenceCounts edgeReferenceCounts, int value) { if (edgeReferenceCounts != null) { if (value == 0 && edgeReferenceCounts.BeforeStartReferenceCount == 0 && edgeReferenceCounts.AfterStartReferenceCount == 0 && edgeReferenceCounts.BeforeEndReferenceCount == 0) { edgeReferenceCounts = null; } else { edgeReferenceCounts.AfterEndReferenceCount = value; } } else if (value != 0) { edgeReferenceCounts = new EdgeReferenceCounts(); edgeReferenceCounts.AfterEndReferenceCount = value; } } #endif // INT_EDGE_REF_COUNT #endregion Protected Methods //------------------------------------------------------ // // Internal Methods // //----------------------------------------------------- #region Internal Methods // Returns a shallow copy of this node. // The clone is a local root with no children. internal abstract TextTreeNode Clone(); // Returns the TextContainer containing this node. internal TextContainer GetTextTree() { SplayTreeNode node; SplayTreeNode containingNode; node = this; while (true) { containingNode = node.GetContainingNode(); if (containingNode == null) break; node = containingNode; } return ((TextTreeRootNode)node).TextContainer; } // Returns the closest DependencyObject scoping a given node. // This includes the node itself and TextContainer.Parent. internal DependencyObject GetDependencyParent() { SplayTreeNode node; DependencyObject parent; SplayTreeNode containingNode; TextTreeTextElementNode elementNode; node = this; while (true) { elementNode = node as TextTreeTextElementNode; if (elementNode != null) { parent = elementNode.TextElement; Invariant.Assert(parent != null, "TextElementNode has null TextElement!"); break; } containingNode = node.GetContainingNode(); if (containingNode == null) { parent = ((TextTreeRootNode)node).TextContainer.Parent; // This may be null. break; } node = containingNode; } return parent; } // Returns the closest Logical Tree Node to a given node, including the // node itself and TextContainer.Parent. internal DependencyObject GetLogicalTreeNode() { TextTreeObjectNode objectNode; TextTreeTextElementNode textElementNode; SplayTreeNode node; SplayTreeNode containingNode; DependencyObject logicalTreeNode; objectNode = this as TextTreeObjectNode; if (objectNode != null) { if (objectNode.EmbeddedElement is FrameworkElement) { return objectNode.EmbeddedElement; } } node = this; while (true) { textElementNode = node as TextTreeTextElementNode; if (textElementNode != null) { logicalTreeNode = textElementNode.TextElement; break; } containingNode = node.GetContainingNode(); if (containingNode == null) { logicalTreeNode = ((TextTreeRootNode)node).TextContainer.Parent; break; } node = containingNode; } return logicalTreeNode; } // Returns the TextPointerContext of the node. // If node is TextTreeTextElementNode, this method returns ElementStart // if direction == Forward, otherwise ElementEnd if direction == Backward. internal abstract TextPointerContext GetPointerContext(LogicalDirection direction); // Increments the reference count of TextPositions referencing a // particular edge of this node. // // If this node is a TextTreeTextNode, the increment may split the node // and the return value is guaranteed to be the node containing the referenced // edge (which may be a new node). Otherwise this method always returns // the original node. internal TextTreeNode IncrementReferenceCount(ElementEdge edge) { return IncrementReferenceCount(edge, +1); } internal virtual TextTreeNode IncrementReferenceCount(ElementEdge edge, bool delta) { return IncrementReferenceCount(edge, delta ? 1 : 0); } // Increments the reference count of TextPositions referencing a // particular edge of this node. // // If this node is a TextTreeTextNode, the increment may split the node // and the return value is guaranteed to be the node containing the referenced // edge (which may be a new node). Otherwise this method always returns // the original node. internal virtual TextTreeNode IncrementReferenceCount(ElementEdge edge, int delta) { Invariant.Assert(delta >= 0); if (delta > 0) { switch (edge) { case ElementEdge.BeforeStart: this.BeforeStartReferenceCount = true; break; case ElementEdge.AfterStart: this.AfterStartReferenceCount = true; break; case ElementEdge.BeforeEnd: this.BeforeEndReferenceCount = true; break; case ElementEdge.AfterEnd: this.AfterEndReferenceCount = true; break; default: Invariant.Assert(false, "Bad ElementEdge value!"); break; } } return this; } // Decrements the reference count of TextPositions referencing this // node. // // Be careful! If this node is a TextTreeTextNode, the decrement may // cause a merge, and this node may be removed from the tree. internal virtual void DecrementReferenceCount(ElementEdge edge) { #if INT_EDGE_REF_COUNT switch (edge) { case ElementEdge.BeforeStart: this.BeforeStartReferenceCount--; Invariant.Assert(this.BeforeStartReferenceCount >= 0, "Bad BeforeStart ref count!"); break; case ElementEdge.AfterStart: this.AfterStartReferenceCount--; Invariant.Assert(this.AfterStartReferenceCount >= 0, "Bad AfterStart ref count!"); break; case ElementEdge.BeforeEnd: this.BeforeEndReferenceCount--; Invariant.Assert(this.BeforeEndReferenceCount >= 0, "Bad BeforeEnd ref count!"); break; case ElementEdge.AfterEnd: this.AfterEndReferenceCount--; Invariant.Assert(this.AfterEndReferenceCount >= 0, "Bad AfterEnd ref count!"); break; default: Invariant.Assert(false, "Bad ElementEdge value!"); break; } #endif // INT_EDGE_REF_COUNT } // Inserts a node at a specified position. internal void InsertAtPosition(TextPointer position) { InsertAtNode(position.Node, position.Edge); } internal ElementEdge GetEdgeFromOffsetNoBias(int nodeOffset) { return GetEdgeFromOffset(nodeOffset, LogicalDirection.Forward); } internal ElementEdge GetEdgeFromOffset(int nodeOffset, LogicalDirection bias) { ElementEdge edge; if (this.SymbolCount == 0) { // If we're pointing at a zero-width TextTreeTextNode, we need to make // sure we get the right edge -- nodeOffset doesn't convey enough information // for GetEdgeFromOffset to compute a correct value. edge = (bias == LogicalDirection.Forward) ? ElementEdge.AfterEnd : ElementEdge.BeforeStart; } else if (nodeOffset == 0) { edge = ElementEdge.BeforeStart; } else if (nodeOffset == this.SymbolCount) { edge = ElementEdge.AfterEnd; } else if (nodeOffset == 1) { edge = ElementEdge.AfterStart; } else { Invariant.Assert(nodeOffset == this.SymbolCount - 1); edge = ElementEdge.BeforeEnd; } return edge; } internal int GetOffsetFromEdge(ElementEdge edge) { int offset; switch (edge) { case ElementEdge.BeforeStart: offset = 0; break; case ElementEdge.AfterStart: offset = 1; break; case ElementEdge.BeforeEnd: offset = this.SymbolCount - 1; break; case ElementEdge.AfterEnd: offset = this.SymbolCount; break; default: offset = 0; Invariant.Assert(false, "Bad ElementEdge value!"); break; } return offset; } #endregion Internal methods //------------------------------------------------------ // // Internal Properties // //------------------------------------------------------ #region Internal Properties // Count of TextPositions referencing the node's BeforeStart edge. internal abstract bool BeforeStartReferenceCount { get; set; } // Count of TextPositions referencing the node's AfterStart edge. internal abstract bool AfterStartReferenceCount { get; set; } // Count of TextPositions referencing the node's BeforeEnd edge. internal abstract bool BeforeEndReferenceCount { get; set; } // Count of TextPositions referencing the node's AfterEnd edge. internal abstract bool AfterEndReferenceCount { get; set; } #endregion Internal Properties } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.text .
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- Rect3DConverter.cs
- Pair.cs
- SvcMapFile.cs
- UserPersonalizationStateInfo.cs
- ELinqQueryState.cs
- BindingsCollection.cs
- cookiecollection.cs
- MetadataArtifactLoader.cs
- ADMembershipUser.cs
- DesignerActionUIService.cs
- SmtpAuthenticationManager.cs
- AppModelKnownContentFactory.cs
- HGlobalSafeHandle.cs
- RSAOAEPKeyExchangeFormatter.cs
- RangeBase.cs
- TextBoxView.cs
- UpdatePanel.cs
- NativeMethods.cs
- DataControlField.cs
- WindowsRichEdit.cs
- FixedFlowMap.cs
- ClientTargetCollection.cs
- StaticDataManager.cs
- HelpFileFileNameEditor.cs
- ParagraphVisual.cs
- DataServiceException.cs
- ListViewTableRow.cs
- ScrollPatternIdentifiers.cs
- SelectionProcessor.cs
- BuildResultCache.cs
- invalidudtexception.cs
- ZoneLinkButton.cs
- Accessible.cs
- SafeFileMappingHandle.cs
- EventLogPermissionHolder.cs
- WebPartDisplayModeEventArgs.cs
- precedingquery.cs
- BindingParameterCollection.cs
- _NegoStream.cs
- grammarelement.cs
- HttpCookie.cs
- ActiveXContainer.cs
- ValueOfAction.cs
- TreeNode.cs
- Point4DConverter.cs
- ObjectDataSourceSelectingEventArgs.cs
- MatchingStyle.cs
- WebPartVerbsEventArgs.cs
- DataAccessor.cs
- XmlDownloadManager.cs
- AttachedPropertyMethodSelector.cs
- QueryOutputWriter.cs
- IdnMapping.cs
- FixedSOMElement.cs
- XamlBrushSerializer.cs
- MsmqIntegrationAppDomainProtocolHandler.cs
- PropertyValueUIItem.cs
- EasingFunctionBase.cs
- FocusTracker.cs
- ButtonBase.cs
- BmpBitmapDecoder.cs
- BuildProvider.cs
- TemplateLookupAction.cs
- TabControlToolboxItem.cs
- BaseTemplateBuildProvider.cs
- ConnectionStringSettings.cs
- StringConcat.cs
- CopyAttributesAction.cs
- ADConnectionHelper.cs
- ClusterSafeNativeMethods.cs
- EntityAdapter.cs
- InlineCollection.cs
- DataGridViewRowHeightInfoNeededEventArgs.cs
- XmlWriterTraceListener.cs
- SecurityPermission.cs
- PropertyCollection.cs
- _BaseOverlappedAsyncResult.cs
- UserPersonalizationStateInfo.cs
- Property.cs
- ListView.cs
- WindowsAuthenticationModule.cs
- DataControlLinkButton.cs
- RegisteredArrayDeclaration.cs
- CaseInsensitiveComparer.cs
- Section.cs
- WebConfigurationHostFileChange.cs
- PrimitiveDataContract.cs
- TextEditorThreadLocalStore.cs
- SchemaElementDecl.cs
- EndpointConfigContainer.cs
- MethodBuilderInstantiation.cs
- InheritanceAttribute.cs
- BeginStoryboard.cs
- RectIndependentAnimationStorage.cs
- QuerySelectOp.cs
- DbProviderSpecificTypePropertyAttribute.cs
- ValidatorCollection.cs
- GridViewSelectEventArgs.cs
- HttpProfileBase.cs
- TdsEnums.cs