// Constructor.
		public TextTree(TextBuffer buffer, TextLayout layout)
				{
					// set the buffer for this text tree
					this.buffer = buffer;

					// set the layout for this text tree
					this.layout = layout;

					// set the root for this text tree
					root = new TextGroup();

					// insert a new line into the buffer
					buffer.Insert(0, '\n');

					// create the first line
					TextLine line = new TextLine
						(buffer.MarkPosition(0, true),
						 buffer.MarkPosition(1, true));

					// insert the first line into the tree
					root.InsertChild(null, line);

					// update the metrics information
					root.UpdateMetrics(layout, true);

					// create the caret position
					caret = buffer.MarkPosition(0, false);

					// create the selection position
					selection = buffer.MarkPosition(0, false);
				}
			// Rebalance the tree at this node.
			public override void Rebalance(TextTree tree)
					{
						// get this node
						TextGroup node = this;

						// rebalance up the tree
						while(node != null)
						{
							// enforce upper bound on child count
							while(node.childCount > MAX_CHILD_COUNT)
							{
								// create a new root before splitting current root
								if(node.parent == null)
								{
									// create the new root node
									TextGroup root = new TextGroup();

									// set the new root's level
									root.level = (node.level + 1);

									// insert the old root under the new root
									root.InsertChild(null, node);

									// set the root of the tree to the new root
									tree.root = root;
								}

								// create the new group for the excess children
								TextGroup group = new TextGroup();

								// set the new group's level
								group.level = node.level;

								// get the first child of the node to be split
								TextNode child = node.first;

								// find the first excess child
								for(int i = 1; i < MIN_CHILD_COUNT; ++i)
								{
									child = child.next;
								}

								// insert first excess child under the new group
								group.InsertChildren(null, child.next);

								// insert group under the current node's parent
								node.parent.InsertChild(node, group);

								// set the current node to the new group
								node = group;
							}

							// enforce lower bound on child count
							while(node.childCount < MIN_CHILD_COUNT)
							{
								// handle the root node case
								if(node.parent == null)
								{
									// root needs at least two children or one line
									if((node.childCount == 1) && (node.level > 1))
									{
										// set the root to its only child
										tree.root = (TextGroup)node.first;

										// remove new root from the old root
										node.RemoveChild(tree.root);
									}

									// we're done rebalancing
									return;
								}

								// rebalance the parent, if too few siblings
								if(node.parent.ChildCount < 2)
								{
									// rebalance the parent
									node.parent.Rebalance(tree);

									// try the current node again
									continue;
								}

								// get the next sibling of the current node
								TextGroup next = (TextGroup)node.next;

								// use previous and swap, if no next sibling
								if(next == null)
								{
									// set the next node to the current node
									next = node;

									// reset current node to previous sibling
									node = (TextGroup)node.prev;
								}

								// calculate the total child count for the nodes
								int fullCount = node.childCount + next.childCount;

								// merge the nodes or split up the children
								if(fullCount <= MAX_CHILD_COUNT)
								{
									// merge the children under a single node
									node.InsertChildren(node.last, next.first);

									// remove the empty node from the tree
									node.parent.RemoveChild(next);

									// continue rebalancing at this node, if needed
									if(fullCount < MIN_CHILD_COUNT) { continue; }
								}
								else
								{
									// calculate the first node's new child count
									int halfCount = (fullCount / 2);

									// move children around as needed
									if(node.childCount < halfCount)
									{
										// move the needed children to the first node
										node.InsertChildren
											(node.last, next.first,
											 (halfCount - node.childCount));
									}
									else if(node.childCount > halfCount)
									{
										// get the first child of the first node
										TextNode child = node.first;

										// get the first of the children to move
										for(int i = 1; i < halfCount; ++i)
										{
											child = child.next;
										}

										// move extra children to the second node
										next.InsertChildren(null, child);
									}
								}
							}

							// set the current node to its parent
							node = (TextGroup)node.parent;
						}
					}