rv = parent->GetDocument(*getter_AddRefs(doc));
rv = parent->GetDocument(getter_AddRefs(doc));
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.parentContainer = trueParent;  sortInfo.sortProperty = nsnull;  sortInfo.sortProperty2 = nsnull;  sortInfo.inbetweenSeparatorSort = PR_FALSE;  sortInfo.cacheFirstHint = PR_TRUE;  if (sortState->mCache)	sortInfo.mInner = sortState->mCache;  else	sortInfo.mInner = nsnull;  if (container != sortState->lastContainer.get()) {    sortState->lastContainer = container;    sortState->lastWasFirst = PR_FALSE;    sortState->lastWasLast = PR_FALSE;  }  PRBool sortInfoAvailable = PR_FALSE;  // look for sorting info on root node  if (NS_SUCCEEDED(rv = root->GetAttr(kNameSpaceID_None, nsXULAtoms::sortResource, 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, nsXULAtoms::sortResource2, 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 {      // 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, getter_AddRefs(sortInfo.sortProperty));      if (NS_FAILED(rv)) return rv;      sortState->sortResource = sortResource;      sortState->sortProperty = sortInfo.sortProperty;            nsAutoString resourceUrl = sortResource;      resourceUrl.Append(NS_LITERAL_STRING("?collation=true"));      rv = gRDFService->GetUnicodeResource(resourceUrl, getter_AddRefs(sortInfo.sortPropertyColl));      if (NS_FAILED(rv)) return rv;      sortState->sortPropertyColl = sortInfo.sortPropertyColl;      resourceUrl = sortResource;      resourceUrl.Append(NS_LITERAL_STRING("?sort=true"));      rv = gRDFService->GetUnicodeResource(resourceUrl, getter_AddRefs(sortInfo.sortPropertySort));      if (NS_FAILED(rv)) return rv;      sortState->sortPropertySort = sortInfo.sortPropertySort;      if (!sortResource2.IsEmpty()) {        rv = gRDFService->GetUnicodeResource(sortResource2, getter_AddRefs(sortInfo.sortProperty2));        if (NS_FAILED(rv)) return rv;        sortState->sortResource2 = sortResource2;        sortState->sortProperty2 = sortInfo.sortProperty2;        resourceUrl = sortResource2;        resourceUrl.Append(NS_LITERAL_STRING("?collation=true"));        rv = gRDFService->GetUnicodeResource(resourceUrl, getter_AddRefs(sortInfo.sortPropertyColl2));        if (NS_FAILED(rv)) return rv;        sortState->sortPropertyColl2 = sortInfo.sortPropertyColl2;        resourceUrl = sortResource2;        resourceUrl.Append(NS_LITERAL_STRING("?sort=true"));        rv = gRDFService->GetUnicodeResource(resourceUrl, 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(*kDescendingStr))    sortInfo.descendingSort = PR_TRUE;  else if (!sortDirection.Equals(*kAscendingStr))    sortInfo.naturalOrderSort = PR_TRUE;  PRBool isContainerRDFSeq = PR_FALSE;    if (sortInfo.db && sortInfo.naturalOrderSort) {    // 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.IsEmpty())        rv = trueParent->GetAttr(kNameSpaceID_None, nsXULAtoms::id, id);      if (!id.IsEmpty()) {        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, nsXULAtoms::staticHint, 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 = root->GetAttr(kNameSpaceID_None, nsXULAtoms::sortStaticsLast, valueStr))          && (rv == NS_CONTENT_ATTR_HAS_VALUE) && (valueStr.EqualsIgnoreCase("true")))      {        // 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, nsXULAtoms::staticHint, 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) {        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) {        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 && 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)    container->InsertChildAt(node, numChildren, aNotify, PR_FALSE);  if (!sortState->mCache && sortInfo.mInner)    sortState->mCache = sortInfo.mInner;  return NS_OK;}