int CMuleListCtrl::CompareItems(wxUIntPtr item1, wxUIntPtr item2)
{
	CSortingList::const_iterator it = m_sort_orders.begin();
	for (; it != m_sort_orders.end(); ++it) {
		int result = m_sort_func(item1, item2, it->first | it->second);
		if (result != 0) {
			return result;
		}
	}

	// Ensure that different items are never considered equal.
	return CmpAny(item1, item2);
}
// Comparison function needed by sort. Returns true if file1 preceeds file2
bool ComparePartFiles(const CPartFile* file1, const CPartFile* file2) {
	if (file1->GetDownPriority() != file2->GetDownPriority()) {
		// To place high-priority files before low priority files we have to 
		// invert this test, since PR_LOW is lower than PR_HIGH, and since 
		// placing a PR_LOW file before a PR_HIGH file would mean that
		// the PR_LOW file gets sources before the PR_HIGH file ...
		return (file1->GetDownPriority() > file2->GetDownPriority());
	} else {
		int sourcesA = file1->GetSourceCount();
		int sourcesB = file2->GetSourceCount();
		
		int notSourcesA = file1->GetNotCurrentSourcesCount();
		int notSourcesB = file2->GetNotCurrentSourcesCount();
		
		int cmp = CmpAny( sourcesA - notSourcesA, sourcesB - notSourcesB );

		if ( cmp == 0 ) {
			cmp = CmpAny( notSourcesA, notSourcesB );
		}

		return cmp < 0;
	}
}
int CMuleListCtrl::SortProc(wxUIntPtr item1, wxUIntPtr item2, long data)
{
	MuleSortData* sortdata = (MuleSortData*) data;
	const CSortingList& orders = sortdata->m_sort_orders;
	
	CSortingList::const_iterator it = orders.begin();
	for (; it != orders.end(); ++it) {
		int result = sortdata->m_sort_func(item1, item2, it->first | it->second);
		if (result != 0) {
			return result;
		}
	}

	// Ensure that different items are never considered equal.
	return CmpAny(item1, item2);
}
int CSharedFilesCtrl::SortProc(wxUIntPtr item1, wxUIntPtr item2, long sortData)
{
	CKnownFile* file1 = (CKnownFile*)item1;
	CKnownFile* file2 = (CKnownFile*)item2;

	int mod = (sortData & CMuleListCtrl::SORT_DES) ? -1 : 1;
	bool altSorting = (sortData & CMuleListCtrl::SORT_ALT) > 0;

	switch (sortData & CMuleListCtrl::COLUMN_MASK) {
		// Sort by filename.
		case  ID_SHARED_COL_NAME:
			return mod * CmpAny(file1->GetFileName(), file2->GetFileName());
		
		// Sort by filesize.
		case  ID_SHARED_COL_SIZE:
			return mod * CmpAny( file1->GetFileSize(), file2->GetFileSize() );

		// Sort by filetype.
		case  ID_SHARED_COL_TYPE:
			return mod * GetFiletypeByName(file1->GetFileName()).CmpNoCase(GetFiletypeByName( file2->GetFileName()) );

		// Sort by priority.
		case  ID_SHARED_COL_PRIO: {
			int8 prioA = file1->GetUpPriority();
			int8 prioB = file2->GetUpPriority();

			// Work-around for PR_VERYLOW which has value 4. See KnownFile.h for that stupidity ...
			return mod * CmpAny( ( prioB != PR_VERYLOW ? prioB : -1 ), ( prioA != PR_VERYLOW ? prioA : -1 ) );
		}

		// Sort by fileID.
		case  ID_SHARED_COL_ID:
			return mod * file1->GetFileHash().Encode().Cmp( file2->GetFileHash().Encode() );

		// Sort by Requests this session.
		case  ID_SHARED_COL_REQ:
			if (altSorting) {
				return mod * CmpAny( file1->statistic.GetAllTimeRequests(), file2->statistic.GetAllTimeRequests() );
			} else {
				return mod * CmpAny( file1->statistic.GetRequests(), file2->statistic.GetRequests() );
			}

		// Sort by accepted requests. Ascending.
		case  ID_SHARED_COL_AREQ:
			if (altSorting) {
				return mod * CmpAny( file1->statistic.GetAllTimeAccepts(), file2->statistic.GetAllTimeAccepts() );
			} else {
				return mod * CmpAny( file1->statistic.GetAccepts(), file2->statistic.GetAccepts() );
			}

		// Sort by transferred. Ascending.
		case  ID_SHARED_COL_TRA:
			if (altSorting) {
				return mod * CmpAny( file1->statistic.GetAllTimeTransferred(), file2->statistic.GetAllTimeTransferred() );
			} else {
				return mod * CmpAny( file1->statistic.GetTransferred(), file2->statistic.GetTransferred() );
			}

		// Sort by Share Ratio. Ascending.
		case  ID_SHARED_COL_RTIO:
			return mod * CmpAny( (double)file1->statistic.GetAllTimeTransferred() / file1->GetFileSize(),
					(double)file2->statistic.GetAllTimeTransferred() / file2->GetFileSize() );

		// Complete sources asc
		case ID_SHARED_COL_CMPL:
			return mod * CmpAny( file1->m_nCompleteSourcesCount, file2->m_nCompleteSourcesCount );

		// Folders ascending
		case ID_SHARED_COL_PATH: {
			if ( file1->IsPartFile() && file2->IsPartFile() )
				return mod *  0;
			if ( file1->IsPartFile() )
				return mod * -1;
			if ( file2->IsPartFile() )
				return mod *  1;

			return mod * CmpAny(file1->GetFilePath(), file2->GetFilePath());
		}
		
		default:
			return 0;
	}
}