Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Framework / System / Windows / Documents / TextTreeTextNode.cs / 1 / TextTreeTextNode.cs
//---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // // Description: A TextContainer node representing a run of text. // // History: // 02/18/2004 : benwest - Created // //--------------------------------------------------------------------------- using System; using MS.Internal; namespace System.Windows.Documents { // Runs of text are represented internally by TextTreeTextNodes. // // Text nodes are regularly "split" -- broken in half -- when a // TextPointer needs to reference a character within the node's run. // We track a reference counts of the number of positions referencing a // text node so that we can later merge it back again when no TextPositions // reference it. // // Unlike other nodes, TextTreeTextNode may only ever be referenced on a // single edge by TextPositions. This is necessary to ensure that we // can split a text node any time a TextPositions needs to reference a // character within the node. With at most one edge referenced we are free // to create a new node covering the unreferenced edge without disturbing // any TextPositoins referencing the original node. // // Unlike all other nodes, text nodes may occasionally have zero symbol counts. // This happens when a TextPointer wants to reference a node edge, but // the node's other edge is already referenced by someone else. In this case, // we split the text node, adding a zero-width node just for the // TextPointer's use. internal class TextTreeTextNode : TextTreeNode { //----------------------------------------------------- // // Constructors // //----------------------------------------------------- #region Constructors // Creates a new TextTreeTextNode instance. internal TextTreeTextNode() { _symbolOffsetCache = -1; } #endregion Constructors //------------------------------------------------------ // // Public Methods // //----------------------------------------------------- #region Public Methods #if DEBUG // Debug-only ToString override. public override string ToString() { return ("TextNode Id=" + this.DebugId + " SymbolCount=" + _symbolCount); } #endif // DEBUG #endregion Public Methods //------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ #region Internal Methods // Returns a shallow copy of this node. // Returns null if this node has a zero symbol count -- // a clone would have no references, so there's no point // in allocating one. internal override TextTreeNode Clone() { TextTreeTextNode clone; clone = null; if (_symbolCount > 0) { clone = new TextTreeTextNode(); clone._symbolCount = _symbolCount; } return clone; } // Returns the TextPointerContext of the node. internal override TextPointerContext GetPointerContext(LogicalDirection direction) { return TextPointerContext.Text; } // Increments a count of the number of TextPositions and TextNavigators // referencing this node. Called when positions are created or moved. // Returns the actual node referenced -- a new node will be created if // there are already references to this node's other edge. internal override TextTreeNode IncrementReferenceCount(ElementEdge edge, int delta) { TextTreeTextNode node; TextTreeTextNode mergeNode; Invariant.Assert(delta >= 0); Invariant.Assert(edge == ElementEdge.BeforeStart || edge == ElementEdge.AfterEnd, "Bad edge ref to TextTreeTextNode!"); if (delta == 0) { return this; } if (_positionRefCount > 0 && edge != _referencedEdge) { // We need to split off a node to cover the new edge. node = Split(edge == ElementEdge.BeforeStart ? 0 : _symbolCount, edge); node._referencedEdge = edge; node._positionRefCount += delta; // It's possible we need to merge a neighbor node. // This happens when someone calls TextContainer.GetNodeAndEdgeAtOffset, // which splits a text node into two non-empty nodes. We can't merge // immediately, because we don't know which of the two nodes will // get an additional ref. // If the unreferenced node of the pair gets the new reference, // there no possibility for a merge. Otherwise, we have to split // again on the already referenced node and end up here. if (edge == ElementEdge.BeforeStart) { // If node B has no references it can merge with node A. //mergeNode = node.GetPreviousNode() as TextTreeTextNode; } else { // If node A has no references it can merge with node B. // mergeNode = node.GetNextNode() as TextTreeTextNode; } if (mergeNode != null && mergeNode._positionRefCount == 0) { mergeNode.Merge(); } } else { node = this; _referencedEdge = edge; _positionRefCount += delta; } return node; } // Decrements a count of the number of TextPositions and TextNavigators // referencing this node. // This method attempts to merge adjacent TextTreeTextNodes when the ref count // transitions from 1 to 0. // // Be careful! This can modify the tree, removing // TextTreeTextNodes. internal override void DecrementReferenceCount(ElementEdge edge) { Invariant.Assert(edge == _referencedEdge, "Bad edge decrement!"); _positionRefCount--; Invariant.Assert(_positionRefCount >= 0, "Bogus PositionRefCount! "); // If the ref count drops to zero, we may be able to merge this node with an adjacent one. if (_positionRefCount == 0) { Merge(); } } // Splits this node into two adjacent nodes. // Returns the node which contains the original requested edge // (e.g., if edge == ElementEdge.BeforeStart, this method returns the // preceding node, if edge == ElementEdge.AfterEnd, it returns the // following node). internal TextTreeTextNode Split(int localOffset, ElementEdge edge) { TextTreeTextNode newNode; TextTreeTextNode edgeNode; ElementEdge newNodeEdge; Invariant.Assert(_symbolCount > 0, "Splitting a zero-width TextNode!"); Invariant.Assert(localOffset >= 0 && localOffset <= _symbolCount, "Bad localOffset!"); Invariant.Assert(edge == ElementEdge.BeforeStart || edge == ElementEdge.AfterEnd, "Bad edge parameter!"); #if DEBUG if (localOffset == 0) { TextTreeNode previousNode; Invariant.Assert(edge == ElementEdge.BeforeStart, "Unexpected edge!"); Invariant.Assert(edge != _referencedEdge, "Splitting at referenced edge!"); previousNode = (TextTreeNode)GetPreviousNode(); Invariant.Assert(previousNode == null || previousNode.SymbolCount > 0 || previousNode.AfterEndReferenceCount, "Found preceding zero-width text node inside Split!"); } else if (localOffset == _symbolCount) { TextTreeNode nextNode; Invariant.Assert(edge == ElementEdge.AfterEnd, "Unexpected edge!"); Invariant.Assert(edge != _referencedEdge, "Splitting at referenced edge!"); nextNode = (TextTreeNode)GetNextNode(); Invariant.Assert(nextNode == null || nextNode.SymbolCount > 0 || nextNode.BeforeStartReferenceCount, "Found following zero-width text node inside Split! (2)"); } #endif // DEBUG newNode = new TextTreeTextNode(); newNode._generation = _generation; // Splay this node to the root so we don't corrupt any LeftSymbolCounts // of ancestor nodes when we fixup _symbolCount below. Splay(); if (_positionRefCount > 0 && _referencedEdge == ElementEdge.BeforeStart) { // New node is the following node. newNode._symbolOffsetCache = (_symbolOffsetCache == -1) ? -1 : _symbolOffsetCache + localOffset; newNode._symbolCount = _symbolCount - localOffset; _symbolCount = localOffset; newNodeEdge = ElementEdge.AfterEnd; edgeNode = (edge == ElementEdge.BeforeStart) ? this : newNode; } else { // New node is the preceding node. newNode._symbolOffsetCache = _symbolOffsetCache; newNode._symbolCount = localOffset; _symbolOffsetCache = (_symbolOffsetCache == -1) ? -1 : _symbolOffsetCache + localOffset; _symbolCount -= localOffset; newNodeEdge = ElementEdge.BeforeStart; edgeNode = (edge == ElementEdge.BeforeStart) ? newNode : this; } Invariant.Assert(_symbolCount >= 0); Invariant.Assert(newNode._symbolCount >= 0); newNode.InsertAtNode(this, newNodeEdge); return edgeNode; } #endregion Internal methods //----------------------------------------------------- // // Internal Properties // //------------------------------------------------------ #region Internal Properties // If this node is a local root, then ParentNode contains it. // Otherwise, this is the node parenting this node within its tree. internal override SplayTreeNode ParentNode { get { return _parentNode; } set { _parentNode = (TextTreeNode)value; } } // TextTreeTextNode never has contained nodes. internal override SplayTreeNode ContainedNode { get { return null; } set { Invariant.Assert(false, "Can't set child on a TextTreeTextNode!"); } } // Count of symbols of all siblings preceding this node. internal override int LeftSymbolCount { get { return _leftSymbolCount; } set { _leftSymbolCount = value; } } // Count of chars of all siblings preceding this node. internal override int LeftCharCount { get { return _leftCharCount; } set { _leftCharCount = value; } } // Left child node in a sibling tree. internal override SplayTreeNode LeftChildNode { get { return _leftChildNode; } set { _leftChildNode = (TextTreeNode)value; } } // Right child node in a sibling tree. internal override SplayTreeNode RightChildNode { get { return _rightChildNode; } set { _rightChildNode = (TextTreeNode)value; } } // The TextContainer's generation when SymbolOffsetCache was last updated. // If the current generation doesn't match TextContainer.Generation, then // SymbolOffsetCache is invalid. internal override uint Generation { get { return _generation; } set { _generation = value; } } // Cached symbol offset. internal override int SymbolOffsetCache { get { return _symbolOffsetCache; } set { _symbolOffsetCache = value; } } // Count of symbols covered by this node. internal override int SymbolCount { get { return _symbolCount; } set { _symbolCount = value; } } // Count of chars covered by this node. internal override int IMECharCount { get { return this.SymbolCount; } set { // Tracked redundently by _symbolCount. } } // Count of TextPositions referencing the node's BeforeStart edge. internal override bool BeforeStartReferenceCount { get { return _referencedEdge == ElementEdge.BeforeStart ? _positionRefCount > 0 : false; } set { Invariant.Assert(false, "Can't set TextTreeTextNode ref counts directly!"); } } // Count of TextPositions referencing the node's AfterStart edge. // Since text nodes don't have an AfterStart edge, this is always zero. internal override bool AfterStartReferenceCount { get { return false; } set { Invariant.Assert(false, "Text nodes don't have an AfterStart edge!"); } } // Count of TextPositions referencing the node's BeforeEnd edge. // Since text nodes don't have an BeforeEnd edge, this is always zero. internal override bool BeforeEndReferenceCount { get { return false; } set { Invariant.Assert(false, "Text nodes don't have a BeforeEnd edge!"); } } // Count of TextPositions referencing the node's AfterEnd edge. internal override bool AfterEndReferenceCount { get { return _referencedEdge == ElementEdge.AfterEnd ? _positionRefCount > 0 : false; } set { Invariant.Assert(false, "Can't set TextTreeTextNode ref counts directly!"); } } #endregion Internal Properties //----------------------------------------------------- // // Private Methods // //----------------------------------------------------- #region Private Methods // Attempts to merge this node with adjacent TextTreeTextNodes. // Called when the position ref counts drops from 1 to 0. private void Merge() { TextTreeTextNode previousNode; TextTreeTextNode nextNode; Invariant.Assert(_positionRefCount == 0, "Inappropriate Merge call!"); // Check the previous node. previousNode = GetPreviousNode() as TextTreeTextNode; if (previousNode != null && (previousNode._positionRefCount == 0 || previousNode._referencedEdge == ElementEdge.BeforeStart)) { // The previous node must take the place of this one, since previous // may still have references. Remove(); // null _parentNode out so that if there's a bug and someone still references this node we'll hear about it. _parentNode = null; previousNode.Splay(); previousNode._symbolCount += _symbolCount; } else { previousNode = this; } // Check the following node. nextNode = previousNode.GetNextNode() as TextTreeTextNode; if (nextNode != null) { if (previousNode._positionRefCount == 0 && (nextNode._positionRefCount == 0 || (nextNode._referencedEdge == ElementEdge.AfterEnd))) { // nextNode must take the place of previousNode, since nextNode // may still have references. previousNode.Remove(); // null _parentNode out so that if there's a bug and someone still references this node we'll hear about it. previousNode._parentNode = null; nextNode.Splay(); if (nextNode._symbolOffsetCache != -1) { nextNode._symbolOffsetCache -= previousNode._symbolCount; } nextNode._symbolCount += previousNode._symbolCount; } else if ((previousNode._positionRefCount == 0 || previousNode._referencedEdge == ElementEdge.BeforeStart) && nextNode._positionRefCount == 0) { // The previous node must take the place of next one, since previousNode // may still have references. nextNode.Remove(); // null _parentNode out so that if there's a bug and someone still references this node we'll hear about it. nextNode._parentNode = null; previousNode.Splay(); previousNode._symbolCount += nextNode._symbolCount; } } } #endregion Private methods //----------------------------------------------------- // // Private Fields // //------------------------------------------------------ #region Private Fields // Count of symbols of all siblings preceding this node. private int _leftSymbolCount; // Count of chars of all siblings preceding this node. private int _leftCharCount; // If this node is a local root, then ParentNode contains it. // Otherwise, this is the node parenting this node within its tree. private TextTreeNode _parentNode; // Left child node in a sibling tree. private TextTreeNode _leftChildNode; // Right child node in a sibling tree. private TextTreeNode _rightChildNode; // // The TextContainer's generation when SymbolOffsetCache was last updated. // If the current generation doesn't match TextContainer.Generation, then // SymbolOffsetCache is invalid. private uint _generation; // Cached symbol offset. private int _symbolOffsetCache; // Count of symbols/chars covered by this node. private int _symbolCount; // The number of TextPositions referencing an edge of this node. // If _positionRefCount is zero, it's safe to merge with surrouding nodes. // private int _positionRefCount; // The edge referenced by one or more TextPositions. // Only valid when _positionRefCount > 0. private ElementEdge _referencedEdge; #endregion Private Fields } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //---------------------------------------------------------------------------- // // // Copyright (C) Microsoft Corporation. All rights reserved. // // // // Description: A TextContainer node representing a run of text. // // History: // 02/18/2004 : benwest - Created // //--------------------------------------------------------------------------- using System; using MS.Internal; namespace System.Windows.Documents { // Runs of text are represented internally by TextTreeTextNodes. // // Text nodes are regularly "split" -- broken in half -- when a // TextPointer needs to reference a character within the node's run. // We track a reference counts of the number of positions referencing a // text node so that we can later merge it back again when no TextPositions // reference it. // // Unlike other nodes, TextTreeTextNode may only ever be referenced on a // single edge by TextPositions. This is necessary to ensure that we // can split a text node any time a TextPositions needs to reference a // character within the node. With at most one edge referenced we are free // to create a new node covering the unreferenced edge without disturbing // any TextPositoins referencing the original node. // // Unlike all other nodes, text nodes may occasionally have zero symbol counts. // This happens when a TextPointer wants to reference a node edge, but // the node's other edge is already referenced by someone else. In this case, // we split the text node, adding a zero-width node just for the // TextPointer's use. internal class TextTreeTextNode : TextTreeNode { //----------------------------------------------------- // // Constructors // //----------------------------------------------------- #region Constructors // Creates a new TextTreeTextNode instance. internal TextTreeTextNode() { _symbolOffsetCache = -1; } #endregion Constructors //------------------------------------------------------ // // Public Methods // //----------------------------------------------------- #region Public Methods #if DEBUG // Debug-only ToString override. public override string ToString() { return ("TextNode Id=" + this.DebugId + " SymbolCount=" + _symbolCount); } #endif // DEBUG #endregion Public Methods //------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ #region Internal Methods // Returns a shallow copy of this node. // Returns null if this node has a zero symbol count -- // a clone would have no references, so there's no point // in allocating one. internal override TextTreeNode Clone() { TextTreeTextNode clone; clone = null; if (_symbolCount > 0) { clone = new TextTreeTextNode(); clone._symbolCount = _symbolCount; } return clone; } // Returns the TextPointerContext of the node. internal override TextPointerContext GetPointerContext(LogicalDirection direction) { return TextPointerContext.Text; } // Increments a count of the number of TextPositions and TextNavigators // referencing this node. Called when positions are created or moved. // Returns the actual node referenced -- a new node will be created if // there are already references to this node's other edge. internal override TextTreeNode IncrementReferenceCount(ElementEdge edge, int delta) { TextTreeTextNode node; TextTreeTextNode mergeNode; Invariant.Assert(delta >= 0); Invariant.Assert(edge == ElementEdge.BeforeStart || edge == ElementEdge.AfterEnd, "Bad edge ref to TextTreeTextNode!"); if (delta == 0) { return this; } if (_positionRefCount > 0 && edge != _referencedEdge) { // We need to split off a node to cover the new edge. node = Split(edge == ElementEdge.BeforeStart ? 0 : _symbolCount, edge); node._referencedEdge = edge; node._positionRefCount += delta; // It's possible we need to merge a neighbor node. // This happens when someone calls TextContainer.GetNodeAndEdgeAtOffset, // which splits a text node into two non-empty nodes. We can't merge // immediately, because we don't know which of the two nodes will // get an additional ref. // If the unreferenced node of the pair gets the new reference, // there no possibility for a merge. Otherwise, we have to split // again on the already referenced node and end up here. if (edge == ElementEdge.BeforeStart) { // If node B has no references it can merge with node A. //mergeNode = node.GetPreviousNode() as TextTreeTextNode; } else { // If node A has no references it can merge with node B. // mergeNode = node.GetNextNode() as TextTreeTextNode; } if (mergeNode != null && mergeNode._positionRefCount == 0) { mergeNode.Merge(); } } else { node = this; _referencedEdge = edge; _positionRefCount += delta; } return node; } // Decrements a count of the number of TextPositions and TextNavigators // referencing this node. // This method attempts to merge adjacent TextTreeTextNodes when the ref count // transitions from 1 to 0. // // Be careful! This can modify the tree, removing // TextTreeTextNodes. internal override void DecrementReferenceCount(ElementEdge edge) { Invariant.Assert(edge == _referencedEdge, "Bad edge decrement!"); _positionRefCount--; Invariant.Assert(_positionRefCount >= 0, "Bogus PositionRefCount! "); // If the ref count drops to zero, we may be able to merge this node with an adjacent one. if (_positionRefCount == 0) { Merge(); } } // Splits this node into two adjacent nodes. // Returns the node which contains the original requested edge // (e.g., if edge == ElementEdge.BeforeStart, this method returns the // preceding node, if edge == ElementEdge.AfterEnd, it returns the // following node). internal TextTreeTextNode Split(int localOffset, ElementEdge edge) { TextTreeTextNode newNode; TextTreeTextNode edgeNode; ElementEdge newNodeEdge; Invariant.Assert(_symbolCount > 0, "Splitting a zero-width TextNode!"); Invariant.Assert(localOffset >= 0 && localOffset <= _symbolCount, "Bad localOffset!"); Invariant.Assert(edge == ElementEdge.BeforeStart || edge == ElementEdge.AfterEnd, "Bad edge parameter!"); #if DEBUG if (localOffset == 0) { TextTreeNode previousNode; Invariant.Assert(edge == ElementEdge.BeforeStart, "Unexpected edge!"); Invariant.Assert(edge != _referencedEdge, "Splitting at referenced edge!"); previousNode = (TextTreeNode)GetPreviousNode(); Invariant.Assert(previousNode == null || previousNode.SymbolCount > 0 || previousNode.AfterEndReferenceCount, "Found preceding zero-width text node inside Split!"); } else if (localOffset == _symbolCount) { TextTreeNode nextNode; Invariant.Assert(edge == ElementEdge.AfterEnd, "Unexpected edge!"); Invariant.Assert(edge != _referencedEdge, "Splitting at referenced edge!"); nextNode = (TextTreeNode)GetNextNode(); Invariant.Assert(nextNode == null || nextNode.SymbolCount > 0 || nextNode.BeforeStartReferenceCount, "Found following zero-width text node inside Split! (2)"); } #endif // DEBUG newNode = new TextTreeTextNode(); newNode._generation = _generation; // Splay this node to the root so we don't corrupt any LeftSymbolCounts // of ancestor nodes when we fixup _symbolCount below. Splay(); if (_positionRefCount > 0 && _referencedEdge == ElementEdge.BeforeStart) { // New node is the following node. newNode._symbolOffsetCache = (_symbolOffsetCache == -1) ? -1 : _symbolOffsetCache + localOffset; newNode._symbolCount = _symbolCount - localOffset; _symbolCount = localOffset; newNodeEdge = ElementEdge.AfterEnd; edgeNode = (edge == ElementEdge.BeforeStart) ? this : newNode; } else { // New node is the preceding node. newNode._symbolOffsetCache = _symbolOffsetCache; newNode._symbolCount = localOffset; _symbolOffsetCache = (_symbolOffsetCache == -1) ? -1 : _symbolOffsetCache + localOffset; _symbolCount -= localOffset; newNodeEdge = ElementEdge.BeforeStart; edgeNode = (edge == ElementEdge.BeforeStart) ? newNode : this; } Invariant.Assert(_symbolCount >= 0); Invariant.Assert(newNode._symbolCount >= 0); newNode.InsertAtNode(this, newNodeEdge); return edgeNode; } #endregion Internal methods //----------------------------------------------------- // // Internal Properties // //------------------------------------------------------ #region Internal Properties // If this node is a local root, then ParentNode contains it. // Otherwise, this is the node parenting this node within its tree. internal override SplayTreeNode ParentNode { get { return _parentNode; } set { _parentNode = (TextTreeNode)value; } } // TextTreeTextNode never has contained nodes. internal override SplayTreeNode ContainedNode { get { return null; } set { Invariant.Assert(false, "Can't set child on a TextTreeTextNode!"); } } // Count of symbols of all siblings preceding this node. internal override int LeftSymbolCount { get { return _leftSymbolCount; } set { _leftSymbolCount = value; } } // Count of chars of all siblings preceding this node. internal override int LeftCharCount { get { return _leftCharCount; } set { _leftCharCount = value; } } // Left child node in a sibling tree. internal override SplayTreeNode LeftChildNode { get { return _leftChildNode; } set { _leftChildNode = (TextTreeNode)value; } } // Right child node in a sibling tree. internal override SplayTreeNode RightChildNode { get { return _rightChildNode; } set { _rightChildNode = (TextTreeNode)value; } } // The TextContainer's generation when SymbolOffsetCache was last updated. // If the current generation doesn't match TextContainer.Generation, then // SymbolOffsetCache is invalid. internal override uint Generation { get { return _generation; } set { _generation = value; } } // Cached symbol offset. internal override int SymbolOffsetCache { get { return _symbolOffsetCache; } set { _symbolOffsetCache = value; } } // Count of symbols covered by this node. internal override int SymbolCount { get { return _symbolCount; } set { _symbolCount = value; } } // Count of chars covered by this node. internal override int IMECharCount { get { return this.SymbolCount; } set { // Tracked redundently by _symbolCount. } } // Count of TextPositions referencing the node's BeforeStart edge. internal override bool BeforeStartReferenceCount { get { return _referencedEdge == ElementEdge.BeforeStart ? _positionRefCount > 0 : false; } set { Invariant.Assert(false, "Can't set TextTreeTextNode ref counts directly!"); } } // Count of TextPositions referencing the node's AfterStart edge. // Since text nodes don't have an AfterStart edge, this is always zero. internal override bool AfterStartReferenceCount { get { return false; } set { Invariant.Assert(false, "Text nodes don't have an AfterStart edge!"); } } // Count of TextPositions referencing the node's BeforeEnd edge. // Since text nodes don't have an BeforeEnd edge, this is always zero. internal override bool BeforeEndReferenceCount { get { return false; } set { Invariant.Assert(false, "Text nodes don't have a BeforeEnd edge!"); } } // Count of TextPositions referencing the node's AfterEnd edge. internal override bool AfterEndReferenceCount { get { return _referencedEdge == ElementEdge.AfterEnd ? _positionRefCount > 0 : false; } set { Invariant.Assert(false, "Can't set TextTreeTextNode ref counts directly!"); } } #endregion Internal Properties //----------------------------------------------------- // // Private Methods // //----------------------------------------------------- #region Private Methods // Attempts to merge this node with adjacent TextTreeTextNodes. // Called when the position ref counts drops from 1 to 0. private void Merge() { TextTreeTextNode previousNode; TextTreeTextNode nextNode; Invariant.Assert(_positionRefCount == 0, "Inappropriate Merge call!"); // Check the previous node. previousNode = GetPreviousNode() as TextTreeTextNode; if (previousNode != null && (previousNode._positionRefCount == 0 || previousNode._referencedEdge == ElementEdge.BeforeStart)) { // The previous node must take the place of this one, since previous // may still have references. Remove(); // null _parentNode out so that if there's a bug and someone still references this node we'll hear about it. _parentNode = null; previousNode.Splay(); previousNode._symbolCount += _symbolCount; } else { previousNode = this; } // Check the following node. nextNode = previousNode.GetNextNode() as TextTreeTextNode; if (nextNode != null) { if (previousNode._positionRefCount == 0 && (nextNode._positionRefCount == 0 || (nextNode._referencedEdge == ElementEdge.AfterEnd))) { // nextNode must take the place of previousNode, since nextNode // may still have references. previousNode.Remove(); // null _parentNode out so that if there's a bug and someone still references this node we'll hear about it. previousNode._parentNode = null; nextNode.Splay(); if (nextNode._symbolOffsetCache != -1) { nextNode._symbolOffsetCache -= previousNode._symbolCount; } nextNode._symbolCount += previousNode._symbolCount; } else if ((previousNode._positionRefCount == 0 || previousNode._referencedEdge == ElementEdge.BeforeStart) && nextNode._positionRefCount == 0) { // The previous node must take the place of next one, since previousNode // may still have references. nextNode.Remove(); // null _parentNode out so that if there's a bug and someone still references this node we'll hear about it. nextNode._parentNode = null; previousNode.Splay(); previousNode._symbolCount += nextNode._symbolCount; } } } #endregion Private methods //----------------------------------------------------- // // Private Fields // //------------------------------------------------------ #region Private Fields // Count of symbols of all siblings preceding this node. private int _leftSymbolCount; // Count of chars of all siblings preceding this node. private int _leftCharCount; // If this node is a local root, then ParentNode contains it. // Otherwise, this is the node parenting this node within its tree. private TextTreeNode _parentNode; // Left child node in a sibling tree. private TextTreeNode _leftChildNode; // Right child node in a sibling tree. private TextTreeNode _rightChildNode; // // The TextContainer's generation when SymbolOffsetCache was last updated. // If the current generation doesn't match TextContainer.Generation, then // SymbolOffsetCache is invalid. private uint _generation; // Cached symbol offset. private int _symbolOffsetCache; // Count of symbols/chars covered by this node. private int _symbolCount; // The number of TextPositions referencing an edge of this node. // If _positionRefCount is zero, it's safe to merge with surrouding nodes. // private int _positionRefCount; // The edge referenced by one or more TextPositions. // Only valid when _positionRefCount > 0. private ElementEdge _referencedEdge; #endregion Private Fields } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- SslSecurityTokenParameters.cs
- TheQuery.cs
- VectorAnimation.cs
- EntityUtil.cs
- OperationCanceledException.cs
- AccessDataSource.cs
- DataException.cs
- SizeConverter.cs
- XmlSchemaCollection.cs
- SecureUICommand.cs
- XPathParser.cs
- OracleConnectionFactory.cs
- DeviceContext2.cs
- ExpandableObjectConverter.cs
- SafeThemeHandle.cs
- BlobPersonalizationState.cs
- CacheAxisQuery.cs
- MediaContextNotificationWindow.cs
- FlatButtonAppearance.cs
- FlowDocumentPaginator.cs
- securitymgrsite.cs
- DBPropSet.cs
- ConstraintConverter.cs
- DBPropSet.cs
- FilterableAttribute.cs
- CompilerError.cs
- DiagnosticSection.cs
- RemoveStoryboard.cs
- SqlParameterCollection.cs
- CodeNamespaceCollection.cs
- FieldNameLookup.cs
- NavigationProperty.cs
- MultipleCopiesCollection.cs
- TypeElement.cs
- XsltFunctions.cs
- ISFTagAndGuidCache.cs
- SoapRpcMethodAttribute.cs
- CodeTypeDelegate.cs
- EventLogHandle.cs
- ResourceReader.cs
- XmlWhitespace.cs
- PackageDigitalSignature.cs
- Pair.cs
- FamilyMap.cs
- ExclusiveCanonicalizationTransform.cs
- ControlValuePropertyAttribute.cs
- TextCharacters.cs
- ExtensibleClassFactory.cs
- Double.cs
- FileLoadException.cs
- SerializationAttributes.cs
- PropertyIdentifier.cs
- SchemaTableOptionalColumn.cs
- CustomCategoryAttribute.cs
- SspiHelper.cs
- GridViewRow.cs
- EdmProperty.cs
- Parameter.cs
- BaseServiceProvider.cs
- WmlCommandAdapter.cs
- XmlSchemas.cs
- WorkflowPersistenceContext.cs
- CqlBlock.cs
- InstanceKeyNotReadyException.cs
- NativeCompoundFileAPIs.cs
- JoinTreeNode.cs
- UnauthorizedAccessException.cs
- PanelDesigner.cs
- SelectionUIHandler.cs
- GlobalAclOperationRequirement.cs
- TypeHelper.cs
- AxParameterData.cs
- DependencyPropertyKey.cs
- ManagedFilter.cs
- PositiveTimeSpanValidatorAttribute.cs
- RequiredAttributeAttribute.cs
- KeyFrames.cs
- BrushConverter.cs
- ViewPort3D.cs
- _HeaderInfoTable.cs
- BackStopAuthenticationModule.cs
- TempFiles.cs
- MatrixIndependentAnimationStorage.cs
- EventMappingSettingsCollection.cs
- WpfWebRequestHelper.cs
- DragDeltaEventArgs.cs
- RtfToXamlLexer.cs
- dbenumerator.cs
- PropertySourceInfo.cs
- SpecularMaterial.cs
- TextRangeSerialization.cs
- MessageFormatterConverter.cs
- TextProperties.cs
- GridEntry.cs
- XsltQilFactory.cs
- BinaryUtilClasses.cs
- HtmlFormWrapper.cs
- StrokeNodeEnumerator.cs
- ContainerFilterService.cs
- ServicePointManagerElement.cs