📄 searchresultswnd.cpp
字号:
//this file is part of eMule
//Copyright (C)2002 Merkur ( devs@emule-project.net / http://www.emule-project.net )
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either
//version 2 of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "stdafx.h"
#include "emule.h"
#include "SearchDlg.h"
#include "SearchResultsWnd.h"
#include "SearchParamsWnd.h"
#include "SearchParams.h"
#include "Packets.h"
#include "OtherFunctions.h"
#include "SearchList.h"
#include "Sockets.h"
#include "ServerList.h"
#include "Server.h"
#include "SafeFile.h"
#include "DownloadQueue.h"
#include "Statistics.h"
#include "emuledlg.h"
#include "opcodes.h"
#include "ED2KLink.h"
#include "Kademlia/Kademlia/Kademlia.h"
#include "kademlia/kademlia/SearchManager.h"
#include "kademlia/kademlia/search.h"
#include "SearchExpr.h"
#define USE_FLEX
#include "Parser.hpp"
#include "Scanner.h"
#include "HelpIDs.h"
#include "Exceptions.h"
#include "StringConversion.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
extern int yyparse();
extern int yyerror(const char* errstr);
#ifdef _UNICODE
extern int yyerror(LPCTSTR errstr);
#endif
extern LPCTSTR _aszInvKadKeywordChars;
enum ESearchTimerID
{
TimerServerTimeout = 1,
TimerGlobalSearch
};
enum ESearchResultImage
{
sriServerActive,
sriGlobalActive,
sriKadActice,
sriClient,
sriServer,
sriGlobal,
sriKad
};
static const LPCTSTR _apszSearchExprKeywords[] = { _T("AND"), _T("OR"), _T("NOT"), NULL };
static const TCHAR _szSearchExprSeperators[] = _T(" ()<>=");
// CSearchResultsWnd dialog
IMPLEMENT_DYNCREATE(CSearchResultsWnd, CResizableFormView)
BEGIN_MESSAGE_MAP(CSearchResultsWnd, CResizableFormView)
ON_WM_TIMER()
ON_BN_CLICKED(IDC_SDOWNLOAD, OnBnClickedSdownload)
ON_BN_CLICKED(IDC_CLEARALL, OnBnClickedClearall)
ON_NOTIFY(TCN_SELCHANGE, IDC_TAB1, OnTcnSelchangeTab1)
ON_MESSAGE(WM_CLOSETAB, OnCloseTab)
ON_WM_DESTROY()
ON_WM_SYSCOLORCHANGE()
ON_WM_SIZE()
ON_WM_CLOSE()
ON_WM_CREATE()
ON_WM_HELPINFO()
ON_MESSAGE(WM_IDLEUPDATECMDUI, OnIdleUpdateCmdUI)
ON_BN_CLICKED(IDC_OPEN_PARAMS_WND, OnBnClickedOpenParamsWnd)
ON_WM_SYSCOMMAND()
END_MESSAGE_MAP()
CSearchResultsWnd::CSearchResultsWnd(CWnd* pParent /*=NULL*/)
: CResizableFormView(CSearchResultsWnd::IDD)
{
m_nSearchID = 0x80000000;
global_search_timer = 0;
searchpacket = NULL;
canceld = false;
servercount = 0;
globsearch = false;
icon_search = NULL;
m_uTimerLocalServer = 0;
m_iSentMoreReq = 0;
searchselect.m_bCloseable = true;
}
CSearchResultsWnd::~CSearchResultsWnd()
{
if (globsearch)
delete searchpacket;
if (icon_search)
VERIFY( DestroyIcon(icon_search) );
if (m_uTimerLocalServer)
VERIFY( KillTimer(m_uTimerLocalServer) );
}
void CSearchResultsWnd::OnInitialUpdate()
{
CResizableFormView::OnInitialUpdate();
InitWindowStyles(this);
theApp.searchlist->SetOutputWnd(&searchlistctrl);
searchlistctrl.Init(theApp.searchlist);
SetAllIcons();
Localize();
searchprogress.SetStep(1);
global_search_timer = 0;
globsearch = false;
AddAnchor(IDC_SDOWNLOAD,BOTTOM_LEFT);
AddAnchor(IDC_SEARCHLIST,TOP_LEFT,BOTTOM_RIGHT);
AddAnchor(IDC_PROGRESS1,BOTTOM_LEFT,BOTTOM_RIGHT);
AddAnchor(IDC_CLEARALL, TOP_RIGHT);
AddAnchor(IDC_OPEN_PARAMS_WND, TOP_RIGHT);
AddAnchor(searchselect.m_hWnd,TOP_LEFT,TOP_RIGHT);
AddAnchor(IDC_STATIC_DLTOof,BOTTOM_LEFT);
AddAnchor(IDC_CATTAB2,BOTTOM_LEFT,BOTTOM_RIGHT);
ShowSearchSelector(false);
if (theApp.emuledlg->m_fontMarlett.m_hObject){
GetDlgItem(IDC_STATIC_DLTOof)->SetFont(&theApp.emuledlg->m_fontMarlett);
GetDlgItem(IDC_STATIC_DLTOof)->SetWindowText(_T("8")); // show a right-arrow
}
}
void CSearchResultsWnd::DoDataExchange(CDataExchange* pDX)
{
CResizableFormView::DoDataExchange(pDX);
DDX_Control(pDX, IDC_SEARCHLIST, searchlistctrl);
DDX_Control(pDX, IDC_PROGRESS1, searchprogress);
DDX_Control(pDX, IDC_TAB1, searchselect);
DDX_Control(pDX, IDC_CATTAB2, m_cattabs);
}
void CSearchResultsWnd::StartSearch(SSearchParams* pParams)
{
switch (pParams->eType)
{
case SearchTypeEd2kServer:
case SearchTypeEd2kGlobal:
case SearchTypeKademlia:
StartNewSearch(pParams);
break;
case SearchTypeFileDonkey:
ShellOpenFile(CreateWebQuery(pParams));
delete pParams;
return;
break;
case SearchTypeVeryCD: //VeryCD
ShellOpenFile(CreateWebQuery(pParams));
delete pParams;
return;
break;
default:
ASSERT(0);
delete pParams;
}
}
void CSearchResultsWnd::OnTimer(UINT nIDEvent)
{
CResizableFormView::OnTimer(nIDEvent);
if (m_uTimerLocalServer != 0 && nIDEvent == m_uTimerLocalServer)
{
if (thePrefs.GetDebugServerSearchesLevel() > 0)
Debug(_T("Timeout waiting on search results of local server\n"));
// the local server did not answer within the timeout
VERIFY( KillTimer(m_uTimerLocalServer) );
m_uTimerLocalServer = 0;
// start the global search
if (globsearch)
{
if (global_search_timer == 0)
VERIFY( (global_search_timer = SetTimer(TimerGlobalSearch, 750, 0)) != NULL );
}
else
CancelSearch();
}
else if (nIDEvent == global_search_timer)
{
if (theApp.serverconnect->IsConnected()){
CServer* toask = theApp.serverlist->GetNextSearchServer();
if (toask == theApp.serverlist->GetServerByAddress(theApp.serverconnect->GetCurrentServer()->GetAddress(),theApp.serverconnect->GetCurrentServer()->GetPort()))
toask = theApp.serverlist->GetNextSearchServer();
if (toask && servercount < theApp.serverlist->GetServerCount()-1){
servercount++;
if (toask->GetUDPFlags() & SRV_UDPFLG_EXT_GETFILES)
searchpacket->opcode = OP_GLOBSEARCHREQ2;
else
searchpacket->opcode = OP_GLOBSEARCHREQ;
if (thePrefs.GetDebugServerUDPLevel() > 0)
Debug(_T(">>> Sending %s to server %s:%u (%u of %u)\n"), (searchpacket->opcode == OP_GLOBSEARCHREQ2) ? _T("OP__GlobSearchReq2") : _T("OP__GlobSearchReq"), toask->GetAddress(), toask->GetPort(), servercount, theApp.serverlist->GetServerCount());
theStats.AddUpDataOverheadServer(searchpacket->size);
theApp.serverconnect->SendUDPPacket(searchpacket,toask,false);
searchprogress.StepIt();
}
else
CancelSearch();
}
else
CancelSearch();
}
else
ASSERT( 0 );
}
void CSearchResultsWnd::SetSearchResultsIcon(UINT uSearchID, int iImage)
{
int iTabItems = searchselect.GetItemCount();
for (int i = 0; i < iTabItems; i++)
{
TCITEM tci;
tci.mask = TCIF_PARAM;
if (searchselect.GetItem(i, &tci) && tci.lParam != NULL && ((const SSearchParams*)tci.lParam)->dwSearchID == uSearchID)
{
tci.mask = TCIF_IMAGE;
tci.iImage = iImage;
searchselect.SetItem(i, &tci);
break;
}
}
}
void CSearchResultsWnd::SetActiveSearchResultsIcon(UINT uSearchID)
{
SSearchParams* pParams = GetSearchResultsParams(uSearchID);
if (pParams)
{
int iImage;
if (pParams->eType == SearchTypeKademlia)
iImage = sriKadActice;
else if (pParams->eType == SearchTypeEd2kGlobal)
iImage = sriGlobalActive;
else
iImage = sriServerActive;
SetSearchResultsIcon(uSearchID, iImage);
}
}
void CSearchResultsWnd::SetInactiveSearchResultsIcon(UINT uSearchID)
{
SSearchParams* pParams = GetSearchResultsParams(uSearchID);
if (pParams)
{
int iImage;
if (pParams->eType == SearchTypeKademlia)
iImage = sriKad;
else if (pParams->eType == SearchTypeEd2kGlobal)
iImage = sriGlobal;
else
iImage = sriServer;
SetSearchResultsIcon(uSearchID, iImage);
}
}
SSearchParams* CSearchResultsWnd::GetSearchResultsParams(UINT uSearchID) const
{
int iTabItems = searchselect.GetItemCount();
for (int i = 0; i < iTabItems; i++)
{
TCITEM tci;
tci.mask = TCIF_PARAM;
if (searchselect.GetItem(i, &tci) && tci.lParam != NULL && ((const SSearchParams*)tci.lParam)->dwSearchID == uSearchID)
return (SSearchParams*)tci.lParam;
}
return NULL;
}
void CSearchResultsWnd::CancelSearch()
{
SetInactiveSearchResultsIcon(m_nSearchID);
canceld = true;
// delete any global search timer
if (globsearch){
delete searchpacket;
searchpacket = NULL;
}
globsearch = false;
if (global_search_timer){
VERIFY( KillTimer(global_search_timer) );
global_search_timer = 0;
searchprogress.SetPos(0);
}
// delete local server timeout timer
if (m_uTimerLocalServer){
VERIFY( KillTimer(m_uTimerLocalServer) );
m_uTimerLocalServer = 0;
}
// set focus
CWnd* pWndFocus = GetFocus();
m_pwndParams->m_ctlCancel.EnableWindow(false);
if (pWndFocus && pWndFocus->m_hWnd == m_pwndParams->m_ctlCancel.m_hWnd)
m_pwndParams->m_ctlName.SetFocus();
m_pwndParams->m_ctlStart.EnableWindow(true);
}
void CSearchResultsWnd::CancelKadSearch(UINT uSearchID)
{
SetInactiveSearchResultsIcon(uSearchID);
}
void CSearchResultsWnd::LocalSearchEnd(uint16 count, bool bMoreResultsAvailable)
{
// local server has answered, kill the timeout timer
if (m_uTimerLocalServer){
VERIFY( KillTimer(m_uTimerLocalServer) );
m_uTimerLocalServer = 0;
}
if (!canceld && count > MAX_RESULTS)
CancelSearch();
if (!canceld){
if (!globsearch){
SetInactiveSearchResultsIcon(m_nSearchID);
m_pwndParams->m_ctlStart.EnableWindow(TRUE);
CWnd* pWndFocus = GetFocus();
m_pwndParams->m_ctlCancel.EnableWindow(FALSE);
if (pWndFocus && pWndFocus->m_hWnd == m_pwndParams->m_ctlCancel.m_hWnd)
m_pwndParams->m_ctlName.SetFocus();
}
else{
VERIFY( (global_search_timer = SetTimer(TimerGlobalSearch, 750, 0)) != NULL );
}
}
m_pwndParams->m_ctlMore.EnableWindow(bMoreResultsAvailable && m_iSentMoreReq < MAX_MORE_SEARCH_REQ);
}
void CSearchResultsWnd::AddUDPResult(uint16 count)
{
if (!canceld && count > MAX_RESULTS)
CancelSearch();
}
void CSearchResultsWnd::OnBnClickedSdownload()
{
//start download(s)
DownloadSelected();
}
void CSearchResultsWnd::OnNMDblclkSearchlist(NMHDR *pNMHDR, LRESULT *pResult)
{
OnBnClickedSdownload();
*pResult = 0;
}
CString CSearchResultsWnd::CreateWebQuery(SSearchParams* pParams)
{
CString query;
switch (pParams->eType)
{
case SearchTypeFileDonkey:
query = _T("http://www.filedonkey.com/search.html?");
query += _T("pattern=") + ToQueryString(pParams->strExpression);
if (pParams->strFileType == ED2KFTSTR_AUDIO)
query += _T("&media=Audio");
else if (pParams->strFileType == ED2KFTSTR_VIDEO)
query += _T("&media=Video");
else if (pParams->strFileType == ED2KFTSTR_PROGRAM)
query += _T("&media=Pro");
query += _T("&requestby=emule");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -