2 // This file is part of the aMule Project.
4 // Copyright (c) 2003-2008 aMule Team ( admin@amule.org / http://www.amule.org )
5 // Copyright (c) 2002-2008 Merkur ( devs@emule-project.net / http://www.emule-project.net )
7 // Any parts of this program derived from the xMule, lMule or eMule project,
8 // or contributed by third-party developers are copyrighted by their
11 // This program is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation; either version 2 of the License, or
14 // (at your option) any later version.
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
21 // You should have received a copy of the GNU General Public License
22 // along with this program; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #include "ServerListCtrl.h" // Interface declarations
28 #include <common/MenuIDs.h>
31 #include <wx/stattext.h>
32 #include <wx/msgdlg.h>
33 #include <wx/settings.h>
35 #include "amule.h" // Needed for theApp
36 #include "DownloadQueue.h" // Needed for CDownloadQueue
37 #ifdef ENABLE_IP2COUNTRY
38 #include "IP2Country.h" // Needed for IP2Country
39 #include "amuleDlg.h" // Needed for IP2Country
41 #include "ServerList.h" // Needed for CServerList
42 #include "ServerConnect.h" // Needed for CServerConnect
43 #include "Server.h" // Needed for CServer and SRV_PR_*
45 #include <common/Format.h> // Needed for CFormat
46 #include <common/TextFile.h> // Needed for CTextFile
49 #define CMuleColour(x) (wxSystemSettings::GetColour(x))
52 BEGIN_EVENT_TABLE(CServerListCtrl
,CMuleListCtrl
)
53 EVT_LIST_ITEM_RIGHT_CLICK( -1, CServerListCtrl::OnItemRightClicked
)
54 EVT_LIST_ITEM_ACTIVATED( -1, CServerListCtrl::OnItemActivated
)
56 EVT_MENU( MP_PRIOLOW
, CServerListCtrl::OnPriorityChange
)
57 EVT_MENU( MP_PRIONORMAL
, CServerListCtrl::OnPriorityChange
)
58 EVT_MENU( MP_PRIOHIGH
, CServerListCtrl::OnPriorityChange
)
60 EVT_MENU( MP_ADDTOSTATIC
, CServerListCtrl::OnStaticChange
)
61 EVT_MENU( MP_REMOVEFROMSTATIC
, CServerListCtrl::OnStaticChange
)
63 EVT_MENU( MP_CONNECTTO
, CServerListCtrl::OnConnectToServer
)
65 EVT_MENU( MP_REMOVE
, CServerListCtrl::OnRemoveServers
)
66 EVT_MENU( MP_REMOVEALL
, CServerListCtrl::OnRemoveServers
)
68 EVT_MENU( MP_GETED2KLINK
, CServerListCtrl::OnGetED2kURL
)
70 EVT_CHAR( CServerListCtrl::OnKeyPressed
)
75 CServerListCtrl::CServerListCtrl( wxWindow
*parent
, wxWindowID winid
, const wxPoint
& pos
, const wxSize
& size
,
76 long style
, const wxValidator
& validator
, const wxString
& name
)
77 : CMuleListCtrl( parent
, winid
, pos
, size
, style
, validator
, name
)
79 // Setting the sorter function.
80 SetSortFunc( SortProc
);
82 // Set the table-name (for loading and saving preferences).
83 SetTableName( wxT("Server") );
87 InsertColumn( COLUMN_SERVER_NAME
, _("Server Name"), wxLIST_FORMAT_LEFT
, 150, wxT("N") );
88 InsertColumn( COLUMN_SERVER_ADDR
, _("Address"), wxLIST_FORMAT_LEFT
, 140, wxT("A") );
89 InsertColumn( COLUMN_SERVER_PORT
, _("Port"), wxLIST_FORMAT_LEFT
, 25, wxT("P") );
90 InsertColumn( COLUMN_SERVER_DESC
, _("Description"), wxLIST_FORMAT_LEFT
, 150, wxT("D") );
91 InsertColumn( COLUMN_SERVER_PING
, _("Ping"), wxLIST_FORMAT_LEFT
, 25, wxT("p") );
92 InsertColumn( COLUMN_SERVER_USERS
, _("Users"), wxLIST_FORMAT_LEFT
, 40, wxT("U") );
93 InsertColumn( COLUMN_SERVER_FILES
, _("Files"), wxLIST_FORMAT_LEFT
, 45, wxT("F") );
94 InsertColumn( COLUMN_SERVER_PRIO
, _("Priority"), wxLIST_FORMAT_LEFT
, 60, wxT("r") );
95 InsertColumn( COLUMN_SERVER_FAILS
, _("Failed"), wxLIST_FORMAT_LEFT
, 40, wxT("f") );
96 InsertColumn( COLUMN_SERVER_STATIC
, _("Static"), wxLIST_FORMAT_LEFT
, 40, wxT("S") );
97 InsertColumn( COLUMN_SERVER_VERSION
, _("Version"), wxLIST_FORMAT_LEFT
, 80, wxT("V") );
99 InsertColumn( COLUMN_SERVER_TCPFLAGS
, wxT("TCP Flags"), wxLIST_FORMAT_LEFT
, 80, wxT("t") );
100 InsertColumn( COLUMN_SERVER_UDPFLAGS
, wxT("UDP Flags"), wxLIST_FORMAT_LEFT
, 80, wxT("u") );
108 wxString
CServerListCtrl::GetOldColumnOrder() const
110 return wxT("N,A,P,D,p,U,F,r,f,S,V,t,u");
114 CServerListCtrl::~CServerListCtrl()
119 void CServerListCtrl::AddServer( CServer
* toadd
)
121 // RefreshServer will add the server.
122 // This also means that we have simple duplicity checking. ;)
123 RefreshServer( toadd
);
129 void CServerListCtrl::RemoveServer(CServer
* server
)
131 long result
= FindItem(-1, reinterpret_cast<wxUIntPtr
>(server
));
132 if ( result
!= -1 ) {
139 void CServerListCtrl::RemoveAllServers(int state
)
141 int pos
= GetNextItem( -1, wxLIST_NEXT_ALL
, state
);
142 bool connected
= theApp
->IsConnectedED2K() ||
143 theApp
->serverconnect
->IsConnecting();
145 while ( pos
!= -1 ) {
146 CServer
* server
= (CServer
*)GetItemData(pos
);
148 if (reinterpret_cast<wxUIntPtr
>(server
) == m_connected
&& connected
) {
149 wxMessageBox(_("You are connected to a server you are trying to delete. Please disconnect first. The server was NOT deleted."), _("Info"), wxOK
, this);
151 } else if (server
->IsStaticMember()) {
152 const wxString name
= (!server
->GetListName() ? wxString(_("(Unknown name)")) : server
->GetListName());
154 if (wxMessageBox(CFormat(_("Are you sure you want to delete the static server %s")) % name
, _("Cancel"), wxICON_QUESTION
| wxYES_NO
, this) == wxYES
) {
155 SetStaticServer(server
, false);
157 theApp
->serverlist
->RemoveServer( server
);
163 theApp
->serverlist
->RemoveServer( server
);
166 pos
= GetNextItem(pos
- 1, wxLIST_NEXT_ALL
, state
);
173 void CServerListCtrl::RefreshServer( CServer
* server
)
175 // Cant really refresh a NULL server
180 wxUIntPtr ptr
= reinterpret_cast<wxUIntPtr
>(server
);
181 long itemnr
= FindItem( -1, ptr
);
182 if ( itemnr
== -1 ) {
183 // We are not at the sure that the server isn't in the list, so we can re-add
184 itemnr
= InsertItem( GetInsertPos( ptr
), server
->GetListName() );
185 SetItemPtrData( itemnr
, ptr
);
188 item
.SetId( itemnr
);
189 item
.SetBackgroundColour(CMuleColour(wxSYS_COLOUR_LISTBOX
));
194 #ifdef ENABLE_IP2COUNTRY
195 // Get the country name
196 if (theApp
->amuledlg
->m_IP2Country
->IsEnabled()) {
197 const CountryData
& countrydata
= theApp
->amuledlg
->m_IP2Country
->GetCountryData(server
->GetFullIP());
198 serverName
<< countrydata
.Name
;
199 serverName
<< wxT(" - ");
201 #endif // ENABLE_IP2COUNTRY
202 serverName
<< server
->GetListName();
203 SetItem(itemnr
, COLUMN_SERVER_NAME
, serverName
);
204 SetItem(itemnr
, COLUMN_SERVER_ADDR
, server
->GetAddress());
205 if (server
->GetAuxPortsList().IsEmpty()) {
206 SetItem( itemnr
, COLUMN_SERVER_PORT
,
207 CFormat(wxT("%u")) % server
->GetPort());
209 SetItem( itemnr
, COLUMN_SERVER_PORT
,
210 CFormat(wxT("%u (%s)")) % server
->GetPort() % server
->GetAuxPortsList());
212 SetItem( itemnr
, COLUMN_SERVER_DESC
, server
->GetDescription() );
214 if ( server
->GetPing() ) {
215 SetItem( itemnr
, COLUMN_SERVER_PING
,
216 CastSecondsToHM(server
->GetPing()/1000, server
->GetPing() % 1000 ) );
218 SetItem( itemnr
, COLUMN_SERVER_PING
, wxEmptyString
);
221 if ( server
->GetUsers() ) {
222 SetItem( itemnr
, COLUMN_SERVER_USERS
,
223 CFormat(wxT("%u")) % server
->GetUsers());
225 SetItem( itemnr
, COLUMN_SERVER_USERS
, wxEmptyString
);
228 if ( server
->GetFiles() ) {
229 SetItem( itemnr
, COLUMN_SERVER_FILES
,
230 CFormat(wxT("%u")) % server
->GetFiles());
232 SetItem( itemnr
, COLUMN_SERVER_FILES
, wxEmptyString
);
235 switch ( server
->GetPreferences() ) {
236 case SRV_PR_LOW
: SetItem(itemnr
, COLUMN_SERVER_PRIO
, _("Low")); break;
237 case SRV_PR_NORMAL
: SetItem(itemnr
, COLUMN_SERVER_PRIO
, _("Normal")); break;
238 case SRV_PR_HIGH
: SetItem(itemnr
, COLUMN_SERVER_PRIO
, _("High") ); break;
239 default: SetItem(itemnr
, COLUMN_SERVER_PRIO
, wxT("---")); // this should never happen
242 SetItem( itemnr
, COLUMN_SERVER_FAILS
, CFormat(wxT("%u")) % server
->GetFailedCount());
243 SetItem( itemnr
, COLUMN_SERVER_STATIC
, ( server
->IsStaticMember() ? _("Yes") : _("No") ) );
244 SetItem( itemnr
, COLUMN_SERVER_VERSION
, server
->GetVersion() );
249 if (server
->GetTCPFlags() & SRV_TCPFLG_COMPRESSION
) {
252 if (server
->GetTCPFlags() & SRV_TCPFLG_NEWTAGS
) {
255 if (server
->GetTCPFlags() & SRV_TCPFLG_UNICODE
) {
258 if (server
->GetTCPFlags() & SRV_TCPFLG_RELATEDSEARCH
) {
261 if (server
->GetTCPFlags() & SRV_TCPFLG_TYPETAGINTEGER
) {
264 if (server
->GetTCPFlags() & SRV_TCPFLG_LARGEFILES
) {
267 if (server
->GetTCPFlags() & SRV_TCPFLG_TCPOBFUSCATION
) {
271 SetItem( itemnr
, COLUMN_SERVER_TCPFLAGS
, flags
);
275 if (server
->GetUDPFlags() & SRV_UDPFLG_EXT_GETSOURCES
) {
278 if (server
->GetUDPFlags() & SRV_UDPFLG_EXT_GETFILES
) {
281 if (server
->GetUDPFlags() & SRV_UDPFLG_NEWTAGS
) {
284 if (server
->GetUDPFlags() & SRV_UDPFLG_UNICODE
) {
287 if (server
->GetUDPFlags() & SRV_UDPFLG_EXT_GETSOURCES2
) {
290 if (server
->GetUDPFlags() & SRV_UDPFLG_LARGEFILES
) {
293 if (server
->GetUDPFlags() & SRV_UDPFLG_UDPOBFUSCATION
) {
296 if (server
->GetUDPFlags() & SRV_UDPFLG_TCPOBFUSCATION
) {
299 SetItem( itemnr
, COLUMN_SERVER_UDPFLAGS
, flags
);
303 // Deletions of items causes rather large ammount of flicker, so to
304 // avoid this, we resort the list to ensure correct ordering.
305 if (!IsItemSorted(itemnr
)) {
311 void CServerListCtrl::HighlightServer( const CServer
* server
, bool highlight
)
313 // Unset the old highlighted server if we are going to set a new one
314 if ( m_connected
&& highlight
) {
315 // A recursive call to do the real work.
316 HighlightServer( (CServer
*)m_connected
, false );
321 long itemnr
= FindItem( -1, reinterpret_cast<wxUIntPtr
>(server
) );
324 item
.SetId( itemnr
);
326 if ( GetItem( item
) ) {
327 wxFont font
= GetFont();
330 font
.SetWeight( wxBOLD
);
332 m_connected
= reinterpret_cast<wxUIntPtr
>(server
);
335 item
.SetFont( font
);
342 //#warning Kry TODO: Dude, this gotta be moved to core
343 bool CServerListCtrl::SetStaticServer( CServer
* server
, bool isStatic
)
345 server
->SetIsStaticMember( isStatic
);
346 RefreshServer( server
);
348 wxString filename
= theApp
->ConfigDir
+ wxT("staticservers.dat");
351 if (!file
.Open(filename
, CTextFile::write
)) {
352 AddLogLineN(CFormat( _("Failed to open '%s'") ) % filename
);
356 for (int i
= 0; i
< GetItemCount(); ++i
) {
357 server
= reinterpret_cast<CServer
*>(GetItemData(i
));
359 if (server
->IsStaticMember()) {
360 file
.WriteLine(CFormat(wxT("%s:%u,%u,%s"))
361 % server
->GetAddress() % server
->GetPort()
362 % server
->GetPreferences() % server
->GetListName());
370 void CServerListCtrl::ShowServerCount()
372 wxStaticText
* label
= CastByName( wxT("serverListLabel"), GetParent(), wxStaticText
);
375 label
->SetLabel(CFormat(_("Servers (%i)")) % GetItemCount());
376 label
->GetParent()->Layout();
381 void CServerListCtrl::OnItemActivated( wxListEvent
& event
)
383 // Unselect all items but the activated one
384 long item
= GetNextItem( -1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
385 while ( item
> -1 ) {
386 SetItemState( item
, 0, wxLIST_STATE_SELECTED
);
388 item
= GetNextItem( item
, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
391 SetItemState( event
.GetIndex(), wxLIST_STATE_SELECTED
, wxLIST_STATE_SELECTED
);
393 wxCommandEvent nulEvt
;
394 OnConnectToServer( nulEvt
);
398 void CServerListCtrl::OnItemRightClicked(wxListEvent
& event
)
400 // Check if clicked item is selected. If not, unselect all and select it.
401 long index
= CheckSelection(event
);
403 bool enable_reconnect
= false;
404 bool enable_static_on
= false;
405 bool enable_static_off
= false;
407 // Gather information on the selected items
408 while ( index
> -1 ) {
409 CServer
* server
= (CServer
*)GetItemData( index
);
411 // The current server is selected, so we might display the reconnect option
412 if ( reinterpret_cast<wxUIntPtr
>(server
) == m_connected
)
413 enable_reconnect
= true;
415 // We want to know which options should be enabled, either one or both
416 enable_static_on
|= !server
->IsStaticMember();
417 enable_static_off
|= server
->IsStaticMember();
419 index
= GetNextItem( index
, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
423 wxMenu
* serverMenu
= new wxMenu(_("Server"));
424 wxMenu
* serverPrioMenu
= new wxMenu();
425 serverPrioMenu
->Append( MP_PRIOLOW
, _("Low") );
426 serverPrioMenu
->Append( MP_PRIONORMAL
, _("Normal") );
427 serverPrioMenu
->Append( MP_PRIOHIGH
, _("High") );
428 serverMenu
->Append( MP_CONNECTTO
, _("Connect to server") );
429 serverMenu
->Append( 12345, _("Priority"), serverPrioMenu
);
431 serverMenu
->AppendSeparator();
433 if (GetSelectedItemCount() == 1) {
434 serverMenu
->Append( MP_ADDTOSTATIC
, _("Mark server as static") );
435 serverMenu
->Append( MP_REMOVEFROMSTATIC
, _("Mark server as non-static") );
437 serverMenu
->Append( MP_ADDTOSTATIC
, _("Mark servers as static") );
438 serverMenu
->Append( MP_REMOVEFROMSTATIC
, _("Mark servers as non-static") );
441 serverMenu
->AppendSeparator();
443 if (GetSelectedItemCount() == 1) {
444 serverMenu
->Append( MP_REMOVE
, _("Remove server") );
446 serverMenu
->Append( MP_REMOVE
, _("Remove servers") );
448 serverMenu
->Append( MP_REMOVEALL
, _("Remove all servers") );
450 serverMenu
->AppendSeparator();
452 if (GetSelectedItemCount() == 1) {
453 serverMenu
->Append( MP_GETED2KLINK
, _("Copy eD2k link to clipboard") );
455 serverMenu
->Append( MP_GETED2KLINK
, _("Copy eD2k links to clipboard") );
458 serverMenu
->Enable( MP_REMOVEFROMSTATIC
, enable_static_off
);
459 serverMenu
->Enable( MP_ADDTOSTATIC
, enable_static_on
);
461 if ( GetSelectedItemCount() == 1 ) {
462 if ( enable_reconnect
)
463 serverMenu
->SetLabel( MP_CONNECTTO
, _("Reconnect to server") );
465 serverMenu
->Enable( MP_CONNECTTO
, false );
469 PopupMenu( serverMenu
, event
.GetPoint() );
474 void CServerListCtrl::OnPriorityChange( wxCommandEvent
& event
)
478 switch ( event
.GetId() ) {
479 case MP_PRIOLOW
: priority
= SRV_PR_LOW
; break;
480 case MP_PRIONORMAL
: priority
= SRV_PR_NORMAL
; break;
481 case MP_PRIOHIGH
: priority
= SRV_PR_HIGH
; break;
488 ItemDataList items
= GetSelectedItems();
490 for ( unsigned int i
= 0; i
< items
.size(); ++i
) {
491 CServer
* server
= (CServer
*)items
[ i
];
493 server
->SetPreference( priority
);
494 RefreshServer( server
);
499 void CServerListCtrl::OnStaticChange( wxCommandEvent
& event
)
501 bool isStatic
= ( event
.GetId() == MP_ADDTOSTATIC
);
503 ItemDataList items
= GetSelectedItems();
505 for ( unsigned int i
= 0; i
< items
.size(); ++i
) {
506 CServer
* server
= (CServer
*)items
[ i
];
508 // Only update items that have the wrong setting
509 if ( server
->IsStaticMember() != isStatic
) {
510 if ( !SetStaticServer( server
, isStatic
) ) {
516 server
->SetIsStaticMember( isStatic
);
517 RefreshServer( server
);
523 void CServerListCtrl::OnConnectToServer( wxCommandEvent
& WXUNUSED(event
) )
525 int item
= GetNextItem( -1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
528 if ( theApp
->IsConnectedED2K() ) {
529 theApp
->serverconnect
->Disconnect();
532 theApp
->serverconnect
->ConnectToServer( (CServer
*)GetItemData( item
) );
537 void CServerListCtrl::OnGetED2kURL( wxCommandEvent
& WXUNUSED(event
) )
539 int pos
= GetNextItem( -1, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
543 while ( pos
!= -1 ) {
544 CServer
* server
= (CServer
*)GetItemData(pos
);
546 URL
+= CFormat(wxT("ed2k://|server|%s|%d|/\n")) % server
->GetFullIP() % server
->GetPort();
548 pos
= GetNextItem( pos
, wxLIST_NEXT_ALL
, wxLIST_STATE_SELECTED
);
553 theApp
->CopyTextToClipboard( URL
);
557 void CServerListCtrl::OnRemoveServers( wxCommandEvent
& event
)
559 if ( event
.GetId() == MP_REMOVEALL
) {
560 if ( GetItemCount() ) {
561 wxString question
= _("Are you sure that you wish to delete all servers?");
563 if ( wxMessageBox( question
, _("Cancel"), wxICON_QUESTION
| wxYES_NO
, this) == wxYES
) {
564 if ( theApp
->serverconnect
->IsConnecting() ) {
565 theApp
->downloadqueue
->StopUDPRequests();
566 theApp
->serverconnect
->StopConnectionTry();
567 theApp
->serverconnect
->Disconnect();
570 RemoveAllServers(wxLIST_STATE_DONTCARE
);
573 } else if ( event
.GetId() == MP_REMOVE
) {
574 if ( GetSelectedItemCount() ) {
576 if (GetSelectedItemCount() == 1) {
577 question
= _("Are you sure that you wish to delete the selected server?");
579 question
= _("Are you sure that you wish to delete the selected servers?");
582 if ( wxMessageBox( question
, _("Cancel"), wxICON_QUESTION
| wxYES_NO
, this) == wxYES
) {
583 RemoveAllServers(wxLIST_STATE_SELECTED
);
590 void CServerListCtrl::OnKeyPressed( wxKeyEvent
& event
)
592 // Check if delete was pressed
593 if ((event
.GetKeyCode() == WXK_DELETE
) || (event
.GetKeyCode() == WXK_NUMPAD_DELETE
)) {
595 evt
.SetId( MP_REMOVE
);
596 OnRemoveServers( evt
);
603 int CServerListCtrl::SortProc(wxUIntPtr item1
, wxUIntPtr item2
, long sortData
)
605 CServer
* server1
= (CServer
*)item1
;
606 CServer
* server2
= (CServer
*)item2
;
608 int mode
= (sortData
& CMuleListCtrl::SORT_DES
) ? -1 : 1;
610 switch (sortData
& CMuleListCtrl::COLUMN_MASK
) {
611 // Sort by server-name
612 case COLUMN_SERVER_NAME
:
613 return mode
* server1
->GetListName().CmpNoCase(server2
->GetListName());
616 case COLUMN_SERVER_ADDR
:
618 if ( server1
->HasDynIP() && server2
->HasDynIP()) {
619 return mode
* server1
->GetDynIP().CmpNoCase( server2
->GetDynIP() );
620 } else if (server1
->HasDynIP()) {
622 } else if (server2
->HasDynIP()) {
625 uint32 a
= wxUINT32_SWAP_ALWAYS(server1
->GetIP());
626 uint32 b
= wxUINT32_SWAP_ALWAYS(server2
->GetIP());
627 return mode
* CmpAny(a
, b
);
631 case COLUMN_SERVER_PORT
: return mode
* CmpAny( server1
->GetPort(), server2
->GetPort() );
632 // Sort by description
633 case COLUMN_SERVER_DESC
: return mode
* server1
->GetDescription().CmpNoCase( server2
->GetDescription() );
635 // The -1 ensures that a value of zero (no ping known) is sorted last.
636 case COLUMN_SERVER_PING
: return mode
* CmpAny( server1
->GetPing() - 1, server2
->GetPing() -1 );
637 // Sort by user-count
638 case COLUMN_SERVER_USERS
: return mode
* CmpAny( server1
->GetUsers(), server2
->GetUsers() );
639 // Sort by file-count
640 case COLUMN_SERVER_FILES
: return mode
* CmpAny( server1
->GetFiles(), server2
->GetFiles() );
642 case COLUMN_SERVER_PRIO
:
644 uint32 srv_pr1
= server1
->GetPreferences();
645 uint32 srv_pr2
= server2
->GetPreferences();
647 case SRV_PR_HIGH
: srv_pr1
= SRV_PR_MAX
; break;
648 case SRV_PR_NORMAL
: srv_pr1
= SRV_PR_MID
; break;
649 case SRV_PR_LOW
: srv_pr1
= SRV_PR_MIN
; break;
653 case SRV_PR_HIGH
: srv_pr2
= SRV_PR_MAX
; break;
654 case SRV_PR_NORMAL
: srv_pr2
= SRV_PR_MID
; break;
655 case SRV_PR_LOW
: srv_pr2
= SRV_PR_MIN
; break;
658 return mode
* CmpAny( srv_pr1
, srv_pr2
);
660 // Sort by failure-count
661 case COLUMN_SERVER_FAILS
: return mode
* CmpAny( server1
->GetFailedCount(), server2
->GetFailedCount() );
662 // Sort by static servers
663 case COLUMN_SERVER_STATIC
:
665 return mode
* CmpAny( server2
->IsStaticMember(), server1
->IsStaticMember() );
668 case COLUMN_SERVER_VERSION
: return mode
* FuzzyStrCmp(server1
->GetVersion(), server2
->GetVersion());
674 // File_checked_for_headers