nsresult NS_NewAutoScrollTimer(nsXULTreeOuterGroupFrame* aTree, nsDragAutoScrollTimer **aResult) ;         class nsDragOverListener : public nsIDOMDragListener { public:  nsDragOverListener ( nsXULTreeOuterGroupFrame* inTree ); virtual ~nsDragOverListener() { } ;  NS_DECL_ISUPPORTS   virtual nsresult HandleEvent(nsIDOMEvent* aEvent); virtual nsresult DragEnter(nsIDOMEvent* aDragEvent); virtual nsresult DragOver(nsIDOMEvent* aDragEvent); virtual nsresult DragExit(nsIDOMEvent* aDragEvent); virtual nsresult DragDrop(nsIDOMEvent* aDragEvent); virtual nsresult DragGesture(nsIDOMEvent* aDragEvent);  protected:  nsXULTreeOuterGroupFrame* mTree;  };   NS_IMPL_ISUPPORTS2(nsDragOverListener, nsIDOMEventListener, nsIDOMDragListener)  nsDragOverListener :: nsDragOverListener ( nsXULTreeOuterGroupFrame* inTree ) : mTree ( inTree ) { NS_INIT_REFCNT(); }           nsresult nsDragOverListener :: DragOver(nsIDOMEvent* aDragEvent) { nsCOMPtr<nsIDOMMouseEvent> mouseEvent ( do_QueryInterface(aDragEvent) ); if ( mouseEvent ) { PRInt32 x = 0, y = 0; mouseEvent->GetClientX ( &x ); mouseEvent->GetClientY ( &y ); mTree->HandleAutoScrollTracking ( nsPoint(x,y) ); } return NS_OK;  }       nsresult nsDragOverListener::HandleEvent(nsIDOMEvent* aEvent) { return NS_OK; } nsresult nsDragOverListener::DragEnter(nsIDOMEvent* aDragEvent) { return NS_OK; } nsresult nsDragOverListener::DragGesture(nsIDOMEvent* aDragEvent) { return NS_OK; } nsresult nsDragOverListener::DragExit(nsIDOMEvent* aDragEvent) { return NS_OK; } nsresult nsDragOverListener::DragDrop(nsIDOMEvent* aDragEvent) { return NS_OK; }    #ifdef XP_MAC #pragma mark - #endif        nsresult NS_NewXULTreeOuterGroupFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRBool aIsRoot, nsIBoxLayout* aLayoutManager, PRBool aIsHorizontal) { NS_PRECONDITION(aNewFrame, "null OUT ptr"); if (nsnull == aNewFrame) { return NS_ERROR_NULL_POINTER; } nsXULTreeOuterGroupFrame* it = new (aPresShell) nsXULTreeOuterGroupFrame(aPresShell, aIsRoot, aLayoutManager, aIsHorizontal); if (!it) return NS_ERROR_OUT_OF_MEMORY;  *aNewFrame = it; return NS_OK;  }    nsXULTreeOuterGroupFrame::nsXULTreeOuterGroupFrame(nsIPresShell* aPresShell, PRBool aIsRoot, nsIBoxLayout* aLayoutManager, PRBool aIsHorizontal) :nsXULTreeGroupFrame(aPresShell, aIsRoot, aLayoutManager, aIsHorizontal), mRowGroupInfo(nsnull), mRowHeight(0), mCurrentIndex(0), mTwipIndex(0), mAutoScrollTimer(nsnull), mTreeIsSorted(PR_FALSE), mDragOverListener(nsnull), mCurrentlyTrackingAutoScroll(PR_FALSE) { }    nsXULTreeOuterGroupFrame::~nsXULTreeOuterGroupFrame() { nsCOMPtr<nsIContent> content; GetContent(getter_AddRefs(content)); nsCOMPtr<nsIDOMEventReceiver> receiver(do_QueryInterface(content));   if ( receiver && mDragOverListener ) receiver->RemoveEventListener(NS_ConvertASCIItoUCS2("dragover"), mDragOverListener, PR_TRUE);  delete mRowGroupInfo;  StopAutoScrollTimer(); NS_IF_RELEASE ( mAutoScrollTimer );  }  NS_IMETHODIMP_(nsrefcnt) nsXULTreeOuterGroupFrame::AddRef(void) { return NS_OK; }  NS_IMETHODIMP_(nsrefcnt) nsXULTreeOuterGroupFrame::Release(void) { return NS_OK; }     NS_INTERFACE_MAP_BEGIN(nsXULTreeOuterGroupFrame) NS_INTERFACE_MAP_ENTRY(nsIScrollbarMediator) NS_INTERFACE_MAP_ENTRY(nsIDragTracker) NS_INTERFACE_MAP_END_INHERITING(nsXULTreeGroupFrame)        NS_IMETHODIMP nsXULTreeOuterGroupFrame::Init(nsIPresContext* aPresContext, nsIContent* aContent, nsIFrame* aParent, nsIStyleContext* aContext, nsIFrame* aPrevInFlow) { nsresult rv = nsXULTreeGroupFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);  float p2t; aPresContext->GetScaledPixelsToTwips(&p2t); mOnePixel = NSIntPixelsToTwips(1, p2t);  nsIFrame* box; aParent->GetParent(&box); if (!box) return rv;  nsCOMPtr<nsIScrollableFrame> scrollFrame(do_QueryInterface(box)); if (!scrollFrame) return rv;  nsIBox* verticalScrollbar; scrollFrame->GetScrollbarBox(PR_TRUE, &verticalScrollbar); if (!verticalScrollbar) { NS_ERROR("Unable to install the scrollbar mediator on the tree widget. You must be using GFX scrollbars."); return NS_ERROR_FAILURE; }  nsCOMPtr<nsIScrollbarFrame> scrollbarFrame(do_QueryInterface(verticalScrollbar)); scrollbarFrame->SetScrollbarMediator(this);      nsCOMPtr<nsIDOMEventReceiver> receiver(do_QueryInterface(aContent)); if ( receiver ) { mDragOverListener = new nsDragOverListener(this); receiver->AddEventListener(NS_ConvertASCIItoUCS2("dragover"), mDragOverListener, PR_FALSE); }  return rv;  }  PRBool nsXULTreeOuterGroupFrame::IsFixedRowSize() { nsCOMPtr<nsIContent> parent; mContent->GetParent(*getter_AddRefs(parent)); nsAutoString rows; parent->GetAttribute(kNameSpaceID_None, nsXULAtoms::rows, rows); if (!rows.IsEmpty()) return PR_TRUE; return PR_FALSE; }  void nsXULTreeOuterGroupFrame::SetRowHeight(nscoord aRowHeight) { if (mRowHeight == 0) { mRowHeight = aRowHeight; nsCOMPtr<nsIContent> parent; mContent->GetParent(*getter_AddRefs(parent)); nsAutoString rows; parent->GetAttribute(kNameSpaceID_None, nsXULAtoms::rows, rows); if (!rows.IsEmpty()) { PRInt32 dummy; PRInt32 count = rows.ToInteger(&dummy); float t2p; mPresContext->GetTwipsToPixels(&t2p); PRInt32 rowHeight = NSTwipsToIntPixels(aRowHeight, t2p); nsAutoString value; value.AppendInt(rowHeight*count); parent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::height, value, PR_FALSE); } nsBoxLayoutState state(mPresContext); MarkDirtyChildren(state); } }  nscoord nsXULTreeOuterGroupFrame::GetYPosition() { nsIBox* box; GetParentBox(&box); if (!box) return 0;  box->GetParentBox(&box); if (!box) return 0;  nsCOMPtr<nsIScrollableFrame> scrollFrame(do_QueryInterface(box)); if (!scrollFrame) return 0;  nscoord x, y; scrollFrame->GetScrollPosition(mPresContext, x, y); return y; }  void nsXULTreeOuterGroupFrame::VerticalScroll(PRInt32 aDelta) { nsIBox* box; GetParentBox(&box); if (!box) return;  box->GetParentBox(&box); if (!box) return;  nsCOMPtr<nsIScrollableFrame> scrollFrame(do_QueryInterface(box)); if (!scrollFrame) return;  nscoord x, y; scrollFrame->GetScrollPosition(mPresContext, x, y);  scrollFrame->ScrollTo(mPresContext, x, aDelta); }  nscoord nsXULTreeOuterGroupFrame::GetAvailableHeight() { nsIBox* box; GetParentBox(&box); if (!box) return 0;  box->GetParentBox(&box); if (!box) return 0;  nsCOMPtr<nsIScrollableFrame> scrollFrame(do_QueryInterface(box)); if (!scrollFrame) return 0;  nscoord x, y; scrollFrame->GetClipSize(mPresContext, &x, &y); return y; }  void nsXULTreeOuterGroupFrame::ComputeTotalRowCount(PRInt32& aCount, nsIContent* aParent) { if (!mRowGroupInfo) { mRowGroupInfo = new nsXULTreeRowGroupInfo(); }  PRInt32 childCount; aParent->ChildCount(childCount);  for (PRInt32 i = 0; i < childCount; i++) { nsCOMPtr<nsIContent> childContent; aParent->ChildAt(i, *getter_AddRefs(childContent)); nsCOMPtr<nsIAtom> tag; childContent->GetTag(*getter_AddRefs(tag)); if (tag.get() == nsXULAtoms::treerow) { if ((aCount%TICK_FACTOR) == 0) mRowGroupInfo->Add(childContent);  mRowGroupInfo->mLastChild = childContent;  aCount++; } else if (tag.get() == nsXULAtoms::treeitem) {  ComputeTotalRowCount(aCount, childContent); } else if (tag.get() == nsXULAtoms::treechildren) {  nsCOMPtr<nsIAtom> openAtom = dont_AddRef(NS_NewAtom("open")); nsAutoString isOpen; nsCOMPtr<nsIContent> parent; childContent->GetParent(*getter_AddRefs(parent)); parent->GetAttribute(kNameSpaceID_None, openAtom, isOpen); if (isOpen.EqualsWithConversion("true")) ComputeTotalRowCount(aCount, childContent); } } }  NS_IMETHODIMP nsXULTreeOuterGroupFrame::ScrollbarButtonPressed(PRInt32 aOldIndex, PRInt32 aNewIndex) { if (aOldIndex == aNewIndex) return NS_OK; if (aNewIndex < aOldIndex) mCurrentIndex--; else mCurrentIndex++; if (mCurrentIndex < 0) { mCurrentIndex = 0; return NS_OK; } InternalPositionChanged(aNewIndex < aOldIndex, 1); return NS_OK; }  NS_IMETHODIMP nsXULTreeOuterGroupFrame::PositionChanged(PRInt32 aOldIndex, PRInt32 aNewIndex) { if (aOldIndex == aNewIndex) return NS_OK;  PRInt32 oldTwipIndex, newTwipIndex; oldTwipIndex = (aOldIndex*mOnePixel); newTwipIndex = (aNewIndex*mOnePixel);  PRInt32 twipDelta = newTwipIndex > oldTwipIndex ? newTwipIndex - oldTwipIndex : oldTwipIndex - newTwipIndex; PRInt32 delta = twipDelta / mRowHeight; PRInt32 remainder = twipDelta % mRowHeight; if (remainder > (mRowHeight/2)) delta++;  if (delta == 0) return NS_OK;  mCurrentIndex = newTwipIndex > oldTwipIndex ? mCurrentIndex + delta : mCurrentIndex - delta;  if (mCurrentIndex < 0) { mCurrentIndex = 0; return NS_OK; }  return InternalPositionChanged(newTwipIndex < oldTwipIndex, delta); }  NS_IMETHODIMP nsXULTreeOuterGroupFrame::InternalPositionChanged(PRBool aUp, PRInt32 aDelta) { PRInt32 visibleRows = GetAvailableHeight()/mRowHeight;   if (aDelta < visibleRows) { if (mContentChain) {      nsCOMPtr<nsIPresShell> shell; mPresContext->GetShell(getter_AddRefs(shell)); shell->FlushPendingNotifications(); }  PRInt32 loseRows = aDelta;   if (!aUp) {  DestroyRows(loseRows); }  else {  nsCOMPtr<nsIContent> rowContent; GetFirstRowContent(getter_AddRefs(rowContent));   ReverseDestroyRows(loseRows);    nsCOMPtr<nsIContent> topRowContent; PRInt32 findContent = aDelta; FindPreviousRowContent(findContent, rowContent, nsnull, getter_AddRefs(topRowContent)); ConstructContentChain(topRowContent);   ConstructOldContentChain(rowContent); } } else {     nsIBox* currBox; GetChildBox(&currBox); while (currBox) { nsIBox* nextBox; currBox->GetNextBox(&nextBox); nsIFrame* frame; currBox->QueryInterface(kIFrameIID, (void**)&frame); mFrameConstructor->RemoveMappingsForFrameSubtree(mPresContext, frame, nsnull); currBox = nextBox; }  nsBoxLayoutState state(mPresContext); ClearChildren(state); mFrames.DestroyFrames(mPresContext);  nsCOMPtr<nsIContent> topRowContent; FindRowContentAtIndex(mCurrentIndex, mContent, getter_AddRefs(topRowContent));  if (topRowContent) ConstructContentChain(topRowContent); }  mTopFrame = mBottomFrame = nsnull;  nsBoxLayoutState state(mPresContext); MarkDirtyChildren(state);  VerticalScroll(mCurrentIndex*mRowHeight);  return NS_OK; }   void nsXULTreeOuterGroupFrame::ConstructContentChain(nsIContent* aRowContent) {  NS_IF_RELEASE(mContentChain); NS_NewISupportsArray(&mContentChain);   nsCOMPtr<nsIContent> currContent = dont_QueryInterface(aRowContent); while (currContent && (currContent.get() != mContent)) { mContentChain->InsertElementAt(currContent, 0); nsCOMPtr<nsIContent> otherContent = currContent; otherContent->GetParent(*getter_AddRefs(currContent)); }  NS_ASSERTION(currContent.get() == mContent, "Disaster! Content not contained in our tree!\n"); }  void nsXULTreeOuterGroupFrame::ConstructOldContentChain(nsIContent* aOldRowContent) { nsCOMPtr<nsIContent> childOfCommonAncestor;     FindChildOfCommonContentChainAncestor(aOldRowContent, getter_AddRefs(childOfCommonAncestor));  if (childOfCommonAncestor) {  CreateOldContentChain(aOldRowContent, childOfCommonAncestor); } }  void nsXULTreeOuterGroupFrame::FindChildOfCommonContentChainAncestor(nsIContent *startContent, nsIContent **child) { PRUint32 count; if (mContentChain) { nsresult rv = mContentChain->Count(&count);  if (NS_SUCCEEDED(rv) && (count >0)) { for (PRInt32 curItem = count - 1; curItem >= 0; curItem--) { nsCOMPtr<nsISupports> supports; mContentChain->GetElementAt(curItem, getter_AddRefs(supports)); nsCOMPtr<nsIContent> curContent = do_QueryInterface(supports);   if (IsAncestor(curContent, startContent, child)) return; } } }    if (IsAncestor(mContent, startContent, child)) return;  *child = nsnull; }     PRBool nsXULTreeOuterGroupFrame::IsAncestor(nsIContent *aRowContent, nsIContent *aOldRowContent, nsIContent** firstDescendant) { nsCOMPtr<nsIContent> prevContent; nsCOMPtr<nsIContent> currContent = dont_QueryInterface(aOldRowContent);  while (currContent) { if (aRowContent == currContent.get()) { if (firstDescendant) { *firstDescendant = prevContent; NS_IF_ADDREF(*firstDescendant); } return PR_TRUE; }  prevContent = currContent; prevContent->GetParent(*getter_AddRefs(currContent)); }  return PR_FALSE; }  void nsXULTreeOuterGroupFrame::CreateOldContentChain(nsIContent* aOldRowContent, nsIContent* topOfChain) { nsCOMPtr<nsIContent> currContent = dont_QueryInterface(aOldRowContent); nsCOMPtr<nsIContent> prevContent;  nsCOMPtr<nsIPresShell> shell; mPresContext->GetShell(getter_AddRefs(shell));     while (currContent.get() != topOfChain) { nsIFrame* primaryFrame = nsnull; shell->GetPrimaryFrameFor(currContent, &primaryFrame);  if (primaryFrame) { nsCOMPtr<nsIXULTreeSlice> slice(do_QueryInterface(primaryFrame)); PRBool isRowGroup = PR_FALSE; if (slice) slice->IsGroupFrame(&isRowGroup);  if (isRowGroup) {  nsCOMPtr<nsIContent> parent; currContent->GetParent(*getter_AddRefs(parent));  nsCOMPtr<nsIContent> firstChild; parent->ChildAt(0, *getter_AddRefs(firstChild));  nsIFrame* parentFrame; primaryFrame->GetParent(&parentFrame); PRBool isParentRowGroup = PR_FALSE; nsCOMPtr<nsIXULTreeSlice> slice(do_QueryInterface(parentFrame)); if (slice) slice->IsGroupFrame(&isParentRowGroup);  if (isParentRowGroup) {  nsXULTreeGroupFrame *parentRowGroupFrame = (nsXULTreeGroupFrame*)parentFrame; nsIFrame *currentTopFrame = parentRowGroupFrame->GetFirstFrame();  nsCOMPtr<nsIContent> topContent; currentTopFrame->GetContent(getter_AddRefs(topContent));      if(topContent.get() != firstChild.get()) { nsCOMPtr<nsISupportsArray> contentChain; NS_NewISupportsArray(getter_AddRefs(contentChain)); contentChain->InsertElementAt(firstChild, 0); parentRowGroupFrame->SetContentChain(contentChain); } } } }  prevContent = currContent; prevContent->GetParent(*getter_AddRefs(currContent)); } }  void nsXULTreeOuterGroupFrame::FindRowContentAtIndex(PRInt32& aIndex, nsIContent* aParent, nsIContent** aResult) {  *aResult = nsnull;   if (mRowGroupInfo == nsnull) return;  PRUint32 index = 0; PRUint32 arrayCount; mRowGroupInfo->mTickArray->Count(&arrayCount); nsCOMPtr<nsIContent> startContent; PRUint32 location = aIndex/TICK_FACTOR + 1; PRUint32 point = location*TICK_FACTOR; if (location >= arrayCount) { startContent = mRowGroupInfo->mLastChild; point = mRowGroupInfo->mRowCount-1; } else { nsCOMPtr<nsISupports> supp = getter_AddRefs(mRowGroupInfo->mTickArray->ElementAt(location)); startContent = do_QueryInterface(supp); }  if (!startContent) { NS_ERROR("The tree's tick array is confused!"); return; }  PRInt32 delta = (PRInt32)(point-aIndex); if (delta == 0) { *aResult = startContent; NS_IF_ADDREF(*aResult); } else FindPreviousRowContent(delta, startContent, nsnull, aResult); }  void nsXULTreeOuterGroupFrame::FindPreviousRowContent(PRInt32& aDelta, nsIContent* aUpwardHint, nsIContent* aDownwardHint, nsIContent** aResult) {  *aResult = nsnull;     PRInt32 index = 0; nsCOMPtr<nsIContent> parentContent; if (aUpwardHint) { aUpwardHint->GetParent(*getter_AddRefs(parentContent)); if (!parentContent) { NS_ERROR("Parent content should not be NULL!"); return; } parentContent->IndexOf(aUpwardHint, index); } else if (aDownwardHint) { parentContent = dont_QueryInterface(aDownwardHint); parentContent->ChildCount(index); }    for (PRInt32 i = index-1; i >= 0; i--) { nsCOMPtr<nsIContent> childContent; parentContent->ChildAt(i, *getter_AddRefs(childContent)); nsCOMPtr<nsIAtom> tag; childContent->GetTag(*getter_AddRefs(tag)); if (tag.get() == nsXULAtoms::treerow) { aDelta--; if (aDelta == 0) { *aResult = childContent; NS_IF_ADDREF(*aResult); return; } } else if (tag.get() == nsXULAtoms::treeitem) {  nsCOMPtr<nsIAtom> openAtom = dont_AddRef(NS_NewAtom("open")); nsAutoString isOpen; childContent->GetAttribute(kNameSpaceID_None, openAtom, isOpen); if (isOpen.EqualsWithConversion("true")) {  PRInt32 childContentCount; nsCOMPtr<nsIContent> grandChild; childContent->ChildCount(childContentCount);  PRInt32 j; for (j = childContentCount-1; j >= 0; j--) {  childContent->ChildAt(j, *getter_AddRefs(grandChild)); nsCOMPtr<nsIAtom> grandChildTag; grandChild->GetTag(*getter_AddRefs(grandChildTag)); if (grandChildTag.get() == nsXULAtoms::treechildren) break; } if (j >= 0 && grandChild) FindPreviousRowContent(aDelta, nsnull, grandChild, aResult);  if (aDelta == 0) return; }   FindPreviousRowContent(aDelta, nsnull, childContent, aResult); if (aDelta == 0) return; } }  nsCOMPtr<nsIAtom> tag; parentContent->GetTag(*getter_AddRefs(tag)); if (tag && tag.get() == nsXULAtoms::tree) {  return; } else if (!aDownwardHint) FindPreviousRowContent(aDelta, parentContent, nsnull, aResult);   }  void nsXULTreeOuterGroupFrame::FindNextRowContent(PRInt32& aDelta, nsIContent* aUpwardHint, nsIContent* aDownwardHint, nsIContent** aResult) {  *aResult = nsnull;     PRInt32 index = -1; nsCOMPtr<nsIContent> parentContent; if (aUpwardHint) { aUpwardHint->GetParent(*getter_AddRefs(parentContent)); if (!parentContent) { NS_ERROR("Parent content should not be NULL!"); return; } parentContent->IndexOf(aUpwardHint, index); } else if (aDownwardHint) { parentContent = dont_QueryInterface(aDownwardHint); }  PRInt32 childCount; parentContent->ChildCount(childCount); for (PRInt32 i = index+1; i < childCount; i++) { nsCOMPtr<nsIContent> childContent; parentContent->ChildAt(i, *getter_AddRefs(childContent)); nsCOMPtr<nsIAtom> tag; childContent->GetTag(*getter_AddRefs(tag)); if (tag.get() == nsXULAtoms::treerow) { aDelta--; if (aDelta == 0) { *aResult = childContent; NS_IF_ADDREF(*aResult); return; } } else if (tag.get() == nsXULAtoms::treeitem) {  FindNextRowContent(aDelta, nsnull, childContent, aResult); if (aDelta == 0) return; } else if (tag.get() == nsXULAtoms::treechildren) {  nsCOMPtr<nsIAtom> openAtom = dont_AddRef(NS_NewAtom("open")); nsAutoString isOpen; parentContent->GetAttribute(kNameSpaceID_None, openAtom, isOpen); if (isOpen.EqualsWithConversion("true")) { FindNextRowContent(aDelta, nsnull, childContent, aResult); if (aDelta == 0) return; } } }  nsCOMPtr<nsIAtom> tag; parentContent->GetTag(*getter_AddRefs(tag)); if (tag && tag.get() == nsXULAtoms::tree) {  return; } else if (!aDownwardHint) FindNextRowContent(aDelta, parentContent, nsnull, aResult);   }  void nsXULTreeOuterGroupFrame::EnsureRowIsVisible(PRInt32 aRowIndex) { PRInt32 rows = GetAvailableHeight()/mRowHeight; PRInt32 bottomIndex = mCurrentIndex + rows - 1; if (IsFixedRowSize()) bottomIndex++;   if (mCurrentIndex <= aRowIndex && aRowIndex <= bottomIndex) return;  PRInt32 newIndex = aRowIndex;  PRInt32 delta = mCurrentIndex > newIndex ? mCurrentIndex - newIndex : newIndex - mCurrentIndex; PRBool up = newIndex < mCurrentIndex; if (up) mCurrentIndex = newIndex; else {  PRInt32 adjustment = newIndex - rows; if (!IsFixedRowSize()) adjustment++; delta = adjustment - mCurrentIndex; mCurrentIndex = adjustment; }  InternalPositionChanged(up, delta);    nsCOMPtr<nsIDocument> doc; mContent->GetDocument(*getter_AddRefs(doc)); doc->FlushPendingNotifications(); }  void nsXULTreeOuterGroupFrame::ScrollToIndex(PRInt32 aRowIndex) { if ( aRowIndex < 0 ) return;  PRInt32 newIndex = aRowIndex; PRInt32 delta = mCurrentIndex > newIndex ? mCurrentIndex - newIndex : newIndex - mCurrentIndex; PRBool up = newIndex < mCurrentIndex; mCurrentIndex = newIndex; InternalPositionChanged(up, delta);    nsCOMPtr<nsIDocument> doc; mContent->GetDocument(*getter_AddRefs(doc)); doc->FlushPendingNotifications(); }     NS_IMETHODIMP nsXULTreeOuterGroupFrame::IndexOfItem(nsIContent* aRoot, nsIContent* aContent, PRBool aDescendIntoRows, PRBool aParentIsOpen, PRInt32 *aResult) { PRInt32 childCount=0; aRoot->ChildCount(childCount);  nsresult rv;  PRInt32 childIndex; for (childIndex=0; childIndex<childCount; childIndex++) { nsCOMPtr<nsIContent> child; aRoot->ChildAt(childIndex, *getter_AddRefs(child));  nsCOMPtr<nsIAtom> childTag; child->GetTag(*getter_AddRefs(childTag));   if (child.get() == aContent) return NS_OK;   if (childTag.get() == nsXULAtoms::treeitem) (*aResult)++;  PRBool descend = PR_TRUE; PRBool parentIsOpen = aParentIsOpen;   if (childTag.get() == nsXULAtoms::treechildren && !parentIsOpen) descend = PR_FALSE;   else if (childTag.get() == nsXULAtoms::treerow && !aDescendIntoRows) descend = PR_FALSE;   else if (childTag.get() == nsXULAtoms::treeitem) { nsAutoString isOpen; rv = child->GetAttribute(kNameSpaceID_None, nsXULAtoms::open, isOpen);  if (!isOpen.EqualsWithConversion("true")) parentIsOpen=PR_FALSE; }   if (descend) { rv = IndexOfItem(child, aContent, aDescendIntoRows, parentIsOpen, aResult); if (NS_SUCCEEDED(rv)) return NS_OK; } }   return NS_ERROR_FAILURE; }        NS_IMETHODIMP nsXULTreeOuterGroupFrame :: Paint ( nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer) { nsresult res = NS_OK; res = nsBoxFrame::Paint ( aPresContext, aRenderingContext, aDirtyRect, aWhichLayer );  if ( (aWhichLayer == eFramePaintLayer_Content) && (mYDropLoc != nsTreeItemDragCapturer::kNoDropLoc || mDropOnContainer || mTreeIsSorted) ) PaintDropFeedback ( aPresContext, aRenderingContext, PR_TRUE );  return res;  }         NS_IMETHODIMP nsXULTreeOuterGroupFrame :: AttributeChanged ( nsIPresContext* aPresContext, nsIContent* aChild, PRInt32 aNameSpaceID, nsIAtom* aAttribute, PRInt32 aHint) { nsresult rv = NS_OK;  if ( aAttribute == nsXULAtoms::ddTriggerRepaintSorted ) {   mTreeIsSorted = PR_TRUE; ForceDrawFrame ( aPresContext, this ); mTreeIsSorted = PR_FALSE; } else rv = nsXULTreeGroupFrame::AttributeChanged ( aPresContext, aChild, aNameSpaceID, aAttribute, aHint );  return rv;  }    #ifdef XP_MAC #pragma mark - #endif         NS_IMETHODIMP nsXULTreeOuterGroupFrame :: StopTracking ( ) {  CaptureMouse ( mPresContext, PR_FALSE );  StopAutoScrollTimer ( ); mCurrentlyTrackingAutoScroll = PR_FALSE;  return NS_OK; }          nsresult nsXULTreeOuterGroupFrame :: HandleAutoScrollTracking ( const nsPoint & aPoint ) { if ( !mCurrentlyTrackingAutoScroll ) {  CaptureMouse ( mPresContext, PR_TRUE );    nsCOMPtr<nsIDragService> dragServ ( do_GetService("component: if ( dragServ ) { nsCOMPtr<nsIDragSession> session; dragServ->GetCurrentSession ( getter_AddRefs(session) ); if ( session ) session->StartTracking(this); }  mCurrentlyTrackingAutoScroll = PR_TRUE; }   StartAutoScrollTimer ( aPoint, 30 );  return NS_OK;  }   nsresult nsXULTreeOuterGroupFrame::StartAutoScrollTimer(const nsPoint& aPoint, PRUint32 aDelay) { nsresult result;  if (!mAutoScrollTimer) { result = NS_NewAutoScrollTimer(this, &mAutoScrollTimer); if (NS_FAILED(result)) return result;  if (!mAutoScrollTimer) return NS_ERROR_OUT_OF_MEMORY; }  result = mAutoScrollTimer->SetDelay(aDelay);  if (NS_FAILED(result)) return result;  return DoAutoScroll(aPoint); }   nsresult nsXULTreeOuterGroupFrame::StopAutoScrollTimer() { if (mAutoScrollTimer) return mAutoScrollTimer->Stop();  return NS_OK; }         nsresult nsXULTreeOuterGroupFrame::DoAutoScroll ( const nsPoint& aPoint ) { if ( mAutoScrollTimer ) mAutoScrollTimer->Stop();  float pixelsToTwips = 0.0; mPresContext->GetPixelsToTwips ( &pixelsToTwips ); nsPoint mouseInTwips ( NSToIntRound(aPoint.x * pixelsToTwips), NSToIntRound(aPoint.y * pixelsToTwips) );    nscoord frameOffsetX = 0, frameOffsetY = 0; nsIFrame* curr = this; curr->GetParent(&curr); while ( curr ) { nsPoint origin; curr->GetOrigin(origin); frameOffsetX += origin.x; frameOffsetY += origin.y; curr->GetParent(&curr); } mouseInTwips.MoveBy ( -frameOffsetX, -frameOffsetY );  const int kMarginHeight = NSToIntRound ( 12 * pixelsToTwips );  if ( mouseInTwips.x <= 0 || mouseInTwips.x >= mRect.width ) UnregisterTracking(); else {  PRBool continueTracking = PR_TRUE; if ( mouseInTwips.y < 0 ) { if ( mouseInTwips.y > -kMarginHeight ) ScrollToIndex ( mCurrentIndex - 1 ); else { continueTracking = PR_FALSE; UnregisterTracking(); } } else if ( mouseInTwips.y > GetAvailableHeight() ) { if ( mouseInTwips.y < GetAvailableHeight() + kMarginHeight ) ScrollToIndex ( mCurrentIndex + 1 ); else { continueTracking = PR_FALSE; UnregisterTracking(); } }   if ( mAutoScrollTimer && continueTracking ) mAutoScrollTimer->Start(aPoint); }  return NS_OK; }        void nsXULTreeOuterGroupFrame :: UnregisterTracking ( ) { nsCOMPtr<nsIDragService> dragService ( do_GetService("component: if ( dragService ) {  nsCOMPtr<nsIDragSession> session; dragService->GetCurrentSession ( getter_AddRefs(session) ); if ( session ) session->StopTracking(); }  }   #ifdef XP_MAC #pragma mark - #endif        NS_IMPL_ISUPPORTS1(nsDragAutoScrollTimer, nsITimerCallback)        void nsDragAutoScrollTimer :: Notify(nsITimer *timer) { mTree->DoAutoScroll(mPoint); }   nsresult
nsresult NS_NewAutoScrollTimer(nsXULTreeOuterGroupFrame* aTree, nsDragAutoScrollTimer **aResult) ;//// nsDragOverListener//// Just a little class that listens for dragOvers to trigger the auto-scrolling// code.//class nsDragOverListener : public nsIDOMDragListener{public:  nsDragOverListener ( nsXULTreeOuterGroupFrame* inTree );  virtual ~nsDragOverListener() { } ;  NS_DECL_ISUPPORTS    // nsIDOMDragListener  virtual nsresult HandleEvent(nsIDOMEvent* aEvent);  virtual nsresult DragEnter(nsIDOMEvent* aDragEvent);  virtual nsresult DragOver(nsIDOMEvent* aDragEvent);  virtual nsresult DragExit(nsIDOMEvent* aDragEvent);  virtual nsresult DragDrop(nsIDOMEvent* aDragEvent);  virtual nsresult DragGesture(nsIDOMEvent* aDragEvent);protected:  nsXULTreeOuterGroupFrame* mTree;}; // nsDragEnterListenerNS_IMPL_ISUPPORTS2(nsDragOverListener, nsIDOMEventListener, nsIDOMDragListener)nsDragOverListener :: nsDragOverListener ( nsXULTreeOuterGroupFrame* inTree )  : mTree ( inTree ){  NS_INIT_REFCNT();}//// DragOver//// Kick off our timer/capturing for autoscrolling, the drag has entered us. We// will continue capturing the mouse until the auto-scroll manager tells us to// stop (either the drag is over, it left the window, or someone else wants a // crack at auto-scrolling).//nsresultnsDragOverListener :: DragOver(nsIDOMEvent* aDragEvent){  nsCOMPtr<nsIDOMMouseEvent> mouseEvent ( do_QueryInterface(aDragEvent) );  if ( mouseEvent ) {    PRInt32 x = 0, y = 0;    mouseEvent->GetClientX ( &x );    mouseEvent->GetClientY ( &y );    mTree->HandleAutoScrollTracking ( nsPoint(x,y) );  }  return NS_OK;} // DragOver//// The rest are stubs//nsresultnsDragOverListener::HandleEvent(nsIDOMEvent* aEvent){  return NS_OK;}nsresultnsDragOverListener::DragEnter(nsIDOMEvent* aDragEvent){  return NS_OK;}nsresultnsDragOverListener::DragGesture(nsIDOMEvent* aDragEvent){  return NS_OK;}nsresultnsDragOverListener::DragExit(nsIDOMEvent* aDragEvent){  return NS_OK;}nsresultnsDragOverListener::DragDrop(nsIDOMEvent* aDragEvent){  return NS_OK;}#ifdef XP_MAC#pragma mark -#endif//// NS_NewXULTreeOuterGroupFrame//// Creates a new TreeOuterGroup frame//nsresultNS_NewXULTreeOuterGroupFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame, PRBool aIsRoot,                         nsIBoxLayout* aLayoutManager, PRBool aIsHorizontal){  NS_PRECONDITION(aNewFrame, "null OUT ptr");  if (nsnull == aNewFrame) {    return NS_ERROR_NULL_POINTER;  }  nsXULTreeOuterGroupFrame* it = new (aPresShell) nsXULTreeOuterGroupFrame(aPresShell, aIsRoot, aLayoutManager, aIsHorizontal);  if (!it)    return NS_ERROR_OUT_OF_MEMORY;  *aNewFrame = it;  return NS_OK;  } // NS_NewXULTreeOuterGroupFrame// ConstructornsXULTreeOuterGroupFrame::nsXULTreeOuterGroupFrame(nsIPresShell* aPresShell, PRBool aIsRoot, nsIBoxLayout* aLayoutManager, PRBool aIsHorizontal):nsXULTreeGroupFrame(aPresShell, aIsRoot, aLayoutManager, aIsHorizontal), mRowGroupInfo(nsnull), mRowHeight(0), mCurrentIndex(0), mTwipIndex(0), mAutoScrollTimer(nsnull), mTreeIsSorted(PR_FALSE), mDragOverListener(nsnull), mCurrentlyTrackingAutoScroll(PR_FALSE){}// DestructornsXULTreeOuterGroupFrame::~nsXULTreeOuterGroupFrame(){  nsCOMPtr<nsIContent> content;  GetContent(getter_AddRefs(content));  nsCOMPtr<nsIDOMEventReceiver> receiver(do_QueryInterface(content));  // NOTE: the last Remove will delete the drag capturer  if ( receiver && mDragOverListener )     receiver->RemoveEventListener(NS_ConvertASCIItoUCS2("dragover"), mDragOverListener, PR_TRUE);    delete mRowGroupInfo;  StopAutoScrollTimer();  NS_IF_RELEASE ( mAutoScrollTimer );}NS_IMETHODIMP_(nsrefcnt) nsXULTreeOuterGroupFrame::AddRef(void){  return NS_OK;}NS_IMETHODIMP_(nsrefcnt)nsXULTreeOuterGroupFrame::Release(void){  return NS_OK;}//// QueryInterface//NS_INTERFACE_MAP_BEGIN(nsXULTreeOuterGroupFrame)  NS_INTERFACE_MAP_ENTRY(nsIScrollbarMediator)  NS_INTERFACE_MAP_ENTRY(nsIDragTracker)NS_INTERFACE_MAP_END_INHERITING(nsXULTreeGroupFrame)//// Init//// Setup scrolling and event listeners for drag auto-scrolling//NS_IMETHODIMPnsXULTreeOuterGroupFrame::Init(nsIPresContext* aPresContext, nsIContent* aContent,                               nsIFrame* aParent, nsIStyleContext* aContext, nsIFrame* aPrevInFlow){  nsresult rv = nsXULTreeGroupFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow);    float p2t;  aPresContext->GetScaledPixelsToTwips(&p2t);  mOnePixel = NSIntPixelsToTwips(1, p2t);    nsIFrame* box;  aParent->GetParent(&box);  if (!box)    return rv;  nsCOMPtr<nsIScrollableFrame> scrollFrame(do_QueryInterface(box));  if (!scrollFrame)    return rv;  nsIBox* verticalScrollbar;  scrollFrame->GetScrollbarBox(PR_TRUE, &verticalScrollbar);  if (!verticalScrollbar) {    NS_ERROR("Unable to install the scrollbar mediator on the tree widget. You must be using GFX scrollbars.");    return NS_ERROR_FAILURE;  }  nsCOMPtr<nsIScrollbarFrame> scrollbarFrame(do_QueryInterface(verticalScrollbar));  scrollbarFrame->SetScrollbarMediator(this);  // Our frame's lifetime is bounded by the lifetime of the content model, so we're guaranteed  // that the content node won't go away on us. As a result, our listener can't go away before the  // frame is deleted. Since the content node holds owning references to our drag capturer, which  // we tear down in the dtor, there is no need to hold an owning ref to it ourselves.    nsCOMPtr<nsIDOMEventReceiver> receiver(do_QueryInterface(aContent));  if ( receiver ) {    mDragOverListener = new nsDragOverListener(this);    receiver->AddEventListener(NS_ConvertASCIItoUCS2("dragover"), mDragOverListener, PR_FALSE);  }    return rv;} // InitPRBoolnsXULTreeOuterGroupFrame::IsFixedRowSize(){  nsCOMPtr<nsIContent> parent;  mContent->GetParent(*getter_AddRefs(parent));  nsAutoString rows;  parent->GetAttribute(kNameSpaceID_None, nsXULAtoms::rows, rows);  if (!rows.IsEmpty())     return PR_TRUE;  return PR_FALSE;}voidnsXULTreeOuterGroupFrame::SetRowHeight(nscoord aRowHeight){   if (mRowHeight == 0) {     mRowHeight = aRowHeight;    nsCOMPtr<nsIContent> parent;    mContent->GetParent(*getter_AddRefs(parent));    nsAutoString rows;    parent->GetAttribute(kNameSpaceID_None, nsXULAtoms::rows, rows);    if (!rows.IsEmpty()) {      PRInt32 dummy;      PRInt32 count = rows.ToInteger(&dummy);      float t2p;      mPresContext->GetTwipsToPixels(&t2p);      PRInt32 rowHeight = NSTwipsToIntPixels(aRowHeight, t2p);      nsAutoString value;      value.AppendInt(rowHeight*count);      parent->SetAttribute(kNameSpaceID_None, nsHTMLAtoms::height, value, PR_FALSE);    }    nsBoxLayoutState state(mPresContext);    MarkDirtyChildren(state);   } }nscoordnsXULTreeOuterGroupFrame::GetYPosition(){  nsIBox* box;  GetParentBox(&box);  if (!box)    return 0;  box->GetParentBox(&box);  if (!box)    return 0;  nsCOMPtr<nsIScrollableFrame> scrollFrame(do_QueryInterface(box));  if (!scrollFrame)    return 0;  nscoord x, y;  scrollFrame->GetScrollPosition(mPresContext, x, y);  return y;}voidnsXULTreeOuterGroupFrame::VerticalScroll(PRInt32 aDelta){  nsIBox* box;  GetParentBox(&box);  if (!box)    return;  box->GetParentBox(&box);  if (!box)    return;  nsCOMPtr<nsIScrollableFrame> scrollFrame(do_QueryInterface(box));  if (!scrollFrame)    return;  nscoord x, y;  scrollFrame->GetScrollPosition(mPresContext, x, y);   scrollFrame->ScrollTo(mPresContext, x, aDelta);}nscoordnsXULTreeOuterGroupFrame::GetAvailableHeight(){  nsIBox* box;  GetParentBox(&box);  if (!box)    return 0;  box->GetParentBox(&box);  if (!box)    return 0;  nsCOMPtr<nsIScrollableFrame> scrollFrame(do_QueryInterface(box));  if (!scrollFrame)    return 0;  nscoord x, y;  scrollFrame->GetClipSize(mPresContext, &x, &y);  return y;}voidnsXULTreeOuterGroupFrame::ComputeTotalRowCount(PRInt32& aCount, nsIContent* aParent){  if (!mRowGroupInfo) {    mRowGroupInfo = new nsXULTreeRowGroupInfo();  }  PRInt32 childCount;  aParent->ChildCount(childCount);  for (PRInt32 i = 0; i < childCount; i++) {    nsCOMPtr<nsIContent> childContent;    aParent->ChildAt(i, *getter_AddRefs(childContent));    nsCOMPtr<nsIAtom> tag;    childContent->GetTag(*getter_AddRefs(tag));    if (tag.get() == nsXULAtoms::treerow) {      if ((aCount%TICK_FACTOR) == 0)        mRowGroupInfo->Add(childContent);      mRowGroupInfo->mLastChild = childContent;      aCount++;    }    else if (tag.get() == nsXULAtoms::treeitem) {      // Descend into this row group and try to find the next row.      ComputeTotalRowCount(aCount, childContent);    }    else if (tag.get() == nsXULAtoms::treechildren) {      // If it's open, descend into its treechildren.      nsCOMPtr<nsIAtom> openAtom = dont_AddRef(NS_NewAtom("open"));      nsAutoString isOpen;      nsCOMPtr<nsIContent> parent;      childContent->GetParent(*getter_AddRefs(parent));      parent->GetAttribute(kNameSpaceID_None, openAtom, isOpen);      if (isOpen.EqualsWithConversion("true"))        ComputeTotalRowCount(aCount, childContent);    }  }}NS_IMETHODIMPnsXULTreeOuterGroupFrame::ScrollbarButtonPressed(PRInt32 aOldIndex, PRInt32 aNewIndex){  if (aOldIndex == aNewIndex)    return NS_OK;  if (aNewIndex < aOldIndex)    mCurrentIndex--;  else mCurrentIndex++;  if (mCurrentIndex < 0) {    mCurrentIndex = 0;    return NS_OK;  }  InternalPositionChanged(aNewIndex < aOldIndex, 1);  return NS_OK;}NS_IMETHODIMPnsXULTreeOuterGroupFrame::PositionChanged(PRInt32 aOldIndex, PRInt32 aNewIndex){  if (aOldIndex == aNewIndex)    return NS_OK;    PRInt32 oldTwipIndex, newTwipIndex;  oldTwipIndex = (aOldIndex*mOnePixel);  newTwipIndex = (aNewIndex*mOnePixel);  PRInt32 twipDelta = newTwipIndex > oldTwipIndex ? newTwipIndex - oldTwipIndex : oldTwipIndex - newTwipIndex;  PRInt32 delta = twipDelta / mRowHeight;  PRInt32 remainder = twipDelta % mRowHeight;  if (remainder > (mRowHeight/2))    delta++;  if (delta == 0)    return NS_OK;  mCurrentIndex = newTwipIndex > oldTwipIndex ? mCurrentIndex + delta : mCurrentIndex - delta;    if (mCurrentIndex < 0) {    mCurrentIndex = 0;    return NS_OK;  }  return InternalPositionChanged(newTwipIndex < oldTwipIndex, delta);}NS_IMETHODIMPnsXULTreeOuterGroupFrame::InternalPositionChanged(PRBool aUp, PRInt32 aDelta){  PRInt32 visibleRows = GetAvailableHeight()/mRowHeight;    // Get our presentation context.  if (aDelta < visibleRows) {    if (mContentChain) {      // XXX This could cause problems because of async reflow.      // Eventually we need to make the code smart enough to look at a content chain      // when building ANOTHER content chain.        // Ensure all reflows happen first.      nsCOMPtr<nsIPresShell> shell;      mPresContext->GetShell(getter_AddRefs(shell));      shell->FlushPendingNotifications();    }    PRInt32 loseRows = aDelta;    // scrolling down    if (!aUp) {      // Figure out how many rows we have to lose off the top.      DestroyRows(loseRows);    }    // scrolling up    else {      // Get our first row content.      nsCOMPtr<nsIContent> rowContent;      GetFirstRowContent(getter_AddRefs(rowContent));      // Figure out how many rows we have to lose off the bottom.      ReverseDestroyRows(loseRows);          // Now that we've lost some rows, we need to create a      // content chain that provides a hint for moving forward.      nsCOMPtr<nsIContent> topRowContent;      PRInt32 findContent = aDelta;      FindPreviousRowContent(findContent, rowContent, nsnull, getter_AddRefs(topRowContent));      ConstructContentChain(topRowContent);	    //Now construct the chain for the old top row so its content chain gets	    //set up correctly.	    ConstructOldContentChain(rowContent);    }  }  else {    // Just blow away all our frames, but keep a content chain    // as a hint to figure out how to build the frames.    // Remove the scrollbar first.    // get the starting row index and row count    nsIBox* currBox;    GetChildBox(&currBox);    while (currBox) {      nsIBox* nextBox;      currBox->GetNextBox(&nextBox);      nsIFrame* frame;      currBox->QueryInterface(kIFrameIID, (void**)&frame);       mFrameConstructor->RemoveMappingsForFrameSubtree(mPresContext, frame, nsnull);      currBox = nextBox;    }    nsBoxLayoutState state(mPresContext);    ClearChildren(state);    mFrames.DestroyFrames(mPresContext);    nsCOMPtr<nsIContent> topRowContent;    FindRowContentAtIndex(mCurrentIndex, mContent, getter_AddRefs(topRowContent));    if (topRowContent)      ConstructContentChain(topRowContent);  }  mTopFrame = mBottomFrame = nsnull; // Make sure everything is cleared out.  nsBoxLayoutState state(mPresContext);  MarkDirtyChildren(state);  VerticalScroll(mCurrentIndex*mRowHeight);  return NS_OK;}void nsXULTreeOuterGroupFrame::ConstructContentChain(nsIContent* aRowContent){  // Create the content chain array.  NS_IF_RELEASE(mContentChain);  NS_NewISupportsArray(&mContentChain);  // Move up the chain until we hit our content node.  nsCOMPtr<nsIContent> currContent = dont_QueryInterface(aRowContent);  while (currContent && (currContent.get() != mContent)) {    mContentChain->InsertElementAt(currContent, 0);    nsCOMPtr<nsIContent> otherContent = currContent;    otherContent->GetParent(*getter_AddRefs(currContent));  }  NS_ASSERTION(currContent.get() == mContent, "Disaster! Content not contained in our tree!\n");}void nsXULTreeOuterGroupFrame::ConstructOldContentChain(nsIContent* aOldRowContent){	nsCOMPtr<nsIContent> childOfCommonAncestor;	//Find the first child of the common ancestor between the new top row's content chain	//and the old top row.  Everything between this child and the old top row potentially need	//to have their content chains reset.	FindChildOfCommonContentChainAncestor(aOldRowContent, getter_AddRefs(childOfCommonAncestor));	if (childOfCommonAncestor) {      //Set up the old top rows content chian.	  CreateOldContentChain(aOldRowContent, childOfCommonAncestor);	}}voidnsXULTreeOuterGroupFrame::FindChildOfCommonContentChainAncestor(nsIContent *startContent, nsIContent **child){	PRUint32 count;	if (mContentChain)	{	  nsresult rv = mContentChain->Count(&count);	  if (NS_SUCCEEDED(rv) && (count >0)) {	    for (PRInt32 curItem = count - 1; curItem >= 0; curItem--) {		    nsCOMPtr<nsISupports> supports;        mContentChain->GetElementAt(curItem, getter_AddRefs(supports));        nsCOMPtr<nsIContent> curContent = do_QueryInterface(supports);		    //See if curContent is an ancestor of startContent.		    if (IsAncestor(curContent, startContent, child))		      return;		  }	  }	}	//mContent isn't actually put in the content chain, so we need to	//check it separately.	if (IsAncestor(mContent, startContent, child))		return;	*child = nsnull;}// if oldRowContent is an ancestor of rowContent, return true,// and return the previous ancestor if requestedPRBoolnsXULTreeOuterGroupFrame::IsAncestor(nsIContent *aRowContent, nsIContent *aOldRowContent, nsIContent** firstDescendant){  nsCOMPtr<nsIContent> prevContent;	  nsCOMPtr<nsIContent> currContent = dont_QueryInterface(aOldRowContent);    while (currContent) {	  if (aRowContent == currContent.get()) {		  if (firstDescendant) {		    *firstDescendant = prevContent;		    NS_IF_ADDREF(*firstDescendant);		  }		  return PR_TRUE;	  }    	  prevContent = currContent;	  prevContent->GetParent(*getter_AddRefs(currContent));  }  return PR_FALSE;}voidnsXULTreeOuterGroupFrame::CreateOldContentChain(nsIContent* aOldRowContent, nsIContent* topOfChain){  nsCOMPtr<nsIContent> currContent = dont_QueryInterface(aOldRowContent);  nsCOMPtr<nsIContent> prevContent;  nsCOMPtr<nsIPresShell> shell;  mPresContext->GetShell(getter_AddRefs(shell));  //For each item between the (oldtoprow) and  // (the new first child of common ancestry between new top row and old top row)  // we need to see if the content chain has to be reset.  while (currContent.get() != topOfChain) {    nsIFrame* primaryFrame = nsnull;    shell->GetPrimaryFrameFor(currContent, &primaryFrame);          if (primaryFrame) {      nsCOMPtr<nsIXULTreeSlice> slice(do_QueryInterface(primaryFrame));      PRBool isRowGroup = PR_FALSE;      if (slice)        slice->IsGroupFrame(&isRowGroup);    	    if (isRowGroup) {		    //Get the current content's parent's first child		    nsCOMPtr<nsIContent> parent;		    currContent->GetParent(*getter_AddRefs(parent));		    		    nsCOMPtr<nsIContent> firstChild;		    parent->ChildAt(0, *getter_AddRefs(firstChild));        nsIFrame* parentFrame;        primaryFrame->GetParent(&parentFrame);        PRBool isParentRowGroup = PR_FALSE;        nsCOMPtr<nsIXULTreeSlice> slice(do_QueryInterface(parentFrame));        if (slice)          slice->IsGroupFrame(&isParentRowGroup);    	      if (isParentRowGroup) {           //Get the current content's parent's first frame.           nsXULTreeGroupFrame *parentRowGroupFrame =               (nsXULTreeGroupFrame*)parentFrame;		       nsIFrame *currentTopFrame = parentRowGroupFrame->GetFirstFrame();			     nsCOMPtr<nsIContent> topContent;			     currentTopFrame->GetContent(getter_AddRefs(topContent));			     // If the current content's parent's first child is different           // than the current frame's parent's first child then we know           // they are out of synch and we need to set the content           // chain correctly.			     if(topContent.get() != firstChild.get()) {				     nsCOMPtr<nsISupportsArray> contentChain;				     NS_NewISupportsArray(getter_AddRefs(contentChain));             contentChain->InsertElementAt(firstChild, 0);             parentRowGroupFrame->SetContentChain(contentChain);           }        }      }    }	  prevContent = currContent;	  prevContent->GetParent(*getter_AddRefs(currContent));  }}voidnsXULTreeOuterGroupFrame::FindRowContentAtIndex(PRInt32& aIndex,                                                nsIContent* aParent,                                                nsIContent** aResult){  // Init to nsnull.  *aResult = nsnull;  // Walk over the tick array.  if (mRowGroupInfo == nsnull)    return;  PRUint32 index = 0;  PRUint32 arrayCount;  mRowGroupInfo->mTickArray->Count(&arrayCount);  nsCOMPtr<nsIContent> startContent;  PRUint32 location = aIndex/TICK_FACTOR + 1;  PRUint32 point = location*TICK_FACTOR;  if (location >= arrayCount) {    startContent = mRowGroupInfo->mLastChild;    point = mRowGroupInfo->mRowCount-1;  }  else {    nsCOMPtr<nsISupports> supp = getter_AddRefs(mRowGroupInfo->mTickArray->ElementAt(location));    startContent = do_QueryInterface(supp);  }  if (!startContent) {    NS_ERROR("The tree's tick array is confused!");    return;  }  PRInt32 delta = (PRInt32)(point-aIndex);  if (delta == 0) {    *aResult = startContent;    NS_IF_ADDREF(*aResult);  }  else FindPreviousRowContent(delta, startContent, nsnull, aResult);}void nsXULTreeOuterGroupFrame::FindPreviousRowContent(PRInt32& aDelta, nsIContent* aUpwardHint,                                                  nsIContent* aDownwardHint,                                                 nsIContent** aResult){  // Init to nsnull.  *aResult = nsnull;  // It disappoints me that this function is completely tied to the content nodes,  // but I can't see any other way to handle this.  I don't have the frames, so I have nothing  // else to fall back on but the content nodes.  PRInt32 index = 0;  nsCOMPtr<nsIContent> parentContent;  if (aUpwardHint) {    aUpwardHint->GetParent(*getter_AddRefs(parentContent));    if (!parentContent) {      NS_ERROR("Parent content should not be NULL!");      return;    }    parentContent->IndexOf(aUpwardHint, index);  }  else if (aDownwardHint) {    parentContent = dont_QueryInterface(aDownwardHint);    parentContent->ChildCount(index);  }  /* Let me see inside the damn nsCOMptrs  nsIAtom* aAtom;  parentContent->GetTag(aAtom);  nsAutoString result;  aAtom->ToString(result);  */  for (PRInt32 i = index-1; i >= 0; i--) {    nsCOMPtr<nsIContent> childContent;    parentContent->ChildAt(i, *getter_AddRefs(childContent));    nsCOMPtr<nsIAtom> tag;    childContent->GetTag(*getter_AddRefs(tag));    if (tag.get() == nsXULAtoms::treerow) {      aDelta--;      if (aDelta == 0) {        *aResult = childContent;        NS_IF_ADDREF(*aResult);        return;      }    }    else if (tag.get() == nsXULAtoms::treeitem) {      // If it's open, descend into its treechildren node first.      nsCOMPtr<nsIAtom> openAtom = dont_AddRef(NS_NewAtom("open"));      nsAutoString isOpen;      childContent->GetAttribute(kNameSpaceID_None, openAtom, isOpen);      if (isOpen.EqualsWithConversion("true")) {        // Find the <treechildren> node.        PRInt32 childContentCount;        nsCOMPtr<nsIContent> grandChild;        childContent->ChildCount(childContentCount);        PRInt32 j;        for (j = childContentCount-1; j >= 0; j--) {                    childContent->ChildAt(j, *getter_AddRefs(grandChild));          nsCOMPtr<nsIAtom> grandChildTag;          grandChild->GetTag(*getter_AddRefs(grandChildTag));          if (grandChildTag.get() == nsXULAtoms::treechildren)            break;        }        if (j >= 0 && grandChild)          FindPreviousRowContent(aDelta, nsnull, grandChild, aResult);              if (aDelta == 0)          return;      }      // Descend into this row group and try to find a previous row.      FindPreviousRowContent(aDelta, nsnull, childContent, aResult);      if (aDelta == 0)        return;    }  }  nsCOMPtr<nsIAtom> tag;  parentContent->GetTag(*getter_AddRefs(tag));  if (tag && tag.get() == nsXULAtoms::tree) {    // Hopeless. It ain't in there.    return;  }  else if (!aDownwardHint) // We didn't find it here. We need to go up to our parent, using ourselves as a hint.    FindPreviousRowContent(aDelta, parentContent, nsnull, aResult);  // Bail. There's nothing else we can do.}void nsXULTreeOuterGroupFrame::FindNextRowContent(PRInt32& aDelta, nsIContent* aUpwardHint,                                              nsIContent* aDownwardHint,                                             nsIContent** aResult){  // Init to nsnull.  *aResult = nsnull;  // It disappoints me that this function is completely tied to the content nodes,  // but I can't see any other way to handle this.  I don't have the frames, so I have nothing  // else to fall back on but the content nodes.  PRInt32 index = -1;  nsCOMPtr<nsIContent> parentContent;  if (aUpwardHint) {    aUpwardHint->GetParent(*getter_AddRefs(parentContent));    if (!parentContent) {      NS_ERROR("Parent content should not be NULL!");      return;    }    parentContent->IndexOf(aUpwardHint, index);  }  else if (aDownwardHint) {    parentContent = dont_QueryInterface(aDownwardHint);  }  PRInt32 childCount;  parentContent->ChildCount(childCount);  for (PRInt32 i = index+1; i < childCount; i++) {    nsCOMPtr<nsIContent> childContent;    parentContent->ChildAt(i, *getter_AddRefs(childContent));    nsCOMPtr<nsIAtom> tag;    childContent->GetTag(*getter_AddRefs(tag));    if (tag.get() == nsXULAtoms::treerow) {      aDelta--;      if (aDelta == 0) {        *aResult = childContent;        NS_IF_ADDREF(*aResult);        return;      }    }    else if (tag.get() == nsXULAtoms::treeitem) {      // Descend into this row group and try to find a next row.      FindNextRowContent(aDelta, nsnull, childContent, aResult);      if (aDelta == 0)        return;    }    else if (tag.get() == nsXULAtoms::treechildren) {      // If it's open, descend into its treechildren node first.      nsCOMPtr<nsIAtom> openAtom = dont_AddRef(NS_NewAtom("open"));      nsAutoString isOpen;      parentContent->GetAttribute(kNameSpaceID_None, openAtom, isOpen);      if (isOpen.EqualsWithConversion("true")) {        FindNextRowContent(aDelta, nsnull, childContent, aResult);        if (aDelta == 0)          return;      }    }  }  nsCOMPtr<nsIAtom> tag;  parentContent->GetTag(*getter_AddRefs(tag));  if (tag && tag.get() == nsXULAtoms::tree) {    // Hopeless. It ain't in there.    return;  }  else if (!aDownwardHint) // We didn't find it here. We need to go up to our parent, using ourselves as a hint.    FindNextRowContent(aDelta, parentContent, nsnull, aResult);  // Bail. There's nothing else we can do.}voidnsXULTreeOuterGroupFrame::EnsureRowIsVisible(PRInt32 aRowIndex){  PRInt32 rows = GetAvailableHeight()/mRowHeight;  PRInt32 bottomIndex = mCurrentIndex + rows - 1;  if (IsFixedRowSize())    bottomIndex++;  // if row is visible, ignore  if (mCurrentIndex <= aRowIndex && aRowIndex <= bottomIndex)    return;  PRInt32 newIndex = aRowIndex;    PRInt32 delta = mCurrentIndex > newIndex ? mCurrentIndex - newIndex : newIndex - mCurrentIndex;  PRBool up = newIndex < mCurrentIndex;  if (up)    mCurrentIndex = newIndex;  else {    // Scroll just enough to bring the newIndex into view.    PRInt32 adjustment = newIndex - rows;    if (!IsFixedRowSize())      adjustment++;    delta = adjustment - mCurrentIndex;    mCurrentIndex = adjustment;  }  InternalPositionChanged(up, delta);  // This change has to happen immediately.  // Flush any pending reflow commands.  nsCOMPtr<nsIDocument> doc;  mContent->GetDocument(*getter_AddRefs(doc));  doc->FlushPendingNotifications();}voidnsXULTreeOuterGroupFrame::ScrollToIndex(PRInt32 aRowIndex){  if ( aRowIndex < 0 )    return;      PRInt32 newIndex = aRowIndex;  PRInt32 delta = mCurrentIndex > newIndex ? mCurrentIndex - newIndex : newIndex - mCurrentIndex;  PRBool up = newIndex < mCurrentIndex;  mCurrentIndex = newIndex;  InternalPositionChanged(up, delta);  // This change has to happen immediately.  // Flush any pending reflow commands.  nsCOMPtr<nsIDocument> doc;  mContent->GetDocument(*getter_AddRefs(doc));  doc->FlushPendingNotifications();}// walks the DOM to get the zero-based row index of the current content// note that aContent can be any element, this will get the index of the// element's parentNS_IMETHODIMPnsXULTreeOuterGroupFrame::IndexOfItem(nsIContent* aRoot, nsIContent* aContent,                                      PRBool aDescendIntoRows, // Invariant                                      PRBool aParentIsOpen,                                      PRInt32 *aResult){  PRInt32 childCount=0;  aRoot->ChildCount(childCount);  nsresult rv;    PRInt32 childIndex;  for (childIndex=0; childIndex<childCount; childIndex++) {    nsCOMPtr<nsIContent> child;    aRoot->ChildAt(childIndex, *getter_AddRefs(child));        nsCOMPtr<nsIAtom> childTag;    child->GetTag(*getter_AddRefs(childTag));    // is this it?    if (child.get() == aContent)      return NS_OK;    // we hit a treerow, count it    if (childTag.get() == nsXULAtoms::treeitem)      (*aResult)++;      PRBool descend = PR_TRUE;    PRBool parentIsOpen = aParentIsOpen;    // don't descend into closed children    if (childTag.get() == nsXULAtoms::treechildren && !parentIsOpen)      descend = PR_FALSE;    // speed optimization - descend into rows only when told    else if (childTag.get() == nsXULAtoms::treerow && !aDescendIntoRows)      descend = PR_FALSE;    // descend as normally, but remember that the parent is closed!    else if (childTag.get() == nsXULAtoms::treeitem) {      nsAutoString isOpen;      rv = child->GetAttribute(kNameSpaceID_None, nsXULAtoms::open, isOpen);      if (!isOpen.EqualsWithConversion("true"))        parentIsOpen=PR_FALSE;    }    // now that we've analyzed the tags, recurse    if (descend) {      rv = IndexOfItem(child, aContent,                       aDescendIntoRows, parentIsOpen, aResult);      if (NS_SUCCEEDED(rv))        return NS_OK;    }  }  // not found  return NS_ERROR_FAILURE;}//// Paint//// Overridden to handle the case where we should be drawing the tree as sorted.//NS_IMETHODIMPnsXULTreeOuterGroupFrame :: Paint ( nsIPresContext* aPresContext, nsIRenderingContext& aRenderingContext,                                      const nsRect& aDirtyRect, nsFramePaintLayer aWhichLayer){  nsresult res = NS_OK;  res = nsBoxFrame::Paint ( aPresContext, aRenderingContext, aDirtyRect, aWhichLayer );    if ( (aWhichLayer == eFramePaintLayer_Content) &&        (mYDropLoc != nsTreeItemDragCapturer::kNoDropLoc || mDropOnContainer || mTreeIsSorted) )    PaintDropFeedback ( aPresContext, aRenderingContext, PR_TRUE );  return res;} // Paint//// AttributeChanged//// Track several attributes set by the d&d drop feedback tracking mechanism, notably// telling us to paint as sorted//NS_IMETHODIMPnsXULTreeOuterGroupFrame :: AttributeChanged ( nsIPresContext* aPresContext, nsIContent* aChild,                                                 PRInt32 aNameSpaceID, nsIAtom* aAttribute, PRInt32 aHint){  nsresult rv = NS_OK;     if ( aAttribute == nsXULAtoms::ddTriggerRepaintSorted ) {    // Set a flag so that children won't draw the drop feedback but the parent    // will.    mTreeIsSorted = PR_TRUE;    ForceDrawFrame ( aPresContext, this );    mTreeIsSorted = PR_FALSE;  }  else    rv = nsXULTreeGroupFrame::AttributeChanged ( aPresContext, aChild, aNameSpaceID, aAttribute, aHint );  return rv; } // AttributeChanged#ifdef XP_MAC#pragma mark -#endif//// StopTracking//// Stop tracking auto-scrolling//NS_IMETHODIMP nsXULTreeOuterGroupFrame :: StopTracking ( ){  // turn off capturing of the mouse.  CaptureMouse ( mPresContext, PR_FALSE );  StopAutoScrollTimer ( );  mCurrentlyTrackingAutoScroll = PR_FALSE;    return NS_OK;}//// HandleAutoScrollTracking//// Do all the setup for tracking drag auto-scrolling. This can be called repeatedly, but the// setup will only be done once. Handles capturing the mouse, starting a timer, and registering// ourselves with a manager that will let us know when we're to stop tracking.//nsresultnsXULTreeOuterGroupFrame :: HandleAutoScrollTracking ( const nsPoint & aPoint ){  if ( !mCurrentlyTrackingAutoScroll ) {        CaptureMouse ( mPresContext, PR_TRUE );    // register with the drag auto-scroll manager so we're told when to stop    // tracking    nsCOMPtr<nsIDragService> dragServ ( do_GetService("component://netscape/widget/dragservice") );    if ( dragServ ) {      nsCOMPtr<nsIDragSession> session;      dragServ->GetCurrentSession ( getter_AddRefs(session) );      if ( session )        session->StartTracking(this);    }        mCurrentlyTrackingAutoScroll = PR_TRUE;   // setup complete  }    // kick off our timer  StartAutoScrollTimer ( aPoint, 30 );  return NS_OK;} // HandleAutoScrollTrackingnsresultnsXULTreeOuterGroupFrame::StartAutoScrollTimer(const nsPoint& aPoint, PRUint32 aDelay){  nsresult result;  if (!mAutoScrollTimer) {    result = NS_NewAutoScrollTimer(this, &mAutoScrollTimer);    if (NS_FAILED(result))      return result;    if (!mAutoScrollTimer)      return NS_ERROR_OUT_OF_MEMORY;  }  result = mAutoScrollTimer->SetDelay(aDelay);  if (NS_FAILED(result))    return result;  return DoAutoScroll(aPoint);}nsresultnsXULTreeOuterGroupFrame::StopAutoScrollTimer(){  if (mAutoScrollTimer)    return mAutoScrollTimer->Stop();  return NS_OK;}//// DoAutoScroll//// Given the current mouse position, checks if it is w/in the bounds of the row area// of the tree. If not, scroll up or down in increments of one row.//nsresultnsXULTreeOuterGroupFrame::DoAutoScroll ( const nsPoint& aPoint ){  if ( mAutoScrollTimer )    mAutoScrollTimer->Stop();  float pixelsToTwips = 0.0;  mPresContext->GetPixelsToTwips ( &pixelsToTwips );  nsPoint mouseInTwips ( NSToIntRound(aPoint.x * pixelsToTwips), NSToIntRound(aPoint.y * pixelsToTwips) );    // compute the offset to top level in twips and subtract the offset from  // the mouse coord to put it into our coordinates.  nscoord frameOffsetX = 0, frameOffsetY = 0;  nsIFrame* curr = this;  curr->GetParent(&curr);  while ( curr ) {    nsPoint origin;    curr->GetOrigin(origin);      // in twips        frameOffsetX += origin.x;     // build the offset incrementally    frameOffsetY += origin.y;        curr->GetParent(&curr);       // moving up the chain  } // until we reach the top    mouseInTwips.MoveBy ( -frameOffsetX, -frameOffsetY );  const int kMarginHeight = NSToIntRound ( 12 * pixelsToTwips );  if ( mouseInTwips.x <= 0 || mouseInTwips.x >= mRect.width )    UnregisterTracking();  else {       // scroll up or down, accordingly. if the mouse is outside of the scroll margin, stop the tracking altogether.    PRBool continueTracking = PR_TRUE;    if ( mouseInTwips.y < 0 ) {      if ( mouseInTwips.y > -kMarginHeight )        ScrollToIndex ( mCurrentIndex - 1 );      else {        continueTracking = PR_FALSE;        UnregisterTracking();      }    }    else if ( mouseInTwips.y > GetAvailableHeight() ) {      if ( mouseInTwips.y < GetAvailableHeight() + kMarginHeight )        ScrollToIndex ( mCurrentIndex + 1 );       else {        continueTracking = PR_FALSE;        UnregisterTracking();      }    }    // restart the timer    if ( mAutoScrollTimer && continueTracking )      mAutoScrollTimer->Start(aPoint);  }  return NS_OK;}//// UnregisterTracking//// Tell the drag session that we're done tracking the mouse//voidnsXULTreeOuterGroupFrame :: UnregisterTracking ( ){  nsCOMPtr<nsIDragService> dragService ( do_GetService("component://netscape/widget/dragservice") );  if ( dragService ) {    // tell anyone interested to stop tracking drags    nsCOMPtr<nsIDragSession> session;    dragService->GetCurrentSession ( getter_AddRefs(session) );    if ( session )      session->StopTracking();  }} // UnregisterTracking#ifdef XP_MAC#pragma mark -#endif//// nsDragAutoScrollTimer Impl//NS_IMPL_ISUPPORTS1(nsDragAutoScrollTimer, nsITimerCallback)//// Notify//// Called when the timer fires. Tells the tree to try to scroll.//voidnsDragAutoScrollTimer :: Notify(nsITimer *timer){  mTree->DoAutoScroll(mPoint);}nsresultNS_NewAutoScrollTimer(nsXULTreeOuterGroupFrame* aTree, nsDragAutoScrollTimer **aResult){  if (!aResult)    return NS_ERROR_NULL_POINTER;  *aResult = new nsDragAutoScrollTimer(aTree);  if (!aResult)    return NS_ERROR_OUT_OF_MEMORY;  NS_ADDREF(*aResult);  return NS_OK;}