fix how we do sorting in ab view. collation keys are raw data, not PRUnichar *.

NOT PART OF THE BUILD.
This commit is contained in:
sspitzer%netscape.com 2001-11-15 22:16:49 +00:00
Родитель ad08915dd8
Коммит 30eac5d8ce
2 изменённых файлов: 85 добавлений и 51 удалений

Просмотреть файл

@ -125,8 +125,10 @@ nsresult nsAbView::RemoveCardAt(PRInt32 row)
AbCard *abcard = (AbCard*) (mCards.ElementAt(row)); AbCard *abcard = (AbCard*) (mCards.ElementAt(row));
NS_IF_RELEASE(abcard->card); NS_IF_RELEASE(abcard->card);
mCards.RemoveElementAt(row); mCards.RemoveElementAt(row);
PR_FREEIF(abcard->primaryCollationKey); if (abcard->primaryCollationKey)
PR_FREEIF(abcard->secondaryCollationKey); nsMemory::Free(abcard->primaryCollationKey);
if (abcard->secondaryCollationKey)
nsMemory::Free(abcard->secondaryCollationKey);
PR_FREEIF(abcard); PR_FREEIF(abcard);
if (mAbViewListener && !mSuppressCountChange) { if (mAbViewListener && !mSuppressCountChange) {
@ -495,10 +497,14 @@ NS_IMETHODIMP nsAbView::GetCardFromRow(PRInt32 row, nsIAbCard **aCard)
return NS_OK; return NS_OK;
} }
#define DESCENDING_SORT_FACTOR -1
#define ASCENDING_SORT_FACTOR 1
typedef struct SortClosure typedef struct SortClosure
{ {
const PRUnichar *colID; const PRUnichar *colID;
PRInt32 factor; PRInt32 factor;
nsAbView *abView;
} SortClosure; } SortClosure;
static int PR_CALLBACK static int PR_CALLBACK
@ -506,31 +512,44 @@ inplaceSortCallback(const void *data1, const void *data2, void *privateData)
{ {
AbCard *card1 = (AbCard *)data1; AbCard *card1 = (AbCard *)data1;
AbCard *card2 = (AbCard *)data2; AbCard *card2 = (AbCard *)data2;
SortClosure *closure = (SortClosure *) privateData; SortClosure *closure = (SortClosure *) privateData;
PRInt32 sortValue; PRInt32 sortValue;
// if we are sorting the "PrimaryEmail", swap the collation keys, as the secondary is always the // if we are sorting the "PrimaryEmail", swap the collation keys, as the secondary is always the
// PrimaryEmail. use the last primary key as the secondary key. // PrimaryEmail. use the last primary key as the secondary key.
// //
// "Pr" to distinguish "PrimaryEmail" from "PagerNumber" // "Pr" to distinguish "PrimaryEmail" from "PagerNumber"
if (closure->colID[0] == 'P' && closure->colID[1] == 'r') { if (closure->colID[0] == 'P' && closure->colID[1] == 'r') {
sortValue = nsCRT::strcmp(card1->secondaryCollationKey, card2->secondaryCollationKey); sortValue = closure->abView->CompareCollationKeys(card1->secondaryCollationKey,card1->secondaryCollationKeyLen,card2->secondaryCollationKey,card2->secondaryCollationKeyLen);
if (sortValue) if (sortValue)
return sortValue * closure->factor; return sortValue * closure->factor;
else else
return nsCRT::strcmp(card1->primaryCollationKey, card2->primaryCollationKey) * (closure->factor); return closure->abView->CompareCollationKeys(card1->primaryCollationKey,card1->primaryCollationKeyLen,card2->primaryCollationKey,card2->primaryCollationKeyLen) * (closure->factor);
} }
else { else {
sortValue = nsCRT::strcmp(card1->primaryCollationKey, card2->primaryCollationKey); sortValue = closure->abView->CompareCollationKeys(card1->primaryCollationKey,card1->primaryCollationKeyLen,card2->primaryCollationKey,card2->primaryCollationKeyLen);
if (sortValue) if (sortValue)
return sortValue * (closure->factor); return sortValue * (closure->factor);
else else
return nsCRT::strcmp(card1->secondaryCollationKey, card2->secondaryCollationKey) * (closure->factor); return closure->abView->CompareCollationKeys(card1->secondaryCollationKey,card1->secondaryCollationKeyLen,card2->secondaryCollationKey,card2->secondaryCollationKeyLen) * (closure->factor);
} }
} }
static void SetSortClosure(const PRUnichar *sortColumn, const PRUnichar *sortDirection, nsAbView *abView, SortClosure *closure)
{
closure->colID = sortColumn;
if (sortDirection && !nsCRT::strcmp(sortDirection, NS_LITERAL_STRING("descending").get()))
closure->factor = DESCENDING_SORT_FACTOR;
else
closure->factor = ASCENDING_SORT_FACTOR;
closure->abView = abView;
return;
}
NS_IMETHODIMP nsAbView::SortBy(const PRUnichar *colID, const PRUnichar *sortDir) NS_IMETHODIMP nsAbView::SortBy(const PRUnichar *colID, const PRUnichar *sortDir)
{ {
nsresult rv; nsresult rv;
@ -571,20 +590,15 @@ NS_IMETHODIMP nsAbView::SortBy(const PRUnichar *colID, const PRUnichar *sortDir)
NS_ENSURE_SUCCESS(rv,rv); NS_ENSURE_SUCCESS(rv,rv);
} }
SortClosure closure;
closure.colID = sortColumn.get();
closure.factor = 1;
nsAutoString sortDirection; nsAutoString sortDirection;
if (!sortDir) if (!sortDir)
sortDirection = NS_LITERAL_STRING("ascending"); // default direction sortDirection = NS_LITERAL_STRING("ascending").get(); // default direction
else { else
sortDirection = sortDir; sortDirection = sortDir;
if (nsCRT::strcmp(sortDirection.get(), NS_LITERAL_STRING("ascending").get())) {
closure.factor = -1;
}
}
SortClosure closure;
SetSortClosure(sortColumn.get(), sortDirection.get(), this, &closure);
mCards.Sort(inplaceSortCallback, (void *)(&closure)); mCards.Sort(inplaceSortCallback, (void *)(&closure));
mSortColumn = sortColumn.get(); mSortColumn = sortColumn.get();
mSortDirection = sortDirection.get(); mSortDirection = sortDirection.get();
@ -595,6 +609,21 @@ NS_IMETHODIMP nsAbView::SortBy(const PRUnichar *colID, const PRUnichar *sortDir)
return NS_OK; return NS_OK;
} }
PRInt32 nsAbView::CompareCollationKeys(PRUint8 *key1, PRUint32 len1, PRUint8 *key2, PRUint32 len2)
{
NS_ASSERTION(mCollationKeyGenerator, "no key generator");
if (!mCollationKeyGenerator)
return 0;
PRInt32 result;
nsresult rv = mCollationKeyGenerator->CompareRawSortKey(key1,len1,key2,len2,&result);
NS_ASSERTION(NS_SUCCEEDED(rv), "key compare failed");
if (NS_FAILED(rv))
result = 0;
return result;
}
nsresult nsAbView::GenerateCollationKeysForCard(const PRUnichar *colID, AbCard *abcard) nsresult nsAbView::GenerateCollationKeysForCard(const PRUnichar *colID, AbCard *abcard)
{ {
nsresult rv; nsresult rv;
@ -607,8 +636,9 @@ nsresult nsAbView::GenerateCollationKeysForCard(const PRUnichar *colID, AbCard *
NS_ENSURE_SUCCESS(rv,rv); NS_ENSURE_SUCCESS(rv,rv);
// XXX be smarter about the allocation // XXX be smarter about the allocation
PR_FREEIF(abcard->primaryCollationKey); if (abcard->primaryCollationKey)
rv = CreateCollationKey(value, &(abcard->primaryCollationKey)); nsMemory::Free(abcard->primaryCollationKey);
rv = CreateCollationKey(value, &(abcard->primaryCollationKey), &(abcard->primaryCollationKeyLen));
NS_ENSURE_SUCCESS(rv,rv); NS_ENSURE_SUCCESS(rv,rv);
// XXX fix me, do this with const to avoid the strcpy // XXX fix me, do this with const to avoid the strcpy
@ -616,14 +646,18 @@ nsresult nsAbView::GenerateCollationKeysForCard(const PRUnichar *colID, AbCard *
NS_ENSURE_SUCCESS(rv,rv); NS_ENSURE_SUCCESS(rv,rv);
// XXX be smarter about the allocation // XXX be smarter about the allocation
PR_FREEIF(abcard->secondaryCollationKey); if (abcard->secondaryCollationKey)
rv = CreateCollationKey(value, &(abcard->secondaryCollationKey)); nsMemory::Free(abcard->secondaryCollationKey);
rv = CreateCollationKey(value, &(abcard->secondaryCollationKey), &(abcard->secondaryCollationKeyLen));
NS_ENSURE_SUCCESS(rv,rv); NS_ENSURE_SUCCESS(rv,rv);
return rv; return rv;
} }
nsresult nsAbView::CreateCollationKey(const PRUnichar *source, PRUnichar **result) nsresult nsAbView::CreateCollationKey(const PRUnichar *aSource, PRUint8 **aKey, PRUint32 *aKeyLen)
{ {
NS_ENSURE_ARG_POINTER(aKey);
NS_ENSURE_ARG_POINTER(aKeyLen);
nsresult rv; nsresult rv;
if (!mCollationKeyGenerator) if (!mCollationKeyGenerator)
{ {
@ -641,31 +675,22 @@ nsresult nsAbView::CreateCollationKey(const PRUnichar *source, PRUnichar **resu
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }
nsAutoString sourceString(source); // XXX can we avoid this copy?
PRUint32 aLength; nsAutoString sourceString(aSource);
rv = mCollationKeyGenerator->GetSortKeyLen(kCollationCaseInSensitive, sourceString, &aLength); rv = mCollationKeyGenerator->GetSortKeyLen(kCollationCaseInSensitive, sourceString, aKeyLen);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
PRUint8* aKey = (PRUint8* ) nsMemory::Alloc (aLength + 3); // plus three for null termination *aKey = (PRUint8*) nsMemory::Alloc (*aKeyLen);
if (!aKey) if (!aKey)
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
rv = mCollationKeyGenerator->CreateRawSortKey(kCollationCaseInSensitive, rv = mCollationKeyGenerator->CreateRawSortKey(kCollationCaseInSensitive, sourceString, *aKey, aKeyLen);
sourceString, aKey, &aLength);
if (NS_FAILED(rv)) if (NS_FAILED(rv))
{ {
nsMemory::Free (aKey); nsMemory::Free(aKey);
return rv; return rv;
} }
return NS_OK;
// Generate a null terminated unicode string.
// Note using PRUnichar* to store collation key is not recommented since the key may contains 0x0000.
aKey[aLength] = 0;
aKey[aLength+1] = 0;
aKey[aLength+2] = 0;
*result = (PRUnichar *) aKey;
return rv;
} }
NS_IMETHODIMP nsAbView::OnItemAdded(nsISupports *parentDir, nsISupports *item) NS_IMETHODIMP nsAbView::OnItemAdded(nsISupports *parentDir, nsISupports *item)
@ -739,7 +764,7 @@ nsresult nsAbView::AddCard(AbCard *abcard, PRBool selectCardAfterAdding, PRInt32
nsresult rv = NS_OK; nsresult rv = NS_OK;
NS_ENSURE_ARG_POINTER(abcard); NS_ENSURE_ARG_POINTER(abcard);
*index = FindIndexForInsert(mSortColumn.get(), abcard); *index = FindIndexForInsert(abcard);
rv = mCards.InsertElementAt((void *)abcard, *index); rv = mCards.InsertElementAt((void *)abcard, *index);
NS_ENSURE_SUCCESS(rv,rv); NS_ENSURE_SUCCESS(rv,rv);
@ -759,17 +784,20 @@ nsresult nsAbView::AddCard(AbCard *abcard, PRBool selectCardAfterAdding, PRInt32
return rv; return rv;
} }
PRInt32 nsAbView::FindIndexForInsert(const PRUnichar *colID, AbCard *abcard) PRInt32 nsAbView::FindIndexForInsert(AbCard *abcard)
{ {
PRInt32 count = mCards.Count(); PRInt32 count = mCards.Count();
PRInt32 i; PRInt32 i;
void *item = (void *)abcard; void *item = (void *)abcard;
SortClosure closure;
SetSortClosure(mSortColumn.get(), mSortDirection.get(), this, &closure);
// XXX todo, binary search // XXX todo, binary search
for (i=0; i < count; i++) { for (i=0; i < count; i++) {
void *current = mCards.ElementAt(i); void *current = mCards.ElementAt(i);
PRInt32 value = inplaceSortCallback(item, current, (void *)colID); PRInt32 value = inplaceSortCallback(item, current, (void *)(&closure));
// XXX not right, for ascending and descending // XXX not right, for ascending and descending
if (value <= 0) if (value <= 0)
break; break;
@ -860,14 +888,16 @@ NS_IMETHODIMP nsAbView::OnItemPropertyChanged(nsISupports *item, const char *pro
rv = GenerateCollationKeysForCard(mSortColumn.get(), newCard); rv = GenerateCollationKeysForCard(mSortColumn.get(), newCard);
NS_ENSURE_SUCCESS(rv,rv); NS_ENSURE_SUCCESS(rv,rv);
if (!nsCRT::strcmp(newCard->primaryCollationKey, oldCard->primaryCollationKey) && if (!CompareCollationKeys(newCard->primaryCollationKey,newCard->primaryCollationKeyLen,oldCard->primaryCollationKey,oldCard->primaryCollationKeyLen)
!nsCRT::strcmp(newCard->secondaryCollationKey, oldCard->secondaryCollationKey)) { && CompareCollationKeys(newCard->secondaryCollationKey,newCard->secondaryCollationKeyLen,oldCard->secondaryCollationKey,oldCard->secondaryCollationKeyLen)) {
// no need to remove and add, since the collation keys haven't change. // no need to remove and add, since the collation keys haven't change.
// since they haven't chagned, the card will sort to the same place. // since they haven't chagned, the card will sort to the same place.
// we just need to clean up what we allocated. // we just need to clean up what we allocated.
NS_IF_RELEASE(newCard->card); NS_IF_RELEASE(newCard->card);
PR_FREEIF(newCard->primaryCollationKey); if (newCard->primaryCollationKey)
PR_FREEIF(newCard->secondaryCollationKey); nsMemory::Free(newCard->primaryCollationKey);
if (newCard->secondaryCollationKey)
nsMemory::Free(newCard->secondaryCollationKey);
PR_FREEIF(newCard); PR_FREEIF(newCard);
// still need to invalidate, as the other columns may have changed // still need to invalidate, as the other columns may have changed

Просмотреть файл

@ -55,8 +55,10 @@
typedef struct AbCard typedef struct AbCard
{ {
nsIAbCard *card; nsIAbCard *card;
PRUnichar *primaryCollationKey; PRUint32 primaryCollationKeyLen;
PRUnichar *secondaryCollationKey; PRUint32 secondaryCollationKeyLen;
PRUint8 *primaryCollationKey;
PRUint8 *secondaryCollationKey;
} AbCard; } AbCard;
@ -71,12 +73,14 @@ public:
NS_DECL_NSIOUTLINERVIEW NS_DECL_NSIOUTLINERVIEW
NS_DECL_NSIABLISTENER NS_DECL_NSIABLISTENER
NS_DECL_NSIOBSERVER NS_DECL_NSIOBSERVER
PRInt32 CompareCollationKeys(PRUint8 *key1, PRUint32 len1, PRUint8 *key2, PRUint32 len2);
private: private:
nsCOMPtr<nsIOutlinerBoxObject> mOutliner; nsCOMPtr<nsIOutlinerBoxObject> mOutliner;
nsCOMPtr<nsIOutlinerSelection> mOutlinerSelection; nsCOMPtr<nsIOutlinerSelection> mOutlinerSelection;
nsresult CreateCollationKey(const PRUnichar *source, PRUnichar **result); nsresult CreateCollationKey(const PRUnichar *aSource, PRUint8 **aKey, PRUint32 *aKenLen);
PRInt32 FindIndexForInsert(const PRUnichar *colID, AbCard *abcard); PRInt32 FindIndexForInsert(AbCard *abcard);
PRInt32 FindIndexForCard(nsIAbCard *card); PRInt32 FindIndexForCard(nsIAbCard *card);
nsresult GenerateCollationKeysForCard(const PRUnichar *colID, AbCard *abcard); nsresult GenerateCollationKeysForCard(const PRUnichar *colID, AbCard *abcard);
nsresult InvalidateOutliner(PRInt32 row); nsresult InvalidateOutliner(PRInt32 row);