You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
522 lines
17 KiB
522 lines
17 KiB
/*******************************************************************************
|
|
*
|
|
* colsort.cpp
|
|
*
|
|
* Helper functions to sort columns
|
|
*
|
|
* copyright notice: Copyright 1997, Citrix Systems Inc.
|
|
* Copyright (c) 1998 - 1999 Microsoft Corporation
|
|
*
|
|
* $Author: donm $ Don Messerli
|
|
*
|
|
* $Log: N:\nt\private\utils\citrix\winutils\tsadmin\VCS\colsort.cpp $
|
|
*
|
|
* Rev 1.10 19 Feb 1998 17:40:12 donm
|
|
* removed latest extension DLL support
|
|
*
|
|
* Rev 1.7 12 Feb 1998 14:20:50 donm
|
|
* missed some State columns
|
|
*
|
|
* Rev 1.6 12 Feb 1998 12:59:20 donm
|
|
* State columns wouldn't sort because they were being treated as numbers
|
|
*
|
|
* Rev 1.5 10 Nov 1997 14:51:30 donm
|
|
* fixed endless recursion in SortTextItems
|
|
*
|
|
* Rev 1.4 07 Nov 1997 23:06:38 donm
|
|
* CompareTCPAddress would trap if ExtServerInfo was NULL
|
|
*
|
|
* Rev 1.3 03 Nov 1997 15:23:22 donm
|
|
* added descending sort/cleanup
|
|
*
|
|
* Rev 1.2 15 Oct 1997 19:50:34 donm
|
|
* update
|
|
*
|
|
* Rev 1.1 13 Oct 1997 18:39:54 donm
|
|
* update
|
|
*
|
|
* Rev 1.0 30 Jul 1997 17:11:26 butchd
|
|
* Initial revision.
|
|
*
|
|
*******************************************************************************/
|
|
|
|
#include "stdafx.h"
|
|
#include "winadmin.h"
|
|
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
|
|
// Compare function for columns of WinStations
|
|
/* no longer used since we want an alphabetical order
|
|
int CALLBACK CompareWinStation(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
|
|
{
|
|
int retval = 0;
|
|
|
|
if(!lParam1 || !lParam2) return 0;
|
|
|
|
ULONG sort1 = ((CWinStation*)lParam1)->GetSortOrder();
|
|
ULONG sort2 = ((CWinStation*)lParam2)->GetSortOrder();
|
|
if(sort1 == sort2) {
|
|
SDCLASS pd1 = ((CWinStation*)lParam1)->GetSdClass();
|
|
SDCLASS pd2 = ((CWinStation*)lParam2)->GetSdClass();
|
|
if(pd1 == pd2) retval = 0;
|
|
else if(pd1 < pd2) retval = -1;
|
|
else retval = 1;
|
|
}
|
|
else if(sort1 < sort2) retval = -1;
|
|
else retval = 1;
|
|
|
|
return(lParamSort ? retval : -retval);
|
|
}
|
|
*/
|
|
|
|
// Compare function for columns of Idle Times
|
|
int CALLBACK CompareIdleTime(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
|
|
{
|
|
int retval = 0;
|
|
|
|
if(!lParam1 || !lParam2) return 0;
|
|
ELAPSEDTIME idle1 = ((CWinStation*)lParam1)->GetIdleTime();
|
|
ELAPSEDTIME idle2 = ((CWinStation*)lParam2)->GetIdleTime();
|
|
// check days first
|
|
if(idle1.days < idle2.days) retval = -1;
|
|
else if(idle1.days > idle2.days) retval = 1;
|
|
// check hours
|
|
else if(idle1.hours < idle2.hours) retval = -1;
|
|
else if(idle1.hours > idle2.hours) retval = 1;
|
|
// check minutes
|
|
else if(idle1.minutes < idle2.minutes) retval = -1;
|
|
else if(idle1.minutes > idle2.minutes) retval = 1;
|
|
// check seconds
|
|
else if(idle1.seconds < idle2.seconds) retval = -1;
|
|
else if(idle1.seconds > idle2.seconds) retval = 1;
|
|
|
|
return(lParamSort ? retval : -retval);
|
|
}
|
|
|
|
|
|
// Compare function for columns of Logon Times
|
|
int CALLBACK CompareLogonTime(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
|
|
{
|
|
int retval = 0;
|
|
|
|
if(!lParam1 || !lParam2) return 0;
|
|
|
|
LARGE_INTEGER logon1 = ((CWinStation*)lParam1)->GetLogonTime();
|
|
LARGE_INTEGER logon2 = ((CWinStation*)lParam2)->GetLogonTime();
|
|
|
|
if(logon1.QuadPart == logon2.QuadPart) retval = 0;
|
|
else if(logon1.QuadPart < logon2.QuadPart) retval = -1;
|
|
else retval = 1;
|
|
|
|
return(lParamSort ? retval : -retval);
|
|
}
|
|
|
|
|
|
// Compare function for columns of TCP/IP Addresses
|
|
int CALLBACK CompareTcpAddress(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
|
|
{
|
|
int retval = 0;
|
|
|
|
if(!lParam1 || !lParam2) return 0;
|
|
|
|
ExtServerInfo *ex1 = (ExtServerInfo*)((CServer*)lParam1)->GetExtendedInfo();
|
|
ExtServerInfo *ex2 = (ExtServerInfo*)((CServer*)lParam2)->GetExtendedInfo();
|
|
|
|
if(!ex1 && !ex2) retval = 0;
|
|
else if(ex1 && !ex2) retval = 1;
|
|
else if(!ex1 && ex2) retval = -1;
|
|
else {
|
|
ULONG tcp1 = ex1->RawTcpAddress;
|
|
ULONG tcp2 = ex2->RawTcpAddress;
|
|
|
|
if(tcp1 == tcp2) retval = 0;
|
|
else if(tcp1 < tcp2) retval = -1;
|
|
else retval = 1;
|
|
}
|
|
|
|
return(lParamSort ? retval : -retval);
|
|
}
|
|
|
|
|
|
// Compare function for columns of Module dates
|
|
int CALLBACK CompareModuleDate(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
|
|
{
|
|
int retval = 0;
|
|
|
|
if(!lParam1 || !lParam2) return 0;
|
|
|
|
// Compare the dates first
|
|
USHORT date1 = ((ExtModuleInfo*)lParam1)->Date;
|
|
USHORT date2 = ((ExtModuleInfo*)lParam2)->Date;
|
|
|
|
if(date1 < date2) retval = -1;
|
|
else if(date1 > date2) retval = 1;
|
|
// Dates are the same, compare the times
|
|
else {
|
|
USHORT time1 = ((ExtModuleInfo*)lParam1)->Time;
|
|
USHORT time2 = ((ExtModuleInfo*)lParam2)->Time;
|
|
if(time1 == time2) retval = 0;
|
|
else if(time1 < time2) retval = -1;
|
|
else retval = 1;
|
|
}
|
|
|
|
return(lParamSort ? retval : -retval);
|
|
}
|
|
|
|
|
|
// Compare function for columns of Module versions
|
|
int CALLBACK CompareModuleVersions(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
|
|
{
|
|
int retval = 0;
|
|
|
|
if(!lParam1 || !lParam2) return 0;
|
|
|
|
// Compare the low versions first
|
|
BYTE lowversion1 = ((ExtModuleInfo*)lParam1)->LowVersion;
|
|
BYTE lowversion2 = ((ExtModuleInfo*)lParam2)->LowVersion;
|
|
|
|
if(lowversion1 < lowversion2) retval = -1;
|
|
else if(lowversion1 > lowversion2) retval = 1;
|
|
// Low versions are the same, compare high version
|
|
else {
|
|
BYTE highversion1 = ((ExtModuleInfo*)lParam1)->HighVersion;
|
|
BYTE highversion2 = ((ExtModuleInfo*)lParam2)->HighVersion;
|
|
if(highversion1 == highversion2) retval = 0;
|
|
else if(highversion1 < highversion2) retval = -1;
|
|
else retval = 1;
|
|
}
|
|
|
|
return(lParamSort ? retval : -retval);
|
|
}
|
|
|
|
|
|
// SortTextItems - Sort the list based on column text
|
|
// Returns - Returns true for success
|
|
// nCol - column that contains the text to be sorted
|
|
// bAscending - indicate sort order
|
|
// low - row to start scanning from - default row is 0
|
|
// high - row to end scan. -1 indicates last row
|
|
BOOL SortTextItems( CListCtrl *pList, int nCol, BOOL bAscending,
|
|
int low /*= 0*/, int high /*= -1*/ ){
|
|
if( nCol >= ((CHeaderCtrl*)pList->GetDlgItem(0))->GetItemCount() )
|
|
return FALSE;
|
|
|
|
if( high == -1 ) high = pList->GetItemCount() - 1;
|
|
|
|
int lo = low;
|
|
int hi = high;
|
|
CString midItem;
|
|
|
|
if( hi <= lo ) return FALSE;
|
|
|
|
midItem = pList->GetItemText( (lo+hi)/2, nCol );
|
|
|
|
// loop through the list until indices cross
|
|
while( lo <= hi ) {
|
|
|
|
// rowText will hold all column text for one row
|
|
CStringArray rowText;
|
|
|
|
// find the first element that is greater than or equal to
|
|
// the partition element starting from the left Index.
|
|
if( bAscending )
|
|
while( ( lo < high ) && ( pList->GetItemText(lo, nCol) < midItem ) )
|
|
++lo;
|
|
else
|
|
while( ( lo < high ) && ( pList->GetItemText(lo, nCol) > midItem ) )
|
|
++lo;
|
|
|
|
// find an element that is smaller than or equal to
|
|
// the partition element starting from the right Index.
|
|
if( bAscending )
|
|
while( ( hi > low ) && ( pList->GetItemText(hi, nCol) > midItem ) )
|
|
--hi;
|
|
else
|
|
while( ( hi > low ) && ( pList->GetItemText(hi, nCol) < midItem ) )
|
|
--hi;
|
|
|
|
// if the indexes have not crossed, swap
|
|
// and if the items are not equal
|
|
if( lo <= hi )
|
|
{
|
|
// swap only if the items are not equal
|
|
if( pList->GetItemText(lo, nCol) != pList->GetItemText(hi, nCol))
|
|
{
|
|
// swap the rows
|
|
LV_ITEM lvitemlo, lvitemhi;
|
|
int nColCount =
|
|
((CHeaderCtrl*)pList->GetDlgItem(0))->GetItemCount();
|
|
rowText.SetSize( nColCount );
|
|
|
|
int i;
|
|
for( i=0; i<nColCount; i++)
|
|
rowText[i] = pList->GetItemText(lo, i);
|
|
lvitemlo.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
|
|
lvitemlo.iItem = lo;
|
|
lvitemlo.iSubItem = 0;
|
|
lvitemlo.stateMask = LVIS_CUT | LVIS_DROPHILITED |
|
|
LVIS_FOCUSED | LVIS_SELECTED |
|
|
LVIS_OVERLAYMASK | LVIS_STATEIMAGEMASK;
|
|
|
|
lvitemhi = lvitemlo;
|
|
lvitemhi.iItem = hi;
|
|
|
|
pList->GetItem( &lvitemlo );
|
|
pList->GetItem( &lvitemhi );
|
|
|
|
for( i=0; i<nColCount; i++)
|
|
pList->SetItemText(lo, i, pList->GetItemText(hi, i));
|
|
|
|
lvitemhi.iItem = lo;
|
|
pList->SetItem( &lvitemhi );
|
|
|
|
for( i=0; i<nColCount; i++)
|
|
pList->SetItemText(hi, i, rowText[i]);
|
|
|
|
lvitemlo.iItem = hi;
|
|
pList->SetItem( &lvitemlo );
|
|
}
|
|
|
|
++lo;
|
|
--hi;
|
|
}
|
|
}
|
|
|
|
// If the right index has not reached the left side of array
|
|
// must now sort the left partition.
|
|
if( low < hi )
|
|
SortTextItems( pList, nCol, bAscending , low, hi);
|
|
|
|
// If the left index has not reached the right side of array
|
|
// must now sort the right partition.
|
|
if( lo < high )
|
|
SortTextItems( pList, nCol, bAscending , lo, high );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
long myatol(CString sTemp)
|
|
{
|
|
|
|
return((long)wcstoul(sTemp.GetBuffer(0), NULL, 10));
|
|
}
|
|
|
|
|
|
BOOL SortNumericItems( CListCtrl *pList, int nCol, BOOL bAscending,long low, long high)
|
|
{
|
|
if( nCol >= ((CHeaderCtrl*)pList->GetDlgItem(0))->GetItemCount() )
|
|
return FALSE;
|
|
|
|
if( high == -1 ) high = pList->GetItemCount() - 1;
|
|
long lo = low;
|
|
long hi = high;
|
|
|
|
long midItem;
|
|
|
|
if( hi <= lo ) return FALSE;
|
|
|
|
midItem = myatol(pList->GetItemText( (lo+hi)/2, nCol ));
|
|
|
|
// loop through the list until indices cross
|
|
while( lo <= hi )
|
|
{
|
|
// rowText will hold all column text for one row
|
|
CStringArray rowText;
|
|
|
|
// find the first element that is greater than or equal to
|
|
// the partition element starting from the left Index.
|
|
if( bAscending )
|
|
while( ( lo < high ) && (myatol(pList->GetItemText(lo, nCol)) < midItem ) )
|
|
++lo;
|
|
else
|
|
while( ( lo < high ) && (myatol(pList->GetItemText(lo, nCol)) > midItem ) )
|
|
++lo;
|
|
|
|
// find an element that is smaller than or equal to
|
|
// the partition element starting from the right Index.
|
|
if( bAscending )
|
|
while( ( hi > low ) && (myatol(pList->GetItemText(hi, nCol)) > midItem ) )
|
|
--hi;
|
|
else
|
|
while( ( hi > low ) && (myatol(pList->GetItemText(hi, nCol)) < midItem ) )
|
|
--hi;
|
|
|
|
// if the indexes have not crossed, swap
|
|
// and if the items are not equal
|
|
if( lo <= hi )
|
|
{
|
|
// swap only if the items are not equal
|
|
if(myatol(pList->GetItemText(lo, nCol)) != myatol(pList->GetItemText(hi, nCol)) )
|
|
{
|
|
// swap the rows
|
|
LV_ITEM lvitemlo, lvitemhi;
|
|
int nColCount =
|
|
((CHeaderCtrl*)pList->GetDlgItem(0))->GetItemCount();
|
|
|
|
rowText.SetSize( nColCount );
|
|
|
|
int i;
|
|
for( i=0; i < nColCount; i++)
|
|
rowText[i] = pList->GetItemText(lo, i);
|
|
|
|
lvitemlo.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
|
|
lvitemlo.iItem = lo;
|
|
lvitemlo.iSubItem = 0;
|
|
lvitemlo.stateMask = LVIS_CUT | LVIS_DROPHILITED |
|
|
LVIS_FOCUSED | LVIS_SELECTED |
|
|
LVIS_OVERLAYMASK | LVIS_STATEIMAGEMASK;
|
|
lvitemhi = lvitemlo;
|
|
lvitemhi.iItem = hi;
|
|
|
|
pList->GetItem( &lvitemlo );
|
|
pList->GetItem( &lvitemhi );
|
|
|
|
for( i=0; i< nColCount; i++)
|
|
pList->SetItemText(lo, i, pList->GetItemText(hi, i) );
|
|
|
|
lvitemhi.iItem = lo;
|
|
pList->SetItem( &lvitemhi );
|
|
|
|
for( i=0; i< nColCount; i++)
|
|
pList->SetItemText(hi, i, rowText[i]);
|
|
|
|
lvitemlo.iItem = hi;
|
|
pList->SetItem( &lvitemlo );
|
|
}
|
|
|
|
++lo;
|
|
--hi;
|
|
}
|
|
}
|
|
|
|
// If the right index has not reached the left side of array
|
|
// must now sort the left partition.
|
|
if( low < hi )
|
|
SortNumericItems( pList, nCol, bAscending , low, hi);
|
|
|
|
// If the left index has not reached the right side of array
|
|
// must now sort the right partition.
|
|
if( lo < high )
|
|
SortNumericItems( pList, nCol, bAscending , lo, high );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// Our lookup table has structures of this type
|
|
typedef struct _ColumnLookup {
|
|
int View; // The view the page is in
|
|
int Page; // Page that needs to be sorted
|
|
int ColumnNumber; // Column that need to be sorted
|
|
int (CALLBACK *CompareFunc)(LPARAM,LPARAM,LPARAM); // Callback to send to CListCtrl.SortItems
|
|
} ColumnLookup;
|
|
|
|
|
|
// This table only includes structures for columns that aren't sorted
|
|
// using the SortTextItems() function
|
|
// NULL for the CompareFunc means that SortNumericItems() should be called
|
|
ColumnLookup ColumnTable[] = {
|
|
// Server User's Page - CWinStation
|
|
{ VIEW_SERVER, PAGE_USERS, USERS_COL_ID, NULL },
|
|
{ VIEW_SERVER, PAGE_USERS, USERS_COL_IDLETIME, CompareIdleTime },
|
|
{ VIEW_SERVER, PAGE_USERS, USERS_COL_LOGONTIME, CompareLogonTime },
|
|
// Server WinStation's Page - CWinStation
|
|
// { VIEW_SERVER, PAGE_WINSTATIONS, WS_COL_WINSTATION, CompareWinStation },
|
|
{ VIEW_SERVER, PAGE_WINSTATIONS, WS_COL_ID, NULL },
|
|
{ VIEW_SERVER, PAGE_WINSTATIONS, WS_COL_IDLETIME, CompareIdleTime },
|
|
{ VIEW_SERVER, PAGE_WINSTATIONS, WS_COL_LOGONTIME, CompareLogonTime },
|
|
// Server Processes' columns - CProcess
|
|
{ VIEW_SERVER, PAGE_PROCESSES, PROC_COL_ID, NULL },
|
|
{ VIEW_SERVER, PAGE_PROCESSES, PROC_COL_PID, NULL },
|
|
// Server Info (Hotfix) columns - CHotfix
|
|
{ VIEW_SERVER, PAGE_INFO, HOTFIX_COL_INSTALLEDON, NULL },
|
|
// WinStation Processes' columns - CProcess
|
|
{ VIEW_WINSTATION, PAGE_WS_PROCESSES, WS_PROC_COL_ID, NULL },
|
|
{ VIEW_WINSTATION, PAGE_WS_PROCESSES, WS_PROC_COL_PID, NULL },
|
|
// WinStation Modules columns - CModule
|
|
{ VIEW_WINSTATION, PAGE_WS_MODULES, MODULES_COL_FILEDATETIME, CompareModuleDate },
|
|
{ VIEW_WINSTATION, PAGE_WS_MODULES, MODULES_COL_SIZE, NULL },
|
|
{ VIEW_WINSTATION, PAGE_WS_MODULES, MODULES_COL_VERSIONS, CompareModuleVersions },
|
|
// All Server Servers columns - CServer
|
|
{ VIEW_ALL_SERVERS, PAGE_AS_SERVERS, SERVERS_COL_TCPADDRESS, CompareTcpAddress },
|
|
{ VIEW_ALL_SERVERS, PAGE_AS_SERVERS, SERVERS_COL_NUMWINSTATIONS, NULL },
|
|
// All Server Users columns - CWinStation
|
|
{ VIEW_ALL_SERVERS, PAGE_AS_USERS, AS_USERS_COL_ID, NULL },
|
|
{ VIEW_ALL_SERVERS, PAGE_AS_USERS, AS_USERS_COL_IDLETIME, CompareIdleTime },
|
|
{ VIEW_ALL_SERVERS, PAGE_AS_USERS, AS_USERS_COL_LOGONTIME, CompareLogonTime },
|
|
// All Server WinStations columns - CWinStation
|
|
// { VIEW_ALL_SERVERS, PAGE_AS_WINSTATIONS, AS_WS_COL_WINSTATION, CompareWinStation },
|
|
{ VIEW_ALL_SERVERS, PAGE_AS_WINSTATIONS, AS_WS_COL_ID, NULL },
|
|
{ VIEW_ALL_SERVERS, PAGE_AS_WINSTATIONS, AS_WS_COL_IDLETIME, CompareIdleTime },
|
|
{ VIEW_ALL_SERVERS, PAGE_AS_WINSTATIONS, AS_WS_COL_LOGONTIME, CompareLogonTime },
|
|
// All Server Processes columns - CProcess
|
|
{ VIEW_ALL_SERVERS, PAGE_AS_PROCESSES, AS_PROC_COL_ID, NULL },
|
|
{ VIEW_ALL_SERVERS, PAGE_AS_PROCESSES, AS_PROC_COL_PID, NULL },
|
|
// All Server Licenses columns - CLicense
|
|
{ VIEW_ALL_SERVERS, PAGE_AS_LICENSES, AS_LICENSE_COL_USERCOUNT, NULL },
|
|
{ VIEW_ALL_SERVERS, PAGE_AS_LICENSES, AS_LICENSE_COL_POOLCOUNT, NULL },
|
|
// Domain Servers columns - CServer
|
|
{ VIEW_DOMAIN, PAGE_DOMAIN_SERVERS, SERVERS_COL_TCPADDRESS, CompareTcpAddress },
|
|
{ VIEW_DOMAIN, PAGE_DOMAIN_SERVERS, SERVERS_COL_NUMWINSTATIONS, NULL },
|
|
// Domain Users columns - CWinStation
|
|
{ VIEW_DOMAIN, PAGE_DOMAIN_USERS, AS_USERS_COL_ID, NULL },
|
|
{ VIEW_DOMAIN, PAGE_DOMAIN_USERS, AS_USERS_COL_IDLETIME, CompareIdleTime },
|
|
{ VIEW_DOMAIN, PAGE_DOMAIN_USERS, AS_USERS_COL_LOGONTIME, CompareLogonTime },
|
|
// Domain WinStations columns - CWinStation
|
|
// { VIEW_DOMAIN, PAGE_DOMAIN_WINSTATIONS, AS_WS_COL_WINSTATION, CompareWinStation },
|
|
{ VIEW_DOMAIN, PAGE_DOMAIN_WINSTATIONS, AS_WS_COL_ID, NULL },
|
|
{ VIEW_DOMAIN, PAGE_DOMAIN_WINSTATIONS, AS_WS_COL_IDLETIME, CompareIdleTime },
|
|
{ VIEW_DOMAIN, PAGE_DOMAIN_WINSTATIONS, AS_WS_COL_LOGONTIME, CompareLogonTime },
|
|
// Domain Processes columns - CProcess
|
|
{ VIEW_DOMAIN, PAGE_DOMAIN_PROCESSES, AS_PROC_COL_ID, NULL },
|
|
{ VIEW_DOMAIN, PAGE_DOMAIN_PROCESSES, AS_PROC_COL_PID, NULL },
|
|
// Domain Licenses columns - CLicense
|
|
{ VIEW_DOMAIN, PAGE_DOMAIN_LICENSES, AS_LICENSE_COL_USERCOUNT, NULL },
|
|
{ VIEW_DOMAIN, PAGE_DOMAIN_LICENSES, AS_LICENSE_COL_POOLCOUNT, NULL },
|
|
};
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// SortByColumn
|
|
//
|
|
// Page - page to be sorted
|
|
// List - pointer to list control to call ->SortItems member function of
|
|
// ColumnNumber - which column is to be sorted on
|
|
// bAscending - TRUE if ascending, FALSE if descending
|
|
//
|
|
static int insort = 0;
|
|
void SortByColumn(int View, int Page, CListCtrl *List, int ColumnNumber, BOOL bAscending)
|
|
{
|
|
if(insort) return;
|
|
|
|
insort = 1;
|
|
BOOL found = FALSE;
|
|
|
|
// Look up the type of column from the ColumnNumber in our table
|
|
int TableSize = sizeof(ColumnTable) / sizeof(ColumnLookup);
|
|
|
|
for(int i = 0; i < TableSize; i++) {
|
|
if(ColumnTable[i].View == View &&
|
|
ColumnTable[i].Page == Page &&
|
|
ColumnTable[i].ColumnNumber == ColumnNumber) {
|
|
if(ColumnTable[i].CompareFunc)
|
|
List->SortItems(ColumnTable[i].CompareFunc, bAscending);
|
|
else
|
|
SortNumericItems(List, ColumnNumber, bAscending, 0, -1);
|
|
found = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!found) SortTextItems( List, ColumnNumber, bAscending, 0, -1);
|
|
|
|
insort = 0;
|
|
|
|
} // end SortByColumn
|