2004-10-23 07:13:18 +00:00
|
|
|
// $Id$
|
|
|
|
//
|
|
|
|
// The contents of this file are subject to the BOINC Public License
|
|
|
|
// Version 1.0 (the "License"); you may not use this file except in
|
|
|
|
// compliance with the License. You may obtain a copy of the License at
|
|
|
|
// http://boinc.berkeley.edu/license_1.0.txt
|
|
|
|
//
|
|
|
|
// Software distributed under the License is distributed on an "AS IS"
|
|
|
|
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
|
|
|
// License for the specific language governing rights and limitations
|
|
|
|
// under the License.
|
|
|
|
//
|
|
|
|
// The Original Code is the Berkeley Open Infrastructure for Network Computing.
|
|
|
|
//
|
|
|
|
// The Initial Developer of the Original Code is the SETI@home project.
|
|
|
|
// Portions created by the SETI@home project are Copyright (C) 2002
|
|
|
|
// University of California at Berkeley. All Rights Reserved.
|
|
|
|
//
|
|
|
|
// Contributor(s):
|
|
|
|
//
|
|
|
|
// Revision History:
|
|
|
|
//
|
|
|
|
|
|
|
|
#if defined(__GNUG__) && !defined(__APPLE__)
|
2004-11-02 04:44:24 +00:00
|
|
|
#pragma implementation "BOINCTaskBar.h"
|
2004-10-23 07:13:18 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "stdwx.h"
|
|
|
|
#include "BOINCGUIApp.h"
|
2004-11-02 04:44:24 +00:00
|
|
|
#include "BOINCTaskBar.h"
|
2004-10-24 05:40:12 +00:00
|
|
|
#include "DlgAbout.h"
|
|
|
|
#include "Events.h"
|
2004-10-23 07:13:18 +00:00
|
|
|
|
|
|
|
#include "res/boinc.xpm"
|
|
|
|
|
|
|
|
|
2004-11-02 10:14:41 +00:00
|
|
|
IMPLEMENT_DYNAMIC_CLASS(CTaskBarIcon, wxTaskBarIconEx)
|
2004-10-23 07:13:18 +00:00
|
|
|
|
2004-11-02 10:14:41 +00:00
|
|
|
BEGIN_EVENT_TABLE (CTaskBarIcon, wxTaskBarIconEx)
|
2004-10-24 05:40:12 +00:00
|
|
|
EVT_MENU(wxID_OPEN, CTaskBarIcon::OnOpen)
|
2004-10-24 07:38:38 +00:00
|
|
|
EVT_MENU_RANGE(ID_TB_ACTIVITYRUNALWAYS, ID_TB_ACTIVITYSUSPEND, CTaskBarIcon::OnActivitySelection)
|
|
|
|
EVT_MENU_RANGE(ID_TB_NETWORKRUNALWAYS, ID_TB_NETWORKSUSPEND, CTaskBarIcon::OnNetworkSelection)
|
2004-10-24 05:40:12 +00:00
|
|
|
EVT_MENU(wxID_ABOUT, CTaskBarIcon::OnAbout)
|
2004-10-23 23:40:11 +00:00
|
|
|
EVT_MENU(wxID_EXIT, CTaskBarIcon::OnExit)
|
2005-01-07 07:32:23 +00:00
|
|
|
EVT_IDLE(CTaskBarIcon::OnIdle)
|
2004-10-24 07:38:38 +00:00
|
|
|
EVT_CLOSE(CTaskBarIcon::OnClose)
|
2004-10-25 10:20:43 +00:00
|
|
|
EVT_TASKBAR_MOVE(CTaskBarIcon::OnMouseMove)
|
|
|
|
EVT_TASKBAR_LEFT_DCLICK(CTaskBarIcon::OnLButtonDClick)
|
2004-11-03 21:06:12 +00:00
|
|
|
|
|
|
|
#ifdef __WXMSW__
|
|
|
|
EVT_TASKBAR_CONTEXT_MENU(CTaskBarIcon::OnContextMenu)
|
|
|
|
#endif
|
2004-11-23 07:45:11 +00:00
|
|
|
|
|
|
|
EVT_TASKBAR_RIGHT_DOWN(CTaskBarIcon::OnRButtonDown)
|
|
|
|
EVT_TASKBAR_RIGHT_UP(CTaskBarIcon::OnRButtonUp)
|
2004-10-23 07:13:18 +00:00
|
|
|
END_EVENT_TABLE ()
|
|
|
|
|
|
|
|
|
|
|
|
CTaskBarIcon::CTaskBarIcon() :
|
2004-11-02 10:14:41 +00:00
|
|
|
wxTaskBarIconEx()
|
2004-10-23 07:13:18 +00:00
|
|
|
{
|
2004-11-04 05:34:51 +00:00
|
|
|
m_iconTaskBarIcon = wxIcon( boinc_xpm );
|
|
|
|
m_dtLastHoverDetected = wxDateTime( (time_t)0 );
|
|
|
|
m_dtLastBalloonDisplayed = wxDateTime( (time_t)0 );
|
2004-10-23 23:40:11 +00:00
|
|
|
|
2004-11-04 05:34:51 +00:00
|
|
|
SetIcon( m_iconTaskBarIcon, wxEmptyString );
|
2004-10-23 07:13:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CTaskBarIcon::~CTaskBarIcon()
|
|
|
|
{
|
|
|
|
RemoveIcon();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-10-24 05:40:12 +00:00
|
|
|
void CTaskBarIcon::OnOpen( wxCommandEvent& WXUNUSED(event) )
|
|
|
|
{
|
2004-10-25 00:56:16 +00:00
|
|
|
ResetTaskBar();
|
2004-10-24 21:30:29 +00:00
|
|
|
|
2004-10-24 05:40:12 +00:00
|
|
|
CMainFrame* pFrame = wxGetApp().GetFrame();
|
|
|
|
wxASSERT(NULL != pFrame);
|
|
|
|
wxASSERT(wxDynamicCast(pFrame, CMainFrame));
|
|
|
|
|
|
|
|
if ( NULL != pFrame )
|
|
|
|
pFrame->Show();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CTaskBarIcon::OnActivitySelection( wxCommandEvent& event )
|
|
|
|
{
|
2004-10-25 00:56:16 +00:00
|
|
|
ResetTaskBar();
|
2004-10-24 21:30:29 +00:00
|
|
|
|
2004-10-24 05:40:12 +00:00
|
|
|
CMainDocument* pDoc = wxGetApp().GetDocument();
|
|
|
|
|
|
|
|
wxASSERT(NULL != pDoc);
|
|
|
|
wxASSERT(wxDynamicCast(pDoc, CMainDocument));
|
|
|
|
|
|
|
|
switch( event.GetId() )
|
|
|
|
{
|
2004-10-24 07:38:38 +00:00
|
|
|
case ID_TB_ACTIVITYRUNALWAYS:
|
2004-10-24 05:40:12 +00:00
|
|
|
pDoc->SetActivityRunMode( CMainDocument::MODE_ALWAYS );
|
|
|
|
break;
|
2004-10-24 07:38:38 +00:00
|
|
|
case ID_TB_ACTIVITYSUSPEND:
|
2004-10-24 05:40:12 +00:00
|
|
|
pDoc->SetActivityRunMode( CMainDocument::MODE_NEVER );
|
|
|
|
break;
|
2004-10-24 07:38:38 +00:00
|
|
|
case ID_TB_ACTIVITYRUNBASEDONPREPERENCES:
|
2004-10-24 05:40:12 +00:00
|
|
|
pDoc->SetActivityRunMode( CMainDocument::MODE_AUTO );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CTaskBarIcon::OnNetworkSelection( wxCommandEvent& event )
|
|
|
|
{
|
2004-10-25 00:56:16 +00:00
|
|
|
ResetTaskBar();
|
2004-10-24 21:30:29 +00:00
|
|
|
|
2004-10-24 05:40:12 +00:00
|
|
|
CMainDocument* pDoc = wxGetApp().GetDocument();
|
|
|
|
|
|
|
|
wxASSERT(NULL != pDoc);
|
|
|
|
wxASSERT(wxDynamicCast(pDoc, CMainDocument));
|
|
|
|
|
|
|
|
switch( event.GetId() )
|
|
|
|
{
|
2004-10-24 07:38:38 +00:00
|
|
|
case ID_TB_NETWORKSUSPEND:
|
2004-10-24 05:40:12 +00:00
|
|
|
if ( event.IsChecked() )
|
|
|
|
pDoc->SetNetworkRunMode( CMainDocument::MODE_ALWAYS );
|
|
|
|
else
|
|
|
|
pDoc->SetNetworkRunMode( CMainDocument::MODE_NEVER );
|
|
|
|
break;
|
2004-10-24 07:38:38 +00:00
|
|
|
case ID_TB_NETWORKRUNALWAYS:
|
|
|
|
case ID_TB_NETWORKRUNBASEDONPREPERENCES:
|
2004-10-24 05:40:12 +00:00
|
|
|
default:
|
|
|
|
pDoc->SetNetworkRunMode( CMainDocument::MODE_ALWAYS );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CTaskBarIcon::OnAbout( wxCommandEvent& WXUNUSED(event) )
|
|
|
|
{
|
2004-10-25 00:56:16 +00:00
|
|
|
ResetTaskBar();
|
2004-10-24 21:30:29 +00:00
|
|
|
|
2004-10-24 05:40:12 +00:00
|
|
|
CDlgAbout* pDlg = new CDlgAbout(NULL);
|
|
|
|
wxASSERT(NULL != pDlg);
|
|
|
|
|
|
|
|
pDlg->ShowModal();
|
|
|
|
|
|
|
|
if (pDlg)
|
|
|
|
pDlg->Destroy();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-10-23 23:40:11 +00:00
|
|
|
void CTaskBarIcon::OnExit( wxCommandEvent& WXUNUSED(event) )
|
2004-10-23 07:13:18 +00:00
|
|
|
{
|
2004-10-25 00:56:16 +00:00
|
|
|
ResetTaskBar();
|
2004-10-24 21:30:29 +00:00
|
|
|
|
2004-10-24 05:40:12 +00:00
|
|
|
CMainFrame* pFrame = wxGetApp().GetFrame();
|
|
|
|
wxASSERT(NULL != pFrame);
|
|
|
|
wxASSERT(wxDynamicCast(pFrame, CMainFrame));
|
|
|
|
|
2004-10-23 23:40:11 +00:00
|
|
|
if ( NULL != pFrame )
|
|
|
|
pFrame->Close(true);
|
2004-10-23 07:13:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-01-07 07:32:23 +00:00
|
|
|
void CTaskBarIcon::OnIdle( wxIdleEvent& event )
|
|
|
|
{
|
|
|
|
wxGetApp().UpdateSystemIdleDetection();
|
|
|
|
event.Skip();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-10-23 23:40:11 +00:00
|
|
|
void CTaskBarIcon::OnClose( wxCloseEvent& event )
|
2004-10-23 07:13:18 +00:00
|
|
|
{
|
2004-10-25 00:56:16 +00:00
|
|
|
ResetTaskBar();
|
2004-10-24 21:30:29 +00:00
|
|
|
|
2004-10-24 05:40:12 +00:00
|
|
|
CMainFrame* pFrame = wxGetApp().GetFrame();
|
|
|
|
wxASSERT(NULL != pFrame);
|
|
|
|
wxASSERT(wxDynamicCast(pFrame, CMainFrame));
|
|
|
|
|
2004-10-23 23:40:11 +00:00
|
|
|
if ( NULL != pFrame )
|
|
|
|
pFrame->Close(true);
|
2004-11-05 21:23:40 +00:00
|
|
|
|
|
|
|
event.Skip();
|
2004-10-23 07:13:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-10-25 10:20:43 +00:00
|
|
|
void CTaskBarIcon::OnMouseMove( wxTaskBarIconEvent& event )
|
2004-10-23 07:13:18 +00:00
|
|
|
{
|
2004-10-23 23:40:11 +00:00
|
|
|
|
2004-11-04 05:34:51 +00:00
|
|
|
wxTimeSpan ts(wxDateTime::Now() - m_dtLastHoverDetected);
|
|
|
|
if ( ts.GetSeconds() >= 10 )
|
|
|
|
m_dtLastHoverDetected = wxDateTime::Now();
|
|
|
|
|
|
|
|
wxTimeSpan tsLastHover(wxDateTime::Now() - m_dtLastHoverDetected);
|
|
|
|
wxTimeSpan tsLastBalloon(wxDateTime::Now() - m_dtLastBalloonDisplayed);
|
|
|
|
if ( (tsLastHover.GetSeconds() >= 2) && (tsLastBalloon.GetSeconds() >= 10) )
|
2004-10-23 23:40:11 +00:00
|
|
|
{
|
2004-11-04 05:34:51 +00:00
|
|
|
m_dtLastBalloonDisplayed = wxDateTime::Now();
|
2004-10-23 23:40:11 +00:00
|
|
|
|
|
|
|
wxString strTitle = wxGetApp().GetAppName();
|
2004-11-04 05:34:51 +00:00
|
|
|
wxString strMachineName = wxEmptyString;
|
2004-10-23 23:40:11 +00:00
|
|
|
wxString strMessage = wxEmptyString;
|
|
|
|
wxString strBuffer = wxEmptyString;
|
|
|
|
wxString strProjectName = wxEmptyString;
|
|
|
|
float fProgress = 0;
|
|
|
|
bool bIsActive = false;
|
|
|
|
bool bIsExecuting = false;
|
|
|
|
bool bIsDownloaded = false;
|
|
|
|
wxInt32 iResultCount = 0;
|
|
|
|
wxInt32 iIndex = 0;
|
|
|
|
CMainDocument* pDoc = wxGetApp().GetDocument();
|
|
|
|
|
|
|
|
wxASSERT(NULL != pDoc);
|
|
|
|
wxASSERT(wxDynamicCast(pDoc, CMainDocument));
|
|
|
|
|
|
|
|
|
2004-11-04 05:34:51 +00:00
|
|
|
pDoc->GetConnectedComputerName( strMachineName );
|
|
|
|
if ( strMachineName.empty() )
|
|
|
|
strTitle = strTitle + wxT(" - (localhost)");
|
|
|
|
else
|
|
|
|
strTitle = strTitle + wxT(" - (") + strMachineName + wxT(")");
|
|
|
|
|
|
|
|
|
|
|
|
iResultCount = pDoc->GetWorkCount();
|
2004-10-23 23:40:11 +00:00
|
|
|
for ( iIndex = 0; iIndex < iResultCount; iIndex++ )
|
|
|
|
{
|
2004-11-17 09:27:06 +00:00
|
|
|
bIsDownloaded = ( CMainDocument::FILES_DOWNLOADED == pDoc->GetWorkState( iIndex ) );
|
2004-10-23 23:40:11 +00:00
|
|
|
bIsActive = ( pDoc->IsWorkActive( iIndex ) );
|
2004-11-17 09:27:06 +00:00
|
|
|
bIsExecuting = ( CMainDocument::SCHED_SCHEDULED == pDoc->GetWorkSchedulerState( iIndex ) );
|
2004-10-23 23:40:11 +00:00
|
|
|
if ( !( bIsActive ) || !( bIsDownloaded ) || !( bIsExecuting ) ) continue;
|
|
|
|
|
|
|
|
pDoc->GetWorkProjectName( iIndex, strProjectName );
|
|
|
|
pDoc->GetWorkFractionDone( iIndex, fProgress );
|
|
|
|
|
2004-10-25 20:58:06 +00:00
|
|
|
strBuffer.Printf(wxT( "%s: %.2f%%\n"), strProjectName.c_str(), fProgress * 100 );
|
2004-10-23 23:40:11 +00:00
|
|
|
strMessage += strBuffer;
|
|
|
|
}
|
|
|
|
|
2004-11-04 05:34:51 +00:00
|
|
|
SetBalloon( m_iconTaskBarIcon, strTitle, strMessage );
|
2004-10-23 23:40:11 +00:00
|
|
|
}
|
2004-10-23 07:13:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-11-03 21:06:12 +00:00
|
|
|
void CTaskBarIcon::OnLButtonDClick( wxTaskBarIconEvent& event )
|
|
|
|
{
|
|
|
|
ResetTaskBar();
|
|
|
|
|
|
|
|
CMainFrame* pFrame = wxGetApp().GetFrame();
|
|
|
|
wxASSERT(NULL != pFrame);
|
|
|
|
wxASSERT(wxDynamicCast(pFrame, CMainFrame));
|
|
|
|
|
|
|
|
if ( NULL != pFrame )
|
|
|
|
pFrame->Show();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef __WXMSW__
|
|
|
|
|
|
|
|
|
|
|
|
void CTaskBarIcon::OnContextMenu( wxTaskBarIconExEvent& event )
|
|
|
|
{
|
|
|
|
CreateContextMenu();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-11-23 07:45:11 +00:00
|
|
|
#endif
|
2004-11-03 21:06:12 +00:00
|
|
|
|
|
|
|
|
2004-10-25 10:20:43 +00:00
|
|
|
void CTaskBarIcon::OnRButtonDown( wxTaskBarIconEvent& event )
|
2004-11-03 21:06:12 +00:00
|
|
|
{
|
2004-11-23 07:45:11 +00:00
|
|
|
if (!IsBalloonsSupported())
|
|
|
|
{
|
|
|
|
m_bButtonPressed = true;
|
|
|
|
}
|
2004-11-03 21:06:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-11-23 07:45:11 +00:00
|
|
|
void CTaskBarIcon::OnRButtonUp( wxTaskBarIconEvent& event )
|
|
|
|
{
|
|
|
|
if (!IsBalloonsSupported())
|
|
|
|
{
|
|
|
|
if (m_bButtonPressed)
|
|
|
|
{
|
|
|
|
CreateContextMenu();
|
|
|
|
m_bButtonPressed = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-11-03 21:06:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
void CTaskBarIcon::ResetTaskBar()
|
|
|
|
{
|
|
|
|
#ifdef __WXMSW___
|
2004-11-04 05:34:51 +00:00
|
|
|
SetBalloon( m_iconTaskBarIcon, wxT(""), wxT("") );
|
2004-11-03 21:06:12 +00:00
|
|
|
#else
|
2004-11-04 05:34:51 +00:00
|
|
|
SetIcon( m_iconTaskBarIcon, wxT("") );
|
2004-11-03 21:06:12 +00:00
|
|
|
#endif
|
|
|
|
|
2004-11-04 05:34:51 +00:00
|
|
|
m_dtLastBalloonDisplayed = wxDateTime::Now();
|
2004-11-03 21:06:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CTaskBarIcon::CreateContextMenu()
|
2004-10-23 07:13:18 +00:00
|
|
|
{
|
2004-10-25 00:56:16 +00:00
|
|
|
ResetTaskBar();
|
2004-10-24 07:43:33 +00:00
|
|
|
|
2004-10-24 05:40:12 +00:00
|
|
|
CMainDocument* pDoc = wxGetApp().GetDocument();
|
|
|
|
wxMenu* menu = new wxMenu;
|
2004-10-25 20:58:06 +00:00
|
|
|
wxMenuItem* menuItem = NULL;
|
2004-10-24 05:40:12 +00:00
|
|
|
wxInt32 iActivityMode = -1;
|
|
|
|
wxInt32 iNetworkMode = -1;
|
|
|
|
|
|
|
|
wxASSERT(NULL != pDoc);
|
|
|
|
wxASSERT(wxDynamicCast(pDoc, CMainDocument));
|
|
|
|
wxASSERT(NULL != menu);
|
|
|
|
|
2004-10-25 20:58:06 +00:00
|
|
|
#ifdef __WXMSW__
|
|
|
|
|
|
|
|
wxFont font = wxSystemSettings::GetFont( wxSYS_DEFAULT_GUI_FONT );
|
|
|
|
font.SetWeight( wxBOLD );
|
|
|
|
|
|
|
|
menuItem = new wxMenuItem( menu, wxID_OPEN, _("&Open BOINC Manager..."), wxEmptyString );
|
|
|
|
menuItem->SetFont( font );
|
|
|
|
|
|
|
|
menu->Append( menuItem );
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
menu->Append( wxID_OPEN, _("&Open BOINC Manager..."), wxEmptyString );
|
|
|
|
|
|
|
|
#endif
|
2004-10-24 05:40:12 +00:00
|
|
|
menu->AppendSeparator();
|
2004-10-24 07:38:38 +00:00
|
|
|
menu->AppendRadioItem( ID_TB_ACTIVITYRUNALWAYS, _("&Run always"), wxEmptyString );
|
|
|
|
menu->AppendRadioItem( ID_TB_ACTIVITYRUNBASEDONPREPERENCES, _("Run based on &preferences"), wxEmptyString );
|
|
|
|
menu->AppendRadioItem( ID_TB_ACTIVITYSUSPEND, _("&Suspend"), wxEmptyString );
|
2004-10-24 05:40:12 +00:00
|
|
|
menu->AppendSeparator();
|
2004-11-22 19:17:13 +00:00
|
|
|
menu->AppendCheckItem( ID_TB_NETWORKSUSPEND, _("&Disable BOINC network access"), wxEmptyString );
|
2004-10-24 05:40:12 +00:00
|
|
|
menu->AppendSeparator();
|
|
|
|
menu->Append( wxID_ABOUT, _("&About BOINC Manager..."), wxEmptyString );
|
|
|
|
menu->AppendSeparator();
|
|
|
|
menu->Append( wxID_EXIT, _("E&xit"), wxEmptyString );
|
|
|
|
|
|
|
|
pDoc->GetActivityRunMode( iActivityMode );
|
|
|
|
switch( iActivityMode )
|
|
|
|
{
|
|
|
|
case CMainDocument::MODE_ALWAYS:
|
2004-10-24 07:38:38 +00:00
|
|
|
menu->Check( ID_TB_ACTIVITYRUNALWAYS, true );
|
2004-10-24 05:40:12 +00:00
|
|
|
break;
|
|
|
|
case CMainDocument::MODE_NEVER:
|
2004-10-24 07:38:38 +00:00
|
|
|
menu->Check( ID_TB_ACTIVITYSUSPEND, true );
|
2004-10-24 05:40:12 +00:00
|
|
|
break;
|
|
|
|
case CMainDocument::MODE_AUTO:
|
2004-10-24 07:38:38 +00:00
|
|
|
menu->Check( ID_TB_ACTIVITYRUNBASEDONPREPERENCES, true );
|
2004-10-24 05:40:12 +00:00
|
|
|
break;
|
|
|
|
}
|
2004-10-23 07:13:18 +00:00
|
|
|
|
2004-10-24 05:40:12 +00:00
|
|
|
pDoc->GetNetworkRunMode( iNetworkMode );
|
2004-10-31 21:03:29 +00:00
|
|
|
if ( CMainDocument::MODE_NEVER == iNetworkMode )
|
|
|
|
menu->Check( ID_TB_NETWORKSUSPEND, true );
|
|
|
|
else
|
|
|
|
menu->Check( ID_TB_NETWORKSUSPEND, false );
|
2004-10-23 07:13:18 +00:00
|
|
|
|
2004-10-23 23:40:11 +00:00
|
|
|
PopupMenu( menu );
|
2004-10-23 07:13:18 +00:00
|
|
|
|
2004-10-23 23:40:11 +00:00
|
|
|
delete menu;
|
2004-10-23 07:13:18 +00:00
|
|
|
}
|
|
|
|
|
2004-12-08 00:40:19 +00:00
|
|
|
|
2005-01-02 18:29:53 +00:00
|
|
|
const char *BOINC_RCSID_531575eeaa = "$Id$";
|