Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / 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
- ItemCollection.cs
- ManagedIStream.cs
- XPathScanner.cs
- IsolatedStorageFile.cs
- PageThemeParser.cs
- EnterpriseServicesHelper.cs
- DashStyle.cs
- RuntimeConfig.cs
- ReflectionTypeLoadException.cs
- RepeaterItemEventArgs.cs
- TextElementEnumerator.cs
- Point3DIndependentAnimationStorage.cs
- ClockController.cs
- RelationshipSet.cs
- FigureParagraph.cs
- Enum.cs
- SetIterators.cs
- IdentitySection.cs
- BamlRecords.cs
- Object.cs
- ChildrenQuery.cs
- FontSource.cs
- TextureBrush.cs
- PartialTrustVisibleAssembliesSection.cs
- DataGridViewTextBoxCell.cs
- Command.cs
- FrameworkElementFactory.cs
- BuildProvider.cs
- SecurityManager.cs
- RelationshipWrapper.cs
- ToolStripButton.cs
- FullTrustAssembly.cs
- WpfSharedBamlSchemaContext.cs
- ThreadAbortException.cs
- DesignerLoader.cs
- _PooledStream.cs
- FillErrorEventArgs.cs
- FtpRequestCacheValidator.cs
- EditorBrowsableAttribute.cs
- EntityTypeBase.cs
- PngBitmapEncoder.cs
- HtmlInputRadioButton.cs
- BeginSelectCardRequest.cs
- DataBindingHandlerAttribute.cs
- OleDbCommand.cs
- ReferenceConverter.cs
- ListControlDataBindingHandler.cs
- CodeObject.cs
- SocketAddress.cs
- SoapMessage.cs
- WebExceptionStatus.cs
- EntityDataSourceSelectingEventArgs.cs
- TableRowCollection.cs
- EmbeddedMailObject.cs
- PersonalizationAdministration.cs
- PerformanceCounterScope.cs
- SettingsSavedEventArgs.cs
- OciLobLocator.cs
- _DomainName.cs
- ErasingStroke.cs
- EventLogLink.cs
- ListenerTraceUtility.cs
- DependencyObjectValidator.cs
- SchemaNotation.cs
- WebAdminConfigurationHelper.cs
- DocumentGridContextMenu.cs
- EdmError.cs
- WebHeaderCollection.cs
- ArglessEventHandlerProxy.cs
- HttpBrowserCapabilitiesBase.cs
- DesignTimeTemplateParser.cs
- UIElement3D.cs
- DetailsViewRowCollection.cs
- DispatcherHookEventArgs.cs
- ServiceXNameTypeConverter.cs
- HtmlTable.cs
- PropertyKey.cs
- RedirectionProxy.cs
- OperatingSystem.cs
- CharacterBuffer.cs
- ApplicationInfo.cs
- Ref.cs
- __ComObject.cs
- CFStream.cs
- BitArray.cs
- PersonalizationProviderHelper.cs
- FileUtil.cs
- TextEditorDragDrop.cs
- ReversePositionQuery.cs
- WeakReferenceEnumerator.cs
- TypeDescriptionProvider.cs
- EdgeProfileValidation.cs
- ZoneLinkButton.cs
- ResourceSet.cs
- SessionConnectionReader.cs
- UserMapPath.cs
- String.cs
- CodeTypeMemberCollection.cs
- Assembly.cs
- LogLogRecordEnumerator.cs