зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
ad08915dd8
Коммит
30eac5d8ce
|
@ -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
|
||||||
|
@ -516,21 +522,34 @@ inplaceSortCallback(const void *data1, const void *data2, void *privateData)
|
||||||
//
|
//
|
||||||
// "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,19 +590,14 @@ 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();
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,11 +74,13 @@ public:
|
||||||
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);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче