From 6222e5412c791a6096e579ed6e0973193511e92e Mon Sep 17 00:00:00 2001 From: "rjc%netscape.com" Date: Thu, 13 Jan 2000 10:16:32 +0000 Subject: [PATCH] Sorting optimizations. (Sort-of) review by putterman@netscape.com --- .../templates/public/nsIXULSortService.idl | 4 +- .../xul/templates/src/nsXULSortService.cpp | 308 ++++++++++-------- .../templates/src/nsXULTemplateBuilder.cpp | 34 +- rdf/base/idl/nsIXULSortService.idl | 4 +- rdf/content/src/nsRDFGenericBuilder.cpp | 34 +- rdf/content/src/nsXULSortService.cpp | 308 ++++++++++-------- rdf/content/src/nsXULTemplateBuilder.cpp | 34 +- 7 files changed, 417 insertions(+), 309 deletions(-) diff --git a/content/xul/templates/public/nsIXULSortService.idl b/content/xul/templates/public/nsIXULSortService.idl index 0243c476d0c0..bc5f4d56f209 100755 --- a/content/xul/templates/public/nsIXULSortService.idl +++ b/content/xul/templates/public/nsIXULSortService.idl @@ -26,16 +26,16 @@ [ptr] native nsIRDFDataSourceHandle( nsIRDFDataSource *); +interface sortState; interface nsIContent; interface nsIDOMNode; - [scriptable, uuid(BFD05261-834C-11d2-8EAC-00805F29F371)] interface nsIXULSortService : nsISupports { void Sort(in nsIDOMNode node, in string sortResource, in string sortDirection); -[noscript] void InsertContainerNode(in nsIRDFCompositeDataSource db, in nsIRDFDataSourceHandle cacheHandle, in nsIContent root, in nsIContent trueParent, +[noscript] void InsertContainerNode(in nsIRDFCompositeDataSource db, in sortState sortStatePtr, in nsIContent root, in nsIContent trueParent, in nsIContent container, in nsIContent node, in boolean aNotify); }; diff --git a/content/xul/templates/src/nsXULSortService.cpp b/content/xul/templates/src/nsXULSortService.cpp index d91cda562607..b5078de6b93b 100644 --- a/content/xul/templates/src/nsXULSortService.cpp +++ b/content/xul/templates/src/nsXULSortService.cpp @@ -18,6 +18,7 @@ * Rights Reserved. * * Contributor(s): + * Robert John Churchill * Pierre Phaneuf */ @@ -131,10 +132,12 @@ static const char kXULNameSpaceURI[] DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Name); DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, BookmarkSeparator); - typedef struct _sortStruct { - nsCOMPtr sortProperty; - nsCOMPtr sortProperty2; + PRBool firstFlag; + nsCOMPtr sortProperty, sortProperty2; + nsCOMPtr sortPropertyColl, sortPropertyColl2; + nsCOMPtr sortPropertySort, sortPropertySort2; + nsCOMPtr db; nsCOMPtr rdfService; nsCOMPtr mInner; @@ -146,6 +149,7 @@ typedef struct _sortStruct { PRBool descendingSort; PRBool naturalOrderSort; PRBool inbetweenSeparatorSort; + } sortStruct, *sortPtr; @@ -211,10 +215,9 @@ nsresult GetTreeCell(nsIContent *node, PRInt32 colIndex, nsIContent **cell); nsresult SortTreeChildren(nsIContent *container, sortPtr sortInfo); nsresult DoSort(nsIDOMNode* node, const nsString& sortResource, const nsString& sortDirection); -static nsresult GetCachedTarget(sortPtr sortInfo, nsIRDFResource* aSource, nsIRDFResource *aProperty, PRBool aTruthValue, nsIRDFNode **aResult); -static nsresult GetCachedResource(sortPtr sortInfo, nsIRDFResource *sortProperty, const char *suffix, nsIRDFResource **res); -static nsresult GetResourceValue(nsIRDFResource *res1, nsIRDFResource *sortProperty, sortPtr sortInfo, nsIRDFNode **, PRBool &isCollationKey); -static nsresult GetNodeValue(nsIContent *node1, nsIRDFResource *sortProperty, sortPtr sortInfo, nsIRDFNode **, PRBool &isCollationKey); +static nsresult GetCachedTarget(sortPtr sortInfo, PRBool useCache, nsIRDFResource* aSource, nsIRDFResource *aProperty, PRBool aTruthValue, nsIRDFNode **aResult); +static nsresult GetResourceValue(nsIRDFResource *res1, sortPtr sortInfo, PRBool first, PRBool useCache, nsIRDFNode **, PRBool &isCollationKey); +static nsresult GetNodeValue(nsIContent *node1, sortPtr sortInfo, PRBool first, nsIRDFNode **, PRBool &isCollationKey); static nsresult GetTreeCell(sortPtr sortInfo, nsIContent *node, PRInt32 cellIndex, nsIContent **cell); static nsresult GetNodeTextValue(sortPtr sortInfo, nsIContent *node, nsString & val); @@ -628,7 +631,7 @@ XULSortServiceImpl::SetSortHints(nsIContent *tree, const nsString &sortResource, tree->SetAttribute(kNameSpaceID_RDF, kResourceAtom, sortResource, PR_FALSE); if (sortResource2.Length() > 0) - tree->SetAttribute(kNameSpaceID_RDF, kResource2Atom, sortDirection, PR_FALSE); + tree->SetAttribute(kNameSpaceID_RDF, kResource2Atom, sortResource2, PR_FALSE); else tree->UnsetAttribute(kNameSpaceID_RDF, kResource2Atom, PR_FALSE); } else @@ -911,103 +914,37 @@ XULSortServiceImpl::CompareNodes(nsIRDFNode *cellNode1, PRBool isCollationKey1, nsresult -XULSortServiceImpl::GetCachedTarget(sortPtr sortInfo, nsIRDFResource* aSource, +XULSortServiceImpl::GetCachedTarget(sortPtr sortInfo, PRBool useCache, nsIRDFResource* aSource, nsIRDFResource *aProperty, PRBool aTruthValue, nsIRDFNode **aResult) { - nsresult rv = NS_OK, rvTemp; + nsresult rv; + + *aResult = nsnull; if (!(sortInfo->mInner)) { // if we don't have a mInner, create one - rvTemp = nsComponentManager::CreateInstance(kRDFInMemoryDataSourceCID, + rv = nsComponentManager::CreateInstance(kRDFInMemoryDataSourceCID, nsnull, NS_GET_IID(nsIRDFDataSource), (void **)&(sortInfo->mInner)); + if (NS_FAILED(rv)) return(rv); } + + rv = NS_RDF_NO_VALUE; if (sortInfo->mInner) { - // else, if we do have a mInner, look for the resource in it - rv = sortInfo->mInner->GetTarget(aSource, aProperty, aTruthValue, aResult); - } - if (NS_SUCCEEDED(rv) && (rv == NS_RDF_NO_VALUE) && (sortInfo->db)) - { - // if we don't have a cached value, look it up in the document's DB - if (NS_SUCCEEDED(rv = (sortInfo->db)->GetTarget(aSource, aProperty, - aTruthValue, aResult)) && (rv != NS_RDF_NO_VALUE)) + if (useCache == PR_TRUE) { - // and if we have a value, cache it away in our mInner also - rvTemp = sortInfo->mInner->Assert(aSource, aProperty, *aResult, PR_TRUE); + // if we do have a mInner, look for the resource in it + rv = sortInfo->mInner->GetTarget(aSource, aProperty, aTruthValue, aResult); } - } - return(rv); -} - - - -nsresult -XULSortServiceImpl::GetCachedResource(sortPtr sortInfo, nsIRDFResource *sortProperty, const char *suffix, nsIRDFResource **res) -{ - nsresult rv; - - *res = nsnull; - - const char *sortPropertyURI = nsnull; - rv = sortProperty->GetValueConst(&sortPropertyURI); - if (NS_SUCCEEDED(rv) && (sortPropertyURI)) - { - nsAutoString resName(sortPropertyURI); - if (suffix) resName += suffix; - - if (!(sortInfo->resCache)) + else if (sortInfo->db) { - // if we don't have a cache, create one - rv = NS_NewISupportsArray(getter_AddRefs(sortInfo->resCache)); - } - else - { - // else, if we do have a cache, look for the resource in it - PRUint32 numRes; - if (NS_SUCCEEDED(rv = sortInfo->resCache->Count(&numRes))) + // if we don't have a cached value, look it up in the document's DB + if (NS_SUCCEEDED(rv = (sortInfo->db)->GetTarget(aSource, aProperty, + aTruthValue, aResult)) && (rv != NS_RDF_NO_VALUE)) { - PRUint32 loop; - for (loop=0; loop iSupports; - if (NS_SUCCEEDED(rv = sortInfo->resCache->GetElementAt(loop, - getter_AddRefs(iSupports)))) - { - nsCOMPtr aRes = do_QueryInterface(iSupports); - if (aRes) - { - const char *resURI = nsnull; - if (NS_SUCCEEDED(rv = aRes->GetValueConst(&resURI)) && (resURI)) - { - if (resName.Equals(resURI)) - { - // found res in cache, so just return it - *res = aRes; - NS_ADDREF(*res); - break; - } - } - } - } - } - } - } - - if (!(*res)) - { - nsCOMPtr sortRes; - if (NS_SUCCEEDED(rv = sortInfo->rdfService->GetUnicodeResource(resName.GetUnicode(), - getter_AddRefs(sortRes))) && (sortRes)) - { - *res = sortRes; - NS_ADDREF(*res); - - // and add it into the cache array - if (sortInfo->resCache) - { - sortInfo->resCache->AppendElement(sortRes); - } + // and if we have a value, cache it away in our mInner also (ignore errors) + sortInfo->mInner->Assert(aSource, aProperty, *aResult, PR_TRUE); } } } @@ -1017,7 +954,7 @@ XULSortServiceImpl::GetCachedResource(sortPtr sortInfo, nsIRDFResource *sortProp nsresult -XULSortServiceImpl::GetResourceValue(nsIRDFResource *res1, nsIRDFResource *sortProperty, sortPtr sortInfo, +XULSortServiceImpl::GetResourceValue(nsIRDFResource *res1, sortPtr sortInfo, PRBool first, PRBool useCache, nsIRDFNode **target, PRBool &isCollationKey) { nsresult rv = NS_OK; @@ -1025,16 +962,17 @@ XULSortServiceImpl::GetResourceValue(nsIRDFResource *res1, nsIRDFResource *sortP *target = nsnull; isCollationKey = PR_FALSE; - if ((res1) && (sortInfo->naturalOrderSort == PR_FALSE) && (sortInfo->sortProperty)) + if ((res1) && (sortInfo->naturalOrderSort == PR_FALSE)) { nsCOMPtr modSortRes; // for any given property, first ask the graph for its value with "?collation=true" appended // to indicate that if there is a collation key available for this value, we want it - if (NS_SUCCEEDED(rv = GetCachedResource(sortInfo, sortInfo->sortProperty, "?collation=true", - getter_AddRefs(modSortRes))) && (modSortRes)) + + modSortRes = (first) ? sortInfo->sortPropertyColl : sortInfo->sortPropertyColl2; + if (modSortRes) { - if (NS_SUCCEEDED(rv = GetCachedTarget(sortInfo, res1, modSortRes, + if (NS_SUCCEEDED(rv = GetCachedTarget(sortInfo, useCache, res1, modSortRes, PR_TRUE, target)) && (rv != NS_RDF_NO_VALUE)) { isCollationKey = PR_TRUE; @@ -1046,10 +984,10 @@ XULSortServiceImpl::GetResourceValue(nsIRDFResource *res1, nsIRDFResource *sortP // to indicate that if there is any distinction between its display value and sorting // value, we want the sorting value (so that, for example, a mail datasource could strip // off a "Re:" on a mail message subject) - if (NS_SUCCEEDED(rv = GetCachedResource(sortInfo, sortInfo->sortProperty, "?sort=true", - getter_AddRefs(modSortRes))) && (modSortRes)) + modSortRes = (first) ? sortInfo->sortPropertySort : sortInfo->sortPropertySort2; + if (modSortRes) { - if (NS_SUCCEEDED(rv = GetCachedTarget(sortInfo, res1, modSortRes, + if (NS_SUCCEEDED(rv = GetCachedTarget(sortInfo, useCache, res1, modSortRes, PR_TRUE, target)) && (rv != NS_RDF_NO_VALUE)) { } @@ -1058,9 +996,13 @@ XULSortServiceImpl::GetResourceValue(nsIRDFResource *res1, nsIRDFResource *sortP if (!(*target)) { // if no collation key and no special sorting value, just get the property value - if (NS_SUCCEEDED(rv = GetCachedTarget(sortInfo, res1, sortProperty, - PR_TRUE, target) && (rv != NS_RDF_NO_VALUE))) + modSortRes = (first) ? sortInfo->sortProperty : sortInfo->sortProperty2; + if (modSortRes) { + if (NS_SUCCEEDED(rv = GetCachedTarget(sortInfo, useCache, res1, modSortRes, + PR_TRUE, target) && (rv != NS_RDF_NO_VALUE))) + { + } } } } @@ -1070,7 +1012,7 @@ XULSortServiceImpl::GetResourceValue(nsIRDFResource *res1, nsIRDFResource *sortP nsresult -XULSortServiceImpl::GetNodeValue(nsIContent *node1, nsIRDFResource *sortProperty, sortPtr sortInfo, +XULSortServiceImpl::GetNodeValue(nsIContent *node1, sortPtr sortInfo, PRBool first, nsIRDFNode **theNode, PRBool &isCollationKey) { nsresult rv; @@ -1115,7 +1057,11 @@ XULSortServiceImpl::GetNodeValue(nsIContent *node1, nsIRDFResource *sortProperty { if (res1) { - rv = GetResourceValue(res1, sortProperty, sortInfo, theNode, isCollationKey); + rv = GetResourceValue(res1, sortInfo, first, PR_TRUE, theNode, isCollationKey); + if ((rv == NS_RDF_NO_VALUE) || (!*theNode)) + { + rv = GetResourceValue(res1, sortInfo, first, PR_FALSE, theNode, isCollationKey); + } } else { @@ -1247,13 +1193,8 @@ XULSortServiceImpl::InplaceSort(nsIContent *node1, nsIContent *node2, sortPtr so sortOrder = 0; nsCOMPtr cellNode1, cellNode2; - GetNodeValue(node1, sortInfo->sortProperty, sortInfo, getter_AddRefs(cellNode1), isCollationKey1); - GetNodeValue(node2, sortInfo->sortProperty, sortInfo, getter_AddRefs(cellNode2), isCollationKey2); - if ((!cellNode1) && (!cellNode2) && (sortInfo->sortProperty2 == nsnull)) - { - rv = GetNodeValue(node1, kNC_Name, sortInfo, getter_AddRefs(cellNode1), isCollationKey1); - rv = GetNodeValue(node2, kNC_Name, sortInfo, getter_AddRefs(cellNode2), isCollationKey2); - } + GetNodeValue(node1, sortInfo, PR_TRUE, getter_AddRefs(cellNode1), isCollationKey1); + GetNodeValue(node2, sortInfo, PR_TRUE, getter_AddRefs(cellNode2), isCollationKey2); PRBool bothValid = PR_FALSE; rv = CompareNodes(cellNode1, isCollationKey1, cellNode2, isCollationKey2, bothValid, sortOrder); @@ -1263,14 +1204,16 @@ XULSortServiceImpl::InplaceSort(nsIContent *node1, nsIContent *node2, sortPtr so // nodes appear to be equivalent, check for secondary sort criteria if (sortInfo->sortProperty2 != nsnull) { - nsCOMPtr temp = sortInfo->sortProperty; - sortInfo->sortProperty = sortInfo->sortProperty2; - sortInfo->sortProperty2 = nsnull; + cellNode1 = nsnull; + cellNode2 = nsnull; + isCollationKey1 = PR_FALSE; + isCollationKey2 = PR_FALSE; + + GetNodeValue(node1, sortInfo, PR_FALSE, getter_AddRefs(cellNode1), isCollationKey1); + GetNodeValue(node2, sortInfo, PR_FALSE, getter_AddRefs(cellNode2), isCollationKey2); - rv = InplaceSort(node1, node2, sortInfo, sortOrder); - - sortInfo->sortProperty2 = sortInfo->sortProperty; - sortInfo->sortProperty = temp; + bothValid = PR_FALSE; + rv = CompareNodes(cellNode1, isCollationKey1, cellNode2, isCollationKey2, bothValid, sortOrder); } } @@ -1437,9 +1380,24 @@ XULSortServiceImpl::SortTreeChildren(nsIContent *container, sortPtr sortInfo) } +// rjc: yes, I'm lame. For the moment, "class sortState" is defined both here and in +// nsRDFGenericBuilder.cpp so any changes made here must also (exactly) be made there also. + +typedef class sortState +{ +public: + nsAutoString sortResource, sortResource2; + + nsCOMPtr mCache; + nsCOMPtr sortProperty, sortProperty2; + nsCOMPtr sortPropertyColl, sortPropertyColl2; + nsCOMPtr sortPropertySort, sortPropertySort2; +} sortStateClass; + + NS_IMETHODIMP -XULSortServiceImpl::InsertContainerNode(nsIRDFCompositeDataSource *db, nsIRDFDataSource **cacheHandle, nsIContent *root, +XULSortServiceImpl::InsertContainerNode(nsIRDFCompositeDataSource *db, sortState *sortState, nsIContent *root, nsIContent *trueParent, nsIContent *container, nsIContent *node, PRBool aNotify) { nsresult rv; @@ -1457,9 +1415,9 @@ XULSortServiceImpl::InsertContainerNode(nsIRDFCompositeDataSource *db, nsIRDFDat sortInfo.sortProperty = nsnull; sortInfo.sortProperty2 = nsnull; sortInfo.inbetweenSeparatorSort = PR_FALSE; - if (cacheHandle != nsnull) + if (sortState->mCache) { - sortInfo.mInner = *cacheHandle; // Note: this can/might be null + sortInfo.mInner = sortState->mCache; // Note: this can/might be null } else { @@ -1505,13 +1463,71 @@ XULSortServiceImpl::InsertContainerNode(nsIRDFCompositeDataSource *db, nsIRDFDat if (sortInfoAvailable) { - rv = gRDFService->GetUnicodeResource(sortResource.GetUnicode(), getter_AddRefs(sortInfo.sortProperty)); - if (NS_FAILED(rv)) return(rv); - if (sortResource2.Length() > 0) + if (sortState->sortResource.Equals(sortResource) && sortState->sortResource2.Equals(sortResource2)) { - rv = gRDFService->GetUnicodeResource(sortResource2.GetUnicode(), getter_AddRefs(sortInfo.sortProperty2)); - if (NS_FAILED(rv)) return(rv); + 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.GetUnicode(), getter_AddRefs(sortInfo.sortProperty)); + if (NS_FAILED(rv)) return(rv); + sortState->sortResource = sortResource; + sortState->sortProperty = sortInfo.sortProperty; + + temp = sortResource; + temp += "?collation=true"; + rv = gRDFService->GetUnicodeResource(temp.GetUnicode(), getter_AddRefs(sortInfo.sortPropertyColl)); + if (NS_FAILED(rv)) return(rv); + sortState->sortPropertyColl = sortInfo.sortPropertyColl; + + temp = sortResource; + temp += "?sort=true"; + rv = gRDFService->GetUnicodeResource(temp.GetUnicode(), getter_AddRefs(sortInfo.sortPropertySort)); + if (NS_FAILED(rv)) return(rv); + sortState->sortPropertySort = sortInfo.sortPropertySort; + + if (sortResource2.Length() > 0) + { + rv = gRDFService->GetUnicodeResource(sortResource2.GetUnicode(), getter_AddRefs(sortInfo.sortProperty2)); + if (NS_FAILED(rv)) return(rv); + sortState->sortResource2 = sortResource2; + sortState->sortProperty2 = sortInfo.sortProperty2; + + temp = sortResource2; + temp += "?collation=true"; + rv = gRDFService->GetUnicodeResource(temp.GetUnicode(), getter_AddRefs(sortInfo.sortPropertyColl2)); + if (NS_FAILED(rv)) return(rv); + sortState->sortPropertyColl2 = sortInfo.sortPropertyColl2; + + temp = sortResource2; + temp += "?sort=true"; + rv = gRDFService->GetUnicodeResource(temp.GetUnicode(), 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 @@ -1634,10 +1650,9 @@ XULSortServiceImpl::InsertContainerNode(nsIRDFCompositeDataSource *db, nsIRDFDat container->AppendChildTo(node, aNotify); } - if ((cacheHandle) && (sortInfo.mInner) && ((*cacheHandle) != sortInfo.mInner.get())) + if ((!sortState->mCache) && (sortInfo.mInner)) { - *cacheHandle = sortInfo.mInner; - NS_ADDREF(*cacheHandle); + sortState->mCache = sortInfo.mInner; } return(NS_OK); } @@ -1695,10 +1710,6 @@ XULSortServiceImpl::DoSort(nsIDOMNode* node, const nsString& sortResource, sortInfo.kTreeCellAtom = kTreeCellAtom; sortInfo.kNameSpaceID_XUL = kNameSpaceID_XUL; - if (NS_FAILED(rv = gRDFService->GetUnicodeResource(sortResource.GetUnicode(), - getter_AddRefs(sortInfo.sortProperty)))) - return(rv); - // determine new sort resource and direction to use if (sortDirection.EqualsIgnoreCase("natural")) { @@ -1718,6 +1729,37 @@ XULSortServiceImpl::DoSort(nsIDOMNode* node, const nsString& sortResource, PRBool found; if (NS_FAILED(rv = GetSortColumnIndex(treeNode, sortResource, sortDirection, sortResource2, sortInfo.inbetweenSeparatorSort, sortInfo.colIndex, found))) return(rv); + + rv = gRDFService->GetUnicodeResource(sortResource.GetUnicode(), getter_AddRefs(sortInfo.sortProperty)); + if (NS_FAILED(rv)) return(rv); + + nsAutoString temp; + temp = sortResource; + temp += "?collation=true"; + rv = gRDFService->GetUnicodeResource(temp.GetUnicode(), getter_AddRefs(sortInfo.sortPropertyColl)); + if (NS_FAILED(rv)) return(rv); + + temp = sortResource; + temp += "?sort=true"; + rv = gRDFService->GetUnicodeResource(temp.GetUnicode(), getter_AddRefs(sortInfo.sortPropertySort)); + if (NS_FAILED(rv)) return(rv); + + if (sortResource2.Length() > 0) + { + rv = gRDFService->GetUnicodeResource(sortResource2.GetUnicode(), getter_AddRefs(sortInfo.sortProperty2)); + if (NS_FAILED(rv)) return(rv); + + temp = sortResource2; + temp += "?collation=true"; + rv = gRDFService->GetUnicodeResource(temp.GetUnicode(), getter_AddRefs(sortInfo.sortPropertyColl2)); + if (NS_FAILED(rv)) return(rv); + + temp = sortResource2; + temp += "?sort=true"; + rv = gRDFService->GetUnicodeResource(temp.GetUnicode(), getter_AddRefs(sortInfo.sortPropertySort2)); + if (NS_FAILED(rv)) return(rv); + } + SetSortHints(treeNode, sortResource, sortDirection, sortResource2, sortInfo.inbetweenSeparatorSort, found); nsCOMPtr treeBody; @@ -1731,8 +1773,8 @@ XULSortServiceImpl::DoSort(nsIDOMNode* node, const nsString& sortResource, if (NS_FAILED(rv = treeBody->GetParent(*getter_AddRefs(treeParent)))) return(rv); if (NS_FAILED(rv = treeParent->IndexOf(treeBody, treeBodyIndex))) return(rv); if (NS_FAILED(rv = treeParent->RemoveChildAt(treeBodyIndex, PR_TRUE))) return(rv); - if (NS_FAILED(rv = treeParent->AppendChildTo(treeBody, PR_TRUE))) return(rv); + return(NS_OK); } diff --git a/content/xul/templates/src/nsXULTemplateBuilder.cpp b/content/xul/templates/src/nsXULTemplateBuilder.cpp index 2a8ff8af9bd6..8dd86db82cdd 100644 --- a/content/xul/templates/src/nsXULTemplateBuilder.cpp +++ b/content/xul/templates/src/nsXULTemplateBuilder.cpp @@ -118,6 +118,22 @@ static NS_DEFINE_CID(kIHTMLElementFactoryIID, NS_IHTML_ELEMENT_FACTORY_IID); //////////////////////////////////////////////////////////////////////// +// rjc: yes, I'm lame. For the moment, "class sortState" is defined both here and in +// nsXULSortService.cpp so any changes made here must also (exactly) be made there also. + +typedef class sortState +{ +public: + // state match strings + nsAutoString sortResource, sortResource2; + + // state variables + nsCOMPtr mCache; + nsCOMPtr sortProperty, sortProperty2; + nsCOMPtr sortPropertyColl, sortPropertyColl2; + nsCOMPtr sortPropertySort, sortPropertySort2; +} sortStateClass; + class RDFGenericBuilderImpl : public nsIRDFContentModelBuilder, public nsIRDFObserver { @@ -309,7 +325,9 @@ protected: nsCOMPtr mRoot; nsCOMPtr mCache; - nsCOMPtr mTimer; + nsCOMPtr mTimer; + + sortState sortState; // pseudo-constants static nsrefcnt gRefCnt; @@ -2068,18 +2086,8 @@ RDFGenericBuilderImpl::BuildContentFromTemplate(nsIContent *aTemplateNode, if (gXULSortService && isResourceElement) { - if (mCache) - { - rv = gXULSortService->InsertContainerNode(mDB, - (nsIRDFDataSource **)&mCache, - mRoot, trueParent, aRealNode, realKid, aNotify); - } - else - { - rv = gXULSortService->InsertContainerNode(mDB, - getter_AddRefs(mCache), - mRoot, trueParent, aRealNode, realKid, aNotify); - } + rv = gXULSortService->InsertContainerNode(mDB, &sortState, + mRoot, trueParent, aRealNode, realKid, aNotify); } if (NS_FAILED(rv)) { diff --git a/rdf/base/idl/nsIXULSortService.idl b/rdf/base/idl/nsIXULSortService.idl index 0243c476d0c0..bc5f4d56f209 100755 --- a/rdf/base/idl/nsIXULSortService.idl +++ b/rdf/base/idl/nsIXULSortService.idl @@ -26,16 +26,16 @@ [ptr] native nsIRDFDataSourceHandle( nsIRDFDataSource *); +interface sortState; interface nsIContent; interface nsIDOMNode; - [scriptable, uuid(BFD05261-834C-11d2-8EAC-00805F29F371)] interface nsIXULSortService : nsISupports { void Sort(in nsIDOMNode node, in string sortResource, in string sortDirection); -[noscript] void InsertContainerNode(in nsIRDFCompositeDataSource db, in nsIRDFDataSourceHandle cacheHandle, in nsIContent root, in nsIContent trueParent, +[noscript] void InsertContainerNode(in nsIRDFCompositeDataSource db, in sortState sortStatePtr, in nsIContent root, in nsIContent trueParent, in nsIContent container, in nsIContent node, in boolean aNotify); }; diff --git a/rdf/content/src/nsRDFGenericBuilder.cpp b/rdf/content/src/nsRDFGenericBuilder.cpp index 2a8ff8af9bd6..8dd86db82cdd 100644 --- a/rdf/content/src/nsRDFGenericBuilder.cpp +++ b/rdf/content/src/nsRDFGenericBuilder.cpp @@ -118,6 +118,22 @@ static NS_DEFINE_CID(kIHTMLElementFactoryIID, NS_IHTML_ELEMENT_FACTORY_IID); //////////////////////////////////////////////////////////////////////// +// rjc: yes, I'm lame. For the moment, "class sortState" is defined both here and in +// nsXULSortService.cpp so any changes made here must also (exactly) be made there also. + +typedef class sortState +{ +public: + // state match strings + nsAutoString sortResource, sortResource2; + + // state variables + nsCOMPtr mCache; + nsCOMPtr sortProperty, sortProperty2; + nsCOMPtr sortPropertyColl, sortPropertyColl2; + nsCOMPtr sortPropertySort, sortPropertySort2; +} sortStateClass; + class RDFGenericBuilderImpl : public nsIRDFContentModelBuilder, public nsIRDFObserver { @@ -309,7 +325,9 @@ protected: nsCOMPtr mRoot; nsCOMPtr mCache; - nsCOMPtr mTimer; + nsCOMPtr mTimer; + + sortState sortState; // pseudo-constants static nsrefcnt gRefCnt; @@ -2068,18 +2086,8 @@ RDFGenericBuilderImpl::BuildContentFromTemplate(nsIContent *aTemplateNode, if (gXULSortService && isResourceElement) { - if (mCache) - { - rv = gXULSortService->InsertContainerNode(mDB, - (nsIRDFDataSource **)&mCache, - mRoot, trueParent, aRealNode, realKid, aNotify); - } - else - { - rv = gXULSortService->InsertContainerNode(mDB, - getter_AddRefs(mCache), - mRoot, trueParent, aRealNode, realKid, aNotify); - } + rv = gXULSortService->InsertContainerNode(mDB, &sortState, + mRoot, trueParent, aRealNode, realKid, aNotify); } if (NS_FAILED(rv)) { diff --git a/rdf/content/src/nsXULSortService.cpp b/rdf/content/src/nsXULSortService.cpp index d91cda562607..b5078de6b93b 100644 --- a/rdf/content/src/nsXULSortService.cpp +++ b/rdf/content/src/nsXULSortService.cpp @@ -18,6 +18,7 @@ * Rights Reserved. * * Contributor(s): + * Robert John Churchill * Pierre Phaneuf */ @@ -131,10 +132,12 @@ static const char kXULNameSpaceURI[] DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Name); DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, BookmarkSeparator); - typedef struct _sortStruct { - nsCOMPtr sortProperty; - nsCOMPtr sortProperty2; + PRBool firstFlag; + nsCOMPtr sortProperty, sortProperty2; + nsCOMPtr sortPropertyColl, sortPropertyColl2; + nsCOMPtr sortPropertySort, sortPropertySort2; + nsCOMPtr db; nsCOMPtr rdfService; nsCOMPtr mInner; @@ -146,6 +149,7 @@ typedef struct _sortStruct { PRBool descendingSort; PRBool naturalOrderSort; PRBool inbetweenSeparatorSort; + } sortStruct, *sortPtr; @@ -211,10 +215,9 @@ nsresult GetTreeCell(nsIContent *node, PRInt32 colIndex, nsIContent **cell); nsresult SortTreeChildren(nsIContent *container, sortPtr sortInfo); nsresult DoSort(nsIDOMNode* node, const nsString& sortResource, const nsString& sortDirection); -static nsresult GetCachedTarget(sortPtr sortInfo, nsIRDFResource* aSource, nsIRDFResource *aProperty, PRBool aTruthValue, nsIRDFNode **aResult); -static nsresult GetCachedResource(sortPtr sortInfo, nsIRDFResource *sortProperty, const char *suffix, nsIRDFResource **res); -static nsresult GetResourceValue(nsIRDFResource *res1, nsIRDFResource *sortProperty, sortPtr sortInfo, nsIRDFNode **, PRBool &isCollationKey); -static nsresult GetNodeValue(nsIContent *node1, nsIRDFResource *sortProperty, sortPtr sortInfo, nsIRDFNode **, PRBool &isCollationKey); +static nsresult GetCachedTarget(sortPtr sortInfo, PRBool useCache, nsIRDFResource* aSource, nsIRDFResource *aProperty, PRBool aTruthValue, nsIRDFNode **aResult); +static nsresult GetResourceValue(nsIRDFResource *res1, sortPtr sortInfo, PRBool first, PRBool useCache, nsIRDFNode **, PRBool &isCollationKey); +static nsresult GetNodeValue(nsIContent *node1, sortPtr sortInfo, PRBool first, nsIRDFNode **, PRBool &isCollationKey); static nsresult GetTreeCell(sortPtr sortInfo, nsIContent *node, PRInt32 cellIndex, nsIContent **cell); static nsresult GetNodeTextValue(sortPtr sortInfo, nsIContent *node, nsString & val); @@ -628,7 +631,7 @@ XULSortServiceImpl::SetSortHints(nsIContent *tree, const nsString &sortResource, tree->SetAttribute(kNameSpaceID_RDF, kResourceAtom, sortResource, PR_FALSE); if (sortResource2.Length() > 0) - tree->SetAttribute(kNameSpaceID_RDF, kResource2Atom, sortDirection, PR_FALSE); + tree->SetAttribute(kNameSpaceID_RDF, kResource2Atom, sortResource2, PR_FALSE); else tree->UnsetAttribute(kNameSpaceID_RDF, kResource2Atom, PR_FALSE); } else @@ -911,103 +914,37 @@ XULSortServiceImpl::CompareNodes(nsIRDFNode *cellNode1, PRBool isCollationKey1, nsresult -XULSortServiceImpl::GetCachedTarget(sortPtr sortInfo, nsIRDFResource* aSource, +XULSortServiceImpl::GetCachedTarget(sortPtr sortInfo, PRBool useCache, nsIRDFResource* aSource, nsIRDFResource *aProperty, PRBool aTruthValue, nsIRDFNode **aResult) { - nsresult rv = NS_OK, rvTemp; + nsresult rv; + + *aResult = nsnull; if (!(sortInfo->mInner)) { // if we don't have a mInner, create one - rvTemp = nsComponentManager::CreateInstance(kRDFInMemoryDataSourceCID, + rv = nsComponentManager::CreateInstance(kRDFInMemoryDataSourceCID, nsnull, NS_GET_IID(nsIRDFDataSource), (void **)&(sortInfo->mInner)); + if (NS_FAILED(rv)) return(rv); } + + rv = NS_RDF_NO_VALUE; if (sortInfo->mInner) { - // else, if we do have a mInner, look for the resource in it - rv = sortInfo->mInner->GetTarget(aSource, aProperty, aTruthValue, aResult); - } - if (NS_SUCCEEDED(rv) && (rv == NS_RDF_NO_VALUE) && (sortInfo->db)) - { - // if we don't have a cached value, look it up in the document's DB - if (NS_SUCCEEDED(rv = (sortInfo->db)->GetTarget(aSource, aProperty, - aTruthValue, aResult)) && (rv != NS_RDF_NO_VALUE)) + if (useCache == PR_TRUE) { - // and if we have a value, cache it away in our mInner also - rvTemp = sortInfo->mInner->Assert(aSource, aProperty, *aResult, PR_TRUE); + // if we do have a mInner, look for the resource in it + rv = sortInfo->mInner->GetTarget(aSource, aProperty, aTruthValue, aResult); } - } - return(rv); -} - - - -nsresult -XULSortServiceImpl::GetCachedResource(sortPtr sortInfo, nsIRDFResource *sortProperty, const char *suffix, nsIRDFResource **res) -{ - nsresult rv; - - *res = nsnull; - - const char *sortPropertyURI = nsnull; - rv = sortProperty->GetValueConst(&sortPropertyURI); - if (NS_SUCCEEDED(rv) && (sortPropertyURI)) - { - nsAutoString resName(sortPropertyURI); - if (suffix) resName += suffix; - - if (!(sortInfo->resCache)) + else if (sortInfo->db) { - // if we don't have a cache, create one - rv = NS_NewISupportsArray(getter_AddRefs(sortInfo->resCache)); - } - else - { - // else, if we do have a cache, look for the resource in it - PRUint32 numRes; - if (NS_SUCCEEDED(rv = sortInfo->resCache->Count(&numRes))) + // if we don't have a cached value, look it up in the document's DB + if (NS_SUCCEEDED(rv = (sortInfo->db)->GetTarget(aSource, aProperty, + aTruthValue, aResult)) && (rv != NS_RDF_NO_VALUE)) { - PRUint32 loop; - for (loop=0; loop iSupports; - if (NS_SUCCEEDED(rv = sortInfo->resCache->GetElementAt(loop, - getter_AddRefs(iSupports)))) - { - nsCOMPtr aRes = do_QueryInterface(iSupports); - if (aRes) - { - const char *resURI = nsnull; - if (NS_SUCCEEDED(rv = aRes->GetValueConst(&resURI)) && (resURI)) - { - if (resName.Equals(resURI)) - { - // found res in cache, so just return it - *res = aRes; - NS_ADDREF(*res); - break; - } - } - } - } - } - } - } - - if (!(*res)) - { - nsCOMPtr sortRes; - if (NS_SUCCEEDED(rv = sortInfo->rdfService->GetUnicodeResource(resName.GetUnicode(), - getter_AddRefs(sortRes))) && (sortRes)) - { - *res = sortRes; - NS_ADDREF(*res); - - // and add it into the cache array - if (sortInfo->resCache) - { - sortInfo->resCache->AppendElement(sortRes); - } + // and if we have a value, cache it away in our mInner also (ignore errors) + sortInfo->mInner->Assert(aSource, aProperty, *aResult, PR_TRUE); } } } @@ -1017,7 +954,7 @@ XULSortServiceImpl::GetCachedResource(sortPtr sortInfo, nsIRDFResource *sortProp nsresult -XULSortServiceImpl::GetResourceValue(nsIRDFResource *res1, nsIRDFResource *sortProperty, sortPtr sortInfo, +XULSortServiceImpl::GetResourceValue(nsIRDFResource *res1, sortPtr sortInfo, PRBool first, PRBool useCache, nsIRDFNode **target, PRBool &isCollationKey) { nsresult rv = NS_OK; @@ -1025,16 +962,17 @@ XULSortServiceImpl::GetResourceValue(nsIRDFResource *res1, nsIRDFResource *sortP *target = nsnull; isCollationKey = PR_FALSE; - if ((res1) && (sortInfo->naturalOrderSort == PR_FALSE) && (sortInfo->sortProperty)) + if ((res1) && (sortInfo->naturalOrderSort == PR_FALSE)) { nsCOMPtr modSortRes; // for any given property, first ask the graph for its value with "?collation=true" appended // to indicate that if there is a collation key available for this value, we want it - if (NS_SUCCEEDED(rv = GetCachedResource(sortInfo, sortInfo->sortProperty, "?collation=true", - getter_AddRefs(modSortRes))) && (modSortRes)) + + modSortRes = (first) ? sortInfo->sortPropertyColl : sortInfo->sortPropertyColl2; + if (modSortRes) { - if (NS_SUCCEEDED(rv = GetCachedTarget(sortInfo, res1, modSortRes, + if (NS_SUCCEEDED(rv = GetCachedTarget(sortInfo, useCache, res1, modSortRes, PR_TRUE, target)) && (rv != NS_RDF_NO_VALUE)) { isCollationKey = PR_TRUE; @@ -1046,10 +984,10 @@ XULSortServiceImpl::GetResourceValue(nsIRDFResource *res1, nsIRDFResource *sortP // to indicate that if there is any distinction between its display value and sorting // value, we want the sorting value (so that, for example, a mail datasource could strip // off a "Re:" on a mail message subject) - if (NS_SUCCEEDED(rv = GetCachedResource(sortInfo, sortInfo->sortProperty, "?sort=true", - getter_AddRefs(modSortRes))) && (modSortRes)) + modSortRes = (first) ? sortInfo->sortPropertySort : sortInfo->sortPropertySort2; + if (modSortRes) { - if (NS_SUCCEEDED(rv = GetCachedTarget(sortInfo, res1, modSortRes, + if (NS_SUCCEEDED(rv = GetCachedTarget(sortInfo, useCache, res1, modSortRes, PR_TRUE, target)) && (rv != NS_RDF_NO_VALUE)) { } @@ -1058,9 +996,13 @@ XULSortServiceImpl::GetResourceValue(nsIRDFResource *res1, nsIRDFResource *sortP if (!(*target)) { // if no collation key and no special sorting value, just get the property value - if (NS_SUCCEEDED(rv = GetCachedTarget(sortInfo, res1, sortProperty, - PR_TRUE, target) && (rv != NS_RDF_NO_VALUE))) + modSortRes = (first) ? sortInfo->sortProperty : sortInfo->sortProperty2; + if (modSortRes) { + if (NS_SUCCEEDED(rv = GetCachedTarget(sortInfo, useCache, res1, modSortRes, + PR_TRUE, target) && (rv != NS_RDF_NO_VALUE))) + { + } } } } @@ -1070,7 +1012,7 @@ XULSortServiceImpl::GetResourceValue(nsIRDFResource *res1, nsIRDFResource *sortP nsresult -XULSortServiceImpl::GetNodeValue(nsIContent *node1, nsIRDFResource *sortProperty, sortPtr sortInfo, +XULSortServiceImpl::GetNodeValue(nsIContent *node1, sortPtr sortInfo, PRBool first, nsIRDFNode **theNode, PRBool &isCollationKey) { nsresult rv; @@ -1115,7 +1057,11 @@ XULSortServiceImpl::GetNodeValue(nsIContent *node1, nsIRDFResource *sortProperty { if (res1) { - rv = GetResourceValue(res1, sortProperty, sortInfo, theNode, isCollationKey); + rv = GetResourceValue(res1, sortInfo, first, PR_TRUE, theNode, isCollationKey); + if ((rv == NS_RDF_NO_VALUE) || (!*theNode)) + { + rv = GetResourceValue(res1, sortInfo, first, PR_FALSE, theNode, isCollationKey); + } } else { @@ -1247,13 +1193,8 @@ XULSortServiceImpl::InplaceSort(nsIContent *node1, nsIContent *node2, sortPtr so sortOrder = 0; nsCOMPtr cellNode1, cellNode2; - GetNodeValue(node1, sortInfo->sortProperty, sortInfo, getter_AddRefs(cellNode1), isCollationKey1); - GetNodeValue(node2, sortInfo->sortProperty, sortInfo, getter_AddRefs(cellNode2), isCollationKey2); - if ((!cellNode1) && (!cellNode2) && (sortInfo->sortProperty2 == nsnull)) - { - rv = GetNodeValue(node1, kNC_Name, sortInfo, getter_AddRefs(cellNode1), isCollationKey1); - rv = GetNodeValue(node2, kNC_Name, sortInfo, getter_AddRefs(cellNode2), isCollationKey2); - } + GetNodeValue(node1, sortInfo, PR_TRUE, getter_AddRefs(cellNode1), isCollationKey1); + GetNodeValue(node2, sortInfo, PR_TRUE, getter_AddRefs(cellNode2), isCollationKey2); PRBool bothValid = PR_FALSE; rv = CompareNodes(cellNode1, isCollationKey1, cellNode2, isCollationKey2, bothValid, sortOrder); @@ -1263,14 +1204,16 @@ XULSortServiceImpl::InplaceSort(nsIContent *node1, nsIContent *node2, sortPtr so // nodes appear to be equivalent, check for secondary sort criteria if (sortInfo->sortProperty2 != nsnull) { - nsCOMPtr temp = sortInfo->sortProperty; - sortInfo->sortProperty = sortInfo->sortProperty2; - sortInfo->sortProperty2 = nsnull; + cellNode1 = nsnull; + cellNode2 = nsnull; + isCollationKey1 = PR_FALSE; + isCollationKey2 = PR_FALSE; + + GetNodeValue(node1, sortInfo, PR_FALSE, getter_AddRefs(cellNode1), isCollationKey1); + GetNodeValue(node2, sortInfo, PR_FALSE, getter_AddRefs(cellNode2), isCollationKey2); - rv = InplaceSort(node1, node2, sortInfo, sortOrder); - - sortInfo->sortProperty2 = sortInfo->sortProperty; - sortInfo->sortProperty = temp; + bothValid = PR_FALSE; + rv = CompareNodes(cellNode1, isCollationKey1, cellNode2, isCollationKey2, bothValid, sortOrder); } } @@ -1437,9 +1380,24 @@ XULSortServiceImpl::SortTreeChildren(nsIContent *container, sortPtr sortInfo) } +// rjc: yes, I'm lame. For the moment, "class sortState" is defined both here and in +// nsRDFGenericBuilder.cpp so any changes made here must also (exactly) be made there also. + +typedef class sortState +{ +public: + nsAutoString sortResource, sortResource2; + + nsCOMPtr mCache; + nsCOMPtr sortProperty, sortProperty2; + nsCOMPtr sortPropertyColl, sortPropertyColl2; + nsCOMPtr sortPropertySort, sortPropertySort2; +} sortStateClass; + + NS_IMETHODIMP -XULSortServiceImpl::InsertContainerNode(nsIRDFCompositeDataSource *db, nsIRDFDataSource **cacheHandle, nsIContent *root, +XULSortServiceImpl::InsertContainerNode(nsIRDFCompositeDataSource *db, sortState *sortState, nsIContent *root, nsIContent *trueParent, nsIContent *container, nsIContent *node, PRBool aNotify) { nsresult rv; @@ -1457,9 +1415,9 @@ XULSortServiceImpl::InsertContainerNode(nsIRDFCompositeDataSource *db, nsIRDFDat sortInfo.sortProperty = nsnull; sortInfo.sortProperty2 = nsnull; sortInfo.inbetweenSeparatorSort = PR_FALSE; - if (cacheHandle != nsnull) + if (sortState->mCache) { - sortInfo.mInner = *cacheHandle; // Note: this can/might be null + sortInfo.mInner = sortState->mCache; // Note: this can/might be null } else { @@ -1505,13 +1463,71 @@ XULSortServiceImpl::InsertContainerNode(nsIRDFCompositeDataSource *db, nsIRDFDat if (sortInfoAvailable) { - rv = gRDFService->GetUnicodeResource(sortResource.GetUnicode(), getter_AddRefs(sortInfo.sortProperty)); - if (NS_FAILED(rv)) return(rv); - if (sortResource2.Length() > 0) + if (sortState->sortResource.Equals(sortResource) && sortState->sortResource2.Equals(sortResource2)) { - rv = gRDFService->GetUnicodeResource(sortResource2.GetUnicode(), getter_AddRefs(sortInfo.sortProperty2)); - if (NS_FAILED(rv)) return(rv); + 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.GetUnicode(), getter_AddRefs(sortInfo.sortProperty)); + if (NS_FAILED(rv)) return(rv); + sortState->sortResource = sortResource; + sortState->sortProperty = sortInfo.sortProperty; + + temp = sortResource; + temp += "?collation=true"; + rv = gRDFService->GetUnicodeResource(temp.GetUnicode(), getter_AddRefs(sortInfo.sortPropertyColl)); + if (NS_FAILED(rv)) return(rv); + sortState->sortPropertyColl = sortInfo.sortPropertyColl; + + temp = sortResource; + temp += "?sort=true"; + rv = gRDFService->GetUnicodeResource(temp.GetUnicode(), getter_AddRefs(sortInfo.sortPropertySort)); + if (NS_FAILED(rv)) return(rv); + sortState->sortPropertySort = sortInfo.sortPropertySort; + + if (sortResource2.Length() > 0) + { + rv = gRDFService->GetUnicodeResource(sortResource2.GetUnicode(), getter_AddRefs(sortInfo.sortProperty2)); + if (NS_FAILED(rv)) return(rv); + sortState->sortResource2 = sortResource2; + sortState->sortProperty2 = sortInfo.sortProperty2; + + temp = sortResource2; + temp += "?collation=true"; + rv = gRDFService->GetUnicodeResource(temp.GetUnicode(), getter_AddRefs(sortInfo.sortPropertyColl2)); + if (NS_FAILED(rv)) return(rv); + sortState->sortPropertyColl2 = sortInfo.sortPropertyColl2; + + temp = sortResource2; + temp += "?sort=true"; + rv = gRDFService->GetUnicodeResource(temp.GetUnicode(), 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 @@ -1634,10 +1650,9 @@ XULSortServiceImpl::InsertContainerNode(nsIRDFCompositeDataSource *db, nsIRDFDat container->AppendChildTo(node, aNotify); } - if ((cacheHandle) && (sortInfo.mInner) && ((*cacheHandle) != sortInfo.mInner.get())) + if ((!sortState->mCache) && (sortInfo.mInner)) { - *cacheHandle = sortInfo.mInner; - NS_ADDREF(*cacheHandle); + sortState->mCache = sortInfo.mInner; } return(NS_OK); } @@ -1695,10 +1710,6 @@ XULSortServiceImpl::DoSort(nsIDOMNode* node, const nsString& sortResource, sortInfo.kTreeCellAtom = kTreeCellAtom; sortInfo.kNameSpaceID_XUL = kNameSpaceID_XUL; - if (NS_FAILED(rv = gRDFService->GetUnicodeResource(sortResource.GetUnicode(), - getter_AddRefs(sortInfo.sortProperty)))) - return(rv); - // determine new sort resource and direction to use if (sortDirection.EqualsIgnoreCase("natural")) { @@ -1718,6 +1729,37 @@ XULSortServiceImpl::DoSort(nsIDOMNode* node, const nsString& sortResource, PRBool found; if (NS_FAILED(rv = GetSortColumnIndex(treeNode, sortResource, sortDirection, sortResource2, sortInfo.inbetweenSeparatorSort, sortInfo.colIndex, found))) return(rv); + + rv = gRDFService->GetUnicodeResource(sortResource.GetUnicode(), getter_AddRefs(sortInfo.sortProperty)); + if (NS_FAILED(rv)) return(rv); + + nsAutoString temp; + temp = sortResource; + temp += "?collation=true"; + rv = gRDFService->GetUnicodeResource(temp.GetUnicode(), getter_AddRefs(sortInfo.sortPropertyColl)); + if (NS_FAILED(rv)) return(rv); + + temp = sortResource; + temp += "?sort=true"; + rv = gRDFService->GetUnicodeResource(temp.GetUnicode(), getter_AddRefs(sortInfo.sortPropertySort)); + if (NS_FAILED(rv)) return(rv); + + if (sortResource2.Length() > 0) + { + rv = gRDFService->GetUnicodeResource(sortResource2.GetUnicode(), getter_AddRefs(sortInfo.sortProperty2)); + if (NS_FAILED(rv)) return(rv); + + temp = sortResource2; + temp += "?collation=true"; + rv = gRDFService->GetUnicodeResource(temp.GetUnicode(), getter_AddRefs(sortInfo.sortPropertyColl2)); + if (NS_FAILED(rv)) return(rv); + + temp = sortResource2; + temp += "?sort=true"; + rv = gRDFService->GetUnicodeResource(temp.GetUnicode(), getter_AddRefs(sortInfo.sortPropertySort2)); + if (NS_FAILED(rv)) return(rv); + } + SetSortHints(treeNode, sortResource, sortDirection, sortResource2, sortInfo.inbetweenSeparatorSort, found); nsCOMPtr treeBody; @@ -1731,8 +1773,8 @@ XULSortServiceImpl::DoSort(nsIDOMNode* node, const nsString& sortResource, if (NS_FAILED(rv = treeBody->GetParent(*getter_AddRefs(treeParent)))) return(rv); if (NS_FAILED(rv = treeParent->IndexOf(treeBody, treeBodyIndex))) return(rv); if (NS_FAILED(rv = treeParent->RemoveChildAt(treeBodyIndex, PR_TRUE))) return(rv); - if (NS_FAILED(rv = treeParent->AppendChildTo(treeBody, PR_TRUE))) return(rv); + return(NS_OK); } diff --git a/rdf/content/src/nsXULTemplateBuilder.cpp b/rdf/content/src/nsXULTemplateBuilder.cpp index 2a8ff8af9bd6..8dd86db82cdd 100644 --- a/rdf/content/src/nsXULTemplateBuilder.cpp +++ b/rdf/content/src/nsXULTemplateBuilder.cpp @@ -118,6 +118,22 @@ static NS_DEFINE_CID(kIHTMLElementFactoryIID, NS_IHTML_ELEMENT_FACTORY_IID); //////////////////////////////////////////////////////////////////////// +// rjc: yes, I'm lame. For the moment, "class sortState" is defined both here and in +// nsXULSortService.cpp so any changes made here must also (exactly) be made there also. + +typedef class sortState +{ +public: + // state match strings + nsAutoString sortResource, sortResource2; + + // state variables + nsCOMPtr mCache; + nsCOMPtr sortProperty, sortProperty2; + nsCOMPtr sortPropertyColl, sortPropertyColl2; + nsCOMPtr sortPropertySort, sortPropertySort2; +} sortStateClass; + class RDFGenericBuilderImpl : public nsIRDFContentModelBuilder, public nsIRDFObserver { @@ -309,7 +325,9 @@ protected: nsCOMPtr mRoot; nsCOMPtr mCache; - nsCOMPtr mTimer; + nsCOMPtr mTimer; + + sortState sortState; // pseudo-constants static nsrefcnt gRefCnt; @@ -2068,18 +2086,8 @@ RDFGenericBuilderImpl::BuildContentFromTemplate(nsIContent *aTemplateNode, if (gXULSortService && isResourceElement) { - if (mCache) - { - rv = gXULSortService->InsertContainerNode(mDB, - (nsIRDFDataSource **)&mCache, - mRoot, trueParent, aRealNode, realKid, aNotify); - } - else - { - rv = gXULSortService->InsertContainerNode(mDB, - getter_AddRefs(mCache), - mRoot, trueParent, aRealNode, realKid, aNotify); - } + rv = gXULSortService->InsertContainerNode(mDB, &sortState, + mRoot, trueParent, aRealNode, realKid, aNotify); } if (NS_FAILED(rv)) {