if (NS_SUCCEEDED(rv = container->GetAttr(kNameSpaceID_None, kStaticsSortLastHintAtom, valueStr))
if (NS_SUCCEEDED(rv = root->GetAttr(kNameSpaceID_None, kStaticsSortLastHintAtom, valueStr))
XULSortServiceImpl::InsertContainerNode(nsIRDFCompositeDataSource *db, nsRDFSortState *sortState, nsIContent *root,					nsIContent *trueParent, nsIContent *container, nsIContent *node, PRBool aNotify){	nsresult	rv;	nsAutoString	sortResource, sortDirection, sortResource2;	_sortStruct	sortInfo;	// get composite db for tree	sortInfo.db = db;	sortInfo.colIndex = -1;	sortInfo.parentContainer = trueParent;	sortInfo.sortProperty = nsnull;	sortInfo.sortProperty2 = nsnull;	sortInfo.inbetweenSeparatorSort = PR_FALSE;	sortInfo.cacheFirstHint = PR_TRUE;	if (sortState->mCache)	{		sortInfo.mInner = sortState->mCache;		// Note: this can/might be null	}	else	{		sortInfo.mInner = nsnull;	}	if (container != sortState->lastContainer.get())	{		sortState->lastContainer = container;		sortState->lastWasFirst = PR_FALSE;		sortState->lastWasLast = PR_FALSE;	}	PRBool			sortInfoAvailable = PR_FALSE;	if (IsTreeElement(root) == PR_TRUE)	{		// tree, so look for treecol/treecolgroup node(s) which provide sorting info		if (NS_SUCCEEDED(rv = GetSortColumnInfo(root, sortResource, sortDirection,			sortResource2, sortInfo.inbetweenSeparatorSort)))		{			sortInfoAvailable = PR_TRUE;		}		else		{			sortDirection.Assign(*naturalStr);		}	}	else	{		// not a tree, so look for sorting info on root node		if (NS_SUCCEEDED(rv = root->GetAttr(kNameSpaceID_None, kSortResourceAtom,			sortResource)) && (rv == NS_CONTENT_ATTR_HAS_VALUE))		{			if (NS_SUCCEEDED(rv = root->GetAttr(kNameSpaceID_None, nsXULAtoms::sortDirection,				sortDirection)) && (rv == NS_CONTENT_ATTR_HAS_VALUE))			{				sortInfoAvailable = PR_TRUE;				if (NS_FAILED(rv = root->GetAttr(kNameSpaceID_None, kSortResource2Atom,					sortResource2)) || (rv != NS_CONTENT_ATTR_HAS_VALUE))				{					sortResource2.Truncate();				}			}		}	}	if (sortInfoAvailable)	{		if (sortState->sortResource.Equals(sortResource) && sortState->sortResource2.Equals(sortResource2))		{			sortInfo.sortProperty = sortState->sortProperty;			sortInfo.sortProperty2 = sortState->sortProperty2;			sortInfo.sortPropertyColl = sortState->sortPropertyColl;			sortInfo.sortPropertyColl2 = sortState->sortPropertyColl2;			sortInfo.sortPropertySort = sortState->sortPropertySort;			sortInfo.sortPropertySort2 = sortState->sortPropertySort2;		}		else		{			nsAutoString	temp;			// either first time, or must have changing sorting info, so flush state cache			sortState->sortProperty = nsnull;	sortState->sortProperty2 = nsnull;			sortState->sortPropertyColl = nsnull;	sortState->sortPropertyColl2 = nsnull;			sortState->sortPropertySort = nsnull;	sortState->sortPropertySort2 = nsnull;			rv = gRDFService->GetUnicodeResource(sortResource.get(), getter_AddRefs(sortInfo.sortProperty));			if (NS_FAILED(rv))	return(rv);			sortState->sortResource = sortResource;			sortState->sortProperty = sortInfo.sortProperty;						temp = sortResource;			temp.Append(NS_LITERAL_STRING("?collation=true"));			rv = gRDFService->GetUnicodeResource(temp.get(), getter_AddRefs(sortInfo.sortPropertyColl));			if (NS_FAILED(rv))	return(rv);			sortState->sortPropertyColl = sortInfo.sortPropertyColl;			temp = sortResource;			temp.Append(NS_LITERAL_STRING("?sort=true"));			rv = gRDFService->GetUnicodeResource(temp.get(), getter_AddRefs(sortInfo.sortPropertySort));			if (NS_FAILED(rv))	return(rv);			sortState->sortPropertySort = sortInfo.sortPropertySort;			if (sortResource2.Length() > 0)			{				rv = gRDFService->GetUnicodeResource(sortResource2.get(), getter_AddRefs(sortInfo.sortProperty2));				if (NS_FAILED(rv))	return(rv);				sortState->sortResource2 = sortResource2;				sortState->sortProperty2 = sortInfo.sortProperty2;				temp = sortResource2;				temp.Append(NS_LITERAL_STRING("?collation=true"));				rv = gRDFService->GetUnicodeResource(temp.get(), getter_AddRefs(sortInfo.sortPropertyColl2));				if (NS_FAILED(rv))	return(rv);				sortState->sortPropertyColl2 = sortInfo.sortPropertyColl2;				temp = sortResource2;				temp.Append(NS_LITERAL_STRING("?sort=true"));				rv = gRDFService->GetUnicodeResource(temp.get(), getter_AddRefs(sortInfo.sortPropertySort2));				if (NS_FAILED(rv))	return(rv);				sortState->sortPropertySort2 = sortInfo.sortPropertySort2;			}		}	}	else	{		// either first time, or must have changing sorting info, so flush state cache		sortState->sortResource.Truncate();		sortState->sortResource2.Truncate();		sortState->sortProperty = nsnull;	sortState->sortProperty2 = nsnull;		sortState->sortPropertyColl = nsnull;	sortState->sortPropertyColl2 = nsnull;		sortState->sortPropertySort = nsnull;	sortState->sortPropertySort2 = nsnull;	}	// set up sort order info	sortInfo.naturalOrderSort = PR_FALSE;	sortInfo.descendingSort = PR_FALSE;	if (sortDirection.Equals(*descendingStr))	{		sortInfo.descendingSort = PR_TRUE;	}	else if (!sortDirection.Equals(*ascendingStr))	{		sortInfo.naturalOrderSort = PR_TRUE;	}	PRBool			isContainerRDFSeq = PR_FALSE;		if ((sortInfo.db) && (sortInfo.naturalOrderSort == PR_TRUE))	{		// walk up the content model to find the REAL		// parent container to determine if its a RDF_Seq		nsCOMPtr<nsIContent>		parent = do_QueryInterface(container, &rv);		nsCOMPtr<nsIContent>		aContent;		nsCOMPtr<nsIDocument>		doc;		if (NS_SUCCEEDED(rv) && parent)		{			rv = parent->GetDocument(*getter_AddRefs(doc));			if (! doc)			{				parent = nsnull;			}		}		if (parent)		{			nsAutoString		id;			nsCOMPtr<nsIAtom>	tag;			if (NS_FAILED(rv = trueParent->GetTag(*getter_AddRefs(tag))))				return(rv);			rv = trueParent->GetAttr(kNameSpaceID_None, nsXULAtoms::ref, id);			if (id.Length() == 0)			{				rv = trueParent->GetAttr(kNameSpaceID_None, nsXULAtoms::id, id);			}			if (id.Length() > 0)			{				nsCOMPtr<nsIRDFResource>	containerRes;				rv = nsXULContentUtils::MakeElementResource(doc, id, getter_AddRefs(containerRes));				if (NS_SUCCEEDED(rv))				{					rv = gRDFC->IsSeq(sortInfo.db, containerRes, 							  &isContainerRDFSeq);				}			}		}	}	PRBool			childAdded = PR_FALSE;	PRInt32			numChildren = 0;	if (NS_FAILED(rv = container->ChildCount(numChildren)))	return(rv);	if ((sortInfo.naturalOrderSort == PR_FALSE) ||		((sortInfo.naturalOrderSort == PR_TRUE) &&		(isContainerRDFSeq == PR_TRUE)))	{		// because numChildren gets modified		PRInt32                 realNumChildren = numChildren;		nsCOMPtr<nsIContent>	child;		// rjc says: determine where static XUL ends and generated XUL/RDF begins		PRInt32			staticCount = 0;		nsAutoString		staticValue;		if (NS_SUCCEEDED(rv = container->GetAttr(kNameSpaceID_None, kStaticHintAtom, staticValue))			&& (rv == NS_CONTENT_ATTR_HAS_VALUE))		{			// found "static" XUL element count hint			PRInt32		strErr=0;			staticCount = staticValue.ToInteger(&strErr);			if (strErr)	staticCount = 0;		}		else		{			// compute the "static" XUL element count			nsAutoString	valueStr;			for (PRInt32 childLoop=0; childLoop<numChildren; childLoop++)			{				container->ChildAt(childLoop, *getter_AddRefs(child));				if (!child)	break;				if (NS_SUCCEEDED(rv = child->GetAttr(kNameSpaceID_None, nsXULAtoms::templateAtom, valueStr))					&& (rv == NS_CONTENT_ATTR_HAS_VALUE))				{					break;				}				else				{					++staticCount;				}			}			if (NS_SUCCEEDED(rv = container->GetAttr(kNameSpaceID_None, kStaticsSortLastHintAtom, valueStr))				&& (rv == NS_CONTENT_ATTR_HAS_VALUE) && (valueStr.EqualsIgnoreCase(*trueStr)))			{				// indicate that static XUL comes after RDF-generated content by making negative				staticCount = -staticCount;			}			// save the "static" XUL element count hint			valueStr.Truncate();			valueStr.AppendInt(staticCount);			container->SetAttr(kNameSpaceID_None, kStaticHintAtom, valueStr, PR_FALSE);		}		if (staticCount <= 0)		{			numChildren += staticCount;			staticCount = 0;		}		else if (staticCount > numChildren)		{			staticCount = numChildren;			numChildren -= staticCount;		}		// figure out where to insert the node when a sort order is being imposed		if (numChildren > 0)		{		        nsIContent		*temp;		        PRInt32			direction;			// rjc says: The following is an implementation of a fairly optimal			// binary search insertion sort... with interpolation at either end-point.			if (sortState->lastWasFirst == PR_TRUE)			{				container->ChildAt(staticCount, *getter_AddRefs(child));				temp = child.get();				direction = inplaceSortCallback(&node, &temp, &sortInfo);				if (direction < 0)				{					container->InsertChildAt(node, staticCount, aNotify, PR_FALSE);					childAdded = PR_TRUE;				}				else				{					sortState->lastWasFirst = PR_FALSE;				}			}			else if (sortState->lastWasLast == PR_TRUE)			{				container->ChildAt(realNumChildren-1, *getter_AddRefs(child));				temp = child.get();				direction = inplaceSortCallback(&node, &temp, &sortInfo);				if (direction > 0)				{					container->InsertChildAt(node, realNumChildren, aNotify,                                             PR_FALSE);					childAdded = PR_TRUE;				}				else				{					sortState->lastWasLast = PR_FALSE;				}			}		        PRInt32	left = staticCount+1, right = realNumChildren, x;		        while ((childAdded == PR_FALSE) && (right >= left))		        {		        	x = (left + right) / 2;				container->ChildAt(x-1, *getter_AddRefs(child));				temp = child.get();				// rjc says: since cacheFirstHint is PR_TRUE, the first node passed				// into inplaceSortCallback() must be the node that doesn't change				direction = inplaceSortCallback(&node, &temp, &sortInfo);				if (((x == left) && (direction < 0)) || (((x == right)) && (direction >= 0)) || (left == right))				{					PRInt32		thePos = ((direction > 0) ? x : x-1);					container->InsertChildAt(node, thePos, aNotify, PR_FALSE);					childAdded = PR_TRUE;										sortState->lastWasFirst = (thePos == staticCount) ? PR_TRUE: PR_FALSE;					sortState->lastWasLast = (thePos >= realNumChildren) ? PR_TRUE: PR_FALSE;										break;				}		        	if (direction < 0)	right = x-1;		        	else			left = x+1;		        }		}	}	if (childAdded == PR_FALSE)	{		container->InsertChildAt(node, numChildren, aNotify, PR_FALSE);	}	if ((!sortState->mCache) && (sortInfo.mInner))	{		sortState->mCache = sortInfo.mInner;	}	return(NS_OK);}