//------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ #region Internal Methods // Inserts text into the text block array. The text is either a string // or an array of char. internal static void InsertText(TextTreeRootTextBlock rootTextBlock, int offset, object text) { TextTreeTextBlock block; int localOffset; int insertCount; int textLength; Invariant.Assert(text is string || text is char[], "Bad text parameter!"); // Get the block matching the insertion point. block = FindBlock(rootTextBlock, offset, out localOffset); // Fill this block to capacity. textLength = TextContainer.GetTextLength(text); insertCount = block.InsertText(localOffset, text, 0, textLength); if (insertCount < textLength) { // Put all the text to the smaller side of the gap into the new block. if (block.GapOffset < TextTreeTextBlock.MaxBlockSize / 2) { InsertTextLeft(block, text, insertCount); } else { InsertTextRight(block, text, insertCount); } } }
// Token: 0x06003DA8 RID: 15784 RVA: 0x0011C590 File Offset: 0x0011A790 internal static char[] CutText(TextTreeRootTextBlock rootTextBlock, int offset, int count) { char[] array = new char[count]; TextTreeText.ReadText(rootTextBlock, offset, count, array, 0); TextTreeText.RemoveText(rootTextBlock, offset, count); return(array); }
// Read text in the block array. internal static void ReadText(TextTreeRootTextBlock rootTextBlock, int offset, int count, char[] chars, int startIndex) { TextTreeTextBlock block; int localOffset; int blockCount; if (count > 0) { // Get the block matching the offset. block = FindBlock(rootTextBlock, offset, out localOffset); while (true) { Invariant.Assert(block != null, "Caller asked for too much text!"); blockCount = block.ReadText(localOffset, count, chars, startIndex); localOffset = 0; count -= blockCount; if (count == 0) { break; } startIndex += blockCount; block = (TextTreeTextBlock)block.GetNextNode(); } } }
// Token: 0x06003DAB RID: 15787 RVA: 0x0011C61F File Offset: 0x0011A81F internal static void InsertElementEdges(TextTreeRootTextBlock rootTextBlock, int offset, int childSymbolCount) { if (childSymbolCount == 0) { TextTreeText.InsertText(rootTextBlock, offset, new string('뻯', 2)); return; } TextTreeText.InsertText(rootTextBlock, offset, new string('뻯', 1)); TextTreeText.InsertText(rootTextBlock, offset + childSymbolCount + 1, new string('\0', 1)); }
// Remove text from the block array, and return the removed text in a // char array. internal static char[] CutText(TextTreeRootTextBlock rootTextBlock, int offset, int count) { char[] text; text = new char[count]; ReadText(rootTextBlock, offset, count, text, 0); RemoveText(rootTextBlock, offset, count); return(text); }
// Token: 0x06003DAC RID: 15788 RVA: 0x0011C65B File Offset: 0x0011A85B internal static void RemoveElementEdges(TextTreeRootTextBlock rootTextBlock, int offset, int symbolCount) { Invariant.Assert(symbolCount >= 2, "Element must span at least two symbols!"); if (symbolCount == 2) { TextTreeText.RemoveText(rootTextBlock, offset, 2); return; } TextTreeText.RemoveText(rootTextBlock, offset + symbolCount - 1, 1); TextTreeText.RemoveText(rootTextBlock, offset, 1); }
// Insert placeholders for elements edges into the block array. // The actual value stored doesn't really matter, it will never be read. internal static void InsertElementEdges(TextTreeRootTextBlock rootTextBlock, int offset, int childSymbolCount) { if (childSymbolCount == 0) { InsertText(rootTextBlock, offset, new string((char)0xbeef, 2)); } else { InsertText(rootTextBlock, offset, new string((char)0xbeef, 1)); InsertText(rootTextBlock, offset + childSymbolCount + 1, new string((char)0x0, 1)); } }
// Token: 0x06003DA7 RID: 15783 RVA: 0x0011C4CC File Offset: 0x0011A6CC internal static void RemoveText(TextTreeRootTextBlock rootTextBlock, int offset, int count) { if (count == 0) { return; } int num; TextTreeTextBlock textTreeTextBlock = TextTreeText.FindBlock(rootTextBlock, offset, out num); if (textTreeTextBlock.Count == num) { textTreeTextBlock = (TextTreeTextBlock)textTreeTextBlock.GetNextNode(); Invariant.Assert(textTreeTextBlock != null); num = 0; } int num2; TextTreeTextBlock textTreeTextBlock2 = TextTreeText.FindBlock(rootTextBlock, offset + count, out num2); int num3; SplayTreeNode splayTreeNode; if (num > 0 || count < textTreeTextBlock.Count) { num3 = Math.Min(count, textTreeTextBlock.Count - num); textTreeTextBlock.RemoveText(num, num3); splayTreeNode = textTreeTextBlock.GetNextNode(); } else { num3 = 0; splayTreeNode = textTreeTextBlock; } if (count > num3) { int num4; SplayTreeNode splayTreeNode2; if (num2 < textTreeTextBlock2.Count) { num4 = num2; textTreeTextBlock2.RemoveText(0, num2); splayTreeNode2 = textTreeTextBlock2.GetPreviousNode(); } else { num4 = 0; splayTreeNode2 = textTreeTextBlock2; } if (num3 + num4 < count) { TextTreeText.Remove((TextTreeTextBlock)splayTreeNode, (TextTreeTextBlock)splayTreeNode2); } } }
// Remove placeholder element edge characters from the block array. internal static void RemoveElementEdges(TextTreeRootTextBlock rootTextBlock, int offset, int symbolCount) { Invariant.Assert(symbolCount >= 2, "Element must span at least two symbols!"); // 2 element edges == 2 symbols. if (symbolCount == 2) { RemoveText(rootTextBlock, offset, 2); } else { RemoveText(rootTextBlock, offset + symbolCount - 1, 1); RemoveText(rootTextBlock, offset, 1); } }
// Token: 0x06003DA6 RID: 15782 RVA: 0x0011C460 File Offset: 0x0011A660 internal static void InsertText(TextTreeRootTextBlock rootTextBlock, int offset, object text) { Invariant.Assert(text is string || text is char[], "Bad text parameter!"); int logicalOffset; TextTreeTextBlock textTreeTextBlock = TextTreeText.FindBlock(rootTextBlock, offset, out logicalOffset); int textLength = TextContainer.GetTextLength(text); int num = textTreeTextBlock.InsertText(logicalOffset, text, 0, textLength); if (num < textLength) { if (textTreeTextBlock.GapOffset < 2048) { TextTreeText.InsertTextLeft(textTreeTextBlock, text, num); return; } TextTreeText.InsertTextRight(textTreeTextBlock, text, num); } }
// Token: 0x06003DAD RID: 15789 RVA: 0x0011C690 File Offset: 0x0011A890 private static TextTreeTextBlock FindBlock(TextTreeRootTextBlock rootTextBlock, int offset, out int localOffset) { int num; TextTreeTextBlock textTreeTextBlock = (TextTreeTextBlock)rootTextBlock.ContainedNode.GetSiblingAtOffset(offset, out num); if (textTreeTextBlock.LeftSymbolCount == offset) { TextTreeTextBlock textTreeTextBlock2 = (TextTreeTextBlock)textTreeTextBlock.GetPreviousNode(); if (textTreeTextBlock2 != null) { textTreeTextBlock = textTreeTextBlock2; num -= textTreeTextBlock.SymbolCount; Invariant.Assert(num >= 0); } } localOffset = offset - num; Invariant.Assert(localOffset >= 0 && localOffset <= textTreeTextBlock.Count); return(textTreeTextBlock); }
// Token: 0x06003DA9 RID: 15785 RVA: 0x0011C5B8 File Offset: 0x0011A7B8 internal static void ReadText(TextTreeRootTextBlock rootTextBlock, int offset, int count, char[] chars, int startIndex) { if (count > 0) { int logicalOffset; TextTreeTextBlock textTreeTextBlock = TextTreeText.FindBlock(rootTextBlock, offset, out logicalOffset); for (;;) { Invariant.Assert(textTreeTextBlock != null, "Caller asked for too much text!"); int num = textTreeTextBlock.ReadText(logicalOffset, count, chars, startIndex); logicalOffset = 0; count -= num; if (count == 0) { break; } startIndex += num; textTreeTextBlock = (TextTreeTextBlock)textTreeTextBlock.GetNextNode(); } } }
//------------------------------------------------------ // // Private Methods // //------------------------------------------------------ #region Private Methods // Finds the TextTreeTextBlock that contains the specified char offset. // Returns the lower block for offsets that border two blocks. private static TextTreeTextBlock FindBlock(TextTreeRootTextBlock rootTextBlock, int offset, out int localOffset) { TextTreeTextBlock node; int nodeOffset; node = (TextTreeTextBlock)rootTextBlock.ContainedNode.GetSiblingAtOffset(offset, out nodeOffset); // If offset is between two blocks, make sure we return the lower of the two. if (node.LeftSymbolCount == offset) { TextTreeTextBlock previousBlock = (TextTreeTextBlock)node.GetPreviousNode(); if (previousBlock != null) { node = previousBlock; nodeOffset -= node.SymbolCount; Invariant.Assert(nodeOffset >= 0); } } localOffset = offset - nodeOffset; Invariant.Assert(localOffset >= 0 && localOffset <= node.Count); return(node); }
// Inserts a placeholder character for an embedded object. // The actual value stored doesn't really matter, it will never be read. internal static void InsertObject(TextTreeRootTextBlock rootTextBlock, int offset) { InsertText(rootTextBlock, offset, new string((char)0xffff, 1)); }
// Remove text from the block array, and return the removed text in a // char array. internal static char[] CutText(TextTreeRootTextBlock rootTextBlock, int offset, int count) { char[] text; text = new char[count]; ReadText(rootTextBlock, offset, count, text, 0); RemoveText(rootTextBlock, offset, count); return text; }
// Read text in the block array. internal static void ReadText(TextTreeRootTextBlock rootTextBlock, int offset, int count, char[] chars, int startIndex) { TextTreeTextBlock block; int localOffset; int blockCount; if (count > 0) { // Get the block matching the offset. block = FindBlock(rootTextBlock, offset, out localOffset); while (true) { Invariant.Assert(block != null, "Caller asked for too much text!"); blockCount = block.ReadText(localOffset, count, chars, startIndex); localOffset = 0; count -= blockCount; if (count == 0) break; startIndex += blockCount; block = (TextTreeTextBlock)block.GetNextNode(); } } }
// Removes text from the block array. // internal static void RemoveText(TextTreeRootTextBlock rootTextBlock, int offset, int count) { int firstBlockLocalOffset; TextTreeTextBlock firstBlock; int lastBlockLocalOffset; TextTreeTextBlock lastBlock; SplayTreeNode firstRemoveBlock; SplayTreeNode lastRemoveBlock; int firstCount; if (count == 0) { // Early out on count == 0 so we don't get in trouble at the // very end of the array. return; } // Get the block matching the offset. firstBlock = FindBlock(rootTextBlock, offset, out firstBlockLocalOffset); if (firstBlock.Count == firstBlockLocalOffset) { // FindIndexForOffset always returns the lower block if we ask // for a cp between two blocks. // For a remove, we want to work with the following block, which // actually contains the content. firstBlock = (TextTreeTextBlock)firstBlock.GetNextNode(); Invariant.Assert(firstBlock != null); firstBlockLocalOffset = 0; } // And the block matching the offset + count. lastBlock = FindBlock(rootTextBlock, offset + count, out lastBlockLocalOffset); if (firstBlockLocalOffset > 0 || count < firstBlock.Count) { // Remove text from the first block. firstCount = Math.Min(count, firstBlock.Count - firstBlockLocalOffset); firstBlock.RemoveText(firstBlockLocalOffset, firstCount); // Don't remove the first block, since some text was left behind. firstRemoveBlock = firstBlock.GetNextNode(); } else { // All text in the first block covered -- just remove it entirely. firstCount = 0; firstRemoveBlock = firstBlock; } if (count > firstCount) { int lastCount; if (lastBlockLocalOffset < lastBlock.Count) { lastCount = lastBlockLocalOffset; // Remove some text. lastBlock.RemoveText(0, lastBlockLocalOffset); // There's text left over in the last block, so don't remove // the block. lastRemoveBlock = lastBlock.GetPreviousNode(); } else { lastCount = 0; // All text in the last block covered -- just remove it entirely. lastRemoveBlock = lastBlock; } // If firstRemoveBlock == lastBlock && lastRemoveBlock == firstBlock, // then there are no more blocks to remove -- we removed a portion // from the first and last block and they are direct neighbors. if (firstCount + lastCount < count) { // Remove any blocks in the middle of first, last. Remove((TextTreeTextBlock)firstRemoveBlock, (TextTreeTextBlock)lastRemoveBlock); } } }
//------------------------------------------------------ // // Private Methods // //------------------------------------------------------ #region Private Methods // Finds the TextTreeTextBlock that contains the specified char offset. // Returns the lower block for offsets that border two blocks. private static TextTreeTextBlock FindBlock(TextTreeRootTextBlock rootTextBlock, int offset, out int localOffset) { TextTreeTextBlock node; int nodeOffset; node = (TextTreeTextBlock)rootTextBlock.ContainedNode.GetSiblingAtOffset(offset, out nodeOffset); // If offset is between two blocks, make sure we return the lower of the two. if (node.LeftSymbolCount == offset) { TextTreeTextBlock previousBlock = (TextTreeTextBlock)node.GetPreviousNode(); if (previousBlock != null) { node = previousBlock; nodeOffset -= node.SymbolCount; Invariant.Assert(nodeOffset >= 0); } } localOffset = offset - nodeOffset; Invariant.Assert(localOffset >= 0 && localOffset <= node.Count); return node; }
// Removes text from the block array. // consider merging blocks after the remove. Not yet clear if // this is desirable. internal static void RemoveText(TextTreeRootTextBlock rootTextBlock, int offset, int count) { int firstBlockLocalOffset; TextTreeTextBlock firstBlock; int lastBlockLocalOffset; TextTreeTextBlock lastBlock; SplayTreeNode firstRemoveBlock; SplayTreeNode lastRemoveBlock; int firstCount; if (count == 0) { // Early out on count == 0 so we don't get in trouble at the // very end of the array. return; } // Get the block matching the offset. firstBlock = FindBlock(rootTextBlock, offset, out firstBlockLocalOffset); if (firstBlock.Count == firstBlockLocalOffset) { // FindIndexForOffset always returns the lower block if we ask // for a cp between two blocks. // For a remove, we want to work with the following block, which // actually contains the content. firstBlock = (TextTreeTextBlock)firstBlock.GetNextNode(); Invariant.Assert(firstBlock != null); firstBlockLocalOffset = 0; } // And the block matching the offset + count. lastBlock = FindBlock(rootTextBlock, offset + count, out lastBlockLocalOffset); if (firstBlockLocalOffset > 0 || count < firstBlock.Count) { // Remove text from the first block. firstCount = Math.Min(count, firstBlock.Count - firstBlockLocalOffset); firstBlock.RemoveText(firstBlockLocalOffset, firstCount); // Don't remove the first block, since some text was left behind. firstRemoveBlock = firstBlock.GetNextNode(); } else { // All text in the first block covered -- just remove it entirely. firstCount = 0; firstRemoveBlock = firstBlock; } if (count > firstCount) { int lastCount; if (lastBlockLocalOffset < lastBlock.Count) { lastCount = lastBlockLocalOffset; // Remove some text. lastBlock.RemoveText(0, lastBlockLocalOffset); // There's text left over in the last block, so don't remove // the block. lastRemoveBlock = lastBlock.GetPreviousNode(); } else { lastCount = 0; // All text in the last block covered -- just remove it entirely. lastRemoveBlock = lastBlock; } // If firstRemoveBlock == lastBlock && lastRemoveBlock == firstBlock, // then there are no more blocks to remove -- we removed a portion // from the first and last block and they are direct neighbors. if (firstCount + lastCount < count) { // Remove any blocks in the middle of first, last. Remove((TextTreeTextBlock)firstRemoveBlock, (TextTreeTextBlock)lastRemoveBlock); } } }
// Token: 0x06003DAA RID: 15786 RVA: 0x0011C60B File Offset: 0x0011A80B internal static void InsertObject(TextTreeRootTextBlock rootTextBlock, int offset) { TextTreeText.InsertText(rootTextBlock, offset, new string(char.MaxValue, 1)); }