//this file is part of eMule
//Copyright (C)2002 Merkur ( merkur-@users.sourceforge.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.


// TransferWnd.cpp : implementation file
//

#include "stdafx.h"
#include "emule.h"
#include "SearchDlg.h"
#include "TransferWnd.h"
#include "otherfunctions.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif


// CTransferWnd dialog

IMPLEMENT_DYNAMIC(CTransferWnd, CDialog)
CTransferWnd::CTransferWnd(CWnd* pParent /*=NULL*/)
	: CResizableDialog(CTransferWnd::IDD, pParent)
{
}

CTransferWnd::~CTransferWnd()
{
	DestroyIcon(icon_download);
}

BEGIN_MESSAGE_MAP(CTransferWnd, CResizableDialog)
	ON_NOTIFY(LVN_HOTTRACK, IDC_UPLOADLIST, OnHoverUploadList)
	ON_NOTIFY(LVN_HOTTRACK, IDC_QUEUELIST, OnHoverUploadList)
	ON_NOTIFY(LVN_HOTTRACK, IDC_DOWNLOADLIST, OnHoverDownloadList)
	ON_NOTIFY(LVN_HOTTRACK, IDC_CLIENTLIST , OnHoverUploadList)
	ON_NOTIFY(TCN_SELCHANGE, IDC_DLTAB, OnTcnSelchangeDltab)
	ON_NOTIFY(NM_RCLICK, IDC_DLTAB, OnNMRclickDltab)
	ON_NOTIFY(LVN_BEGINDRAG, IDC_DOWNLOADLIST, OnLvnBegindrag)
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()
	ON_NOTIFY(LVN_KEYDOWN, IDC_DOWNLOADLIST, OnLvnKeydownDownloadlist)
	ON_NOTIFY(NM_TABMOVED, IDC_DLTAB, OnTabMovement)
END_MESSAGE_MAP()


BOOL CTransferWnd::OnInitDialog(){
	CResizableDialog::OnInitDialog();
	InitWindowStyles(this);
	windowtransferstate = 1;

	uploadlistctrl.Init();
	downloadlistctrl.Init();
	queuelistctrl.Init();
	clientlistctrl.Init();
	queuelistctrl.Hide();
	clientlistctrl.Hide();
	uploadlistctrl.Visable();

    Localize(); // i_a 

	icon_download=(HICON)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_DIRECTDOWNLOAD), IMAGE_ICON, 16, 16, 0);
	((CStatic*)GetDlgItem(IDC_DOWNLOAD_ICO))->SetIcon(icon_download);

	m_uplBtn.SetIcon(IDI_UPLOAD);	m_uplBtn.SetAlign(CButtonST::ST_ALIGN_HORIZ);
	m_uplBtn.SetFlat();
	m_uplBtn.SetLeftAlign(true); 
	
	AddAnchor(IDC_DOWNLOADLIST,TOP_LEFT,CSize(100, theApp.glob_prefs->GetSplitterbarPosition() ));
	AddAnchor(IDC_UPLOADLIST,CSize(0,theApp.glob_prefs->GetSplitterbarPosition()),BOTTOM_RIGHT);
	AddAnchor(IDC_QUEUELIST,CSize(0,theApp.glob_prefs->GetSplitterbarPosition()),BOTTOM_RIGHT);
	AddAnchor(IDC_CLIENTLIST,CSize(0,theApp.glob_prefs->GetSplitterbarPosition()),BOTTOM_RIGHT);
	AddAnchor(IDC_UPLOAD_ICO,CSize(0,theApp.glob_prefs->GetSplitterbarPosition()),BOTTOM_RIGHT);
	AddAnchor(IDC_QUEUECOUNT,BOTTOM_LEFT);
	AddAnchor(IDC_TSTATIC1,BOTTOM_LEFT);
	AddAnchor(IDC_QUEUE_REFRESH_BUTTON, BOTTOM_RIGHT);
	AddAnchor(IDC_DLTAB,CSize(50,0) ,TOP_RIGHT);

	// splitting functionality
	CRect rc,rcSpl,rcDown;

	GetWindowRect(rc);
	ScreenToClient(rc);
	
	rcSpl=rc; rcSpl.top=rc.bottom-100 ; rcSpl.bottom=rcSpl.top+5;rcSpl.left=55;
	m_wndSplitter.Create(WS_CHILD | WS_VISIBLE, rcSpl, this, IDC_SPLITTER);
	SetInitLayout();
	
	//cats
	rightclickindex=-1;

	downloadlistactive=true;
	m_bIsDragging=false;

	// show & cat-tabs
  	sprintf(theApp.glob_prefs->GetCategory(0)->title, GetCatTitle(theApp.glob_prefs->GetAllcatType()) );

	sprintf(theApp.glob_prefs->GetCategory(0)->incomingpath,theApp.glob_prefs->GetIncomingDir());
	for (int ix=0;ix<theApp.glob_prefs->GetCatCount();ix++)
		m_dlTab.InsertItem(ix,theApp.glob_prefs->GetCategory(ix)->title );

	// create tooltip control for download categories
	m_tooltip.Create(this, TTS_NOPREFIX);
	m_dlTab.SetToolTips(&m_tooltip);
	UpdateTabToolTips();
	m_tooltip.SendMessage(TTM_SETMAXTIPWIDTH, 0, SHRT_MAX); // recognize \n chars!
	m_tooltip.SetDelayTime(TTDT_AUTOPOP, 20000);
	m_tooltip.SetDelayTime(TTDT_INITIAL, 0);
	m_tooltip.Activate(TRUE);

	UpdateListCount(windowtransferstate);
	VerifyCatTabSize();

	return true;
}

void CTransferWnd::ShowQueueCount(uint32 number){
	char buffer[100];
	sprintf(buffer,"%u (%u "+ GetResString(IDS_BANNED).MakeLower() +")",number,theApp.clientlist->GetBannedCount() );
	this->GetDlgItem(IDC_QUEUECOUNT)->SetWindowText(buffer);
}

void CTransferWnd::DoDataExchange(CDataExchange* pDX)
{
	CResizableDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_UPLOADLIST, uploadlistctrl);
	DDX_Control(pDX, IDC_DOWNLOADLIST, downloadlistctrl);
	DDX_Control(pDX, IDC_QUEUELIST, queuelistctrl);
	DDX_Control(pDX, IDC_CLIENTLIST, clientlistctrl);
	DDX_Control(pDX, IDC_UPLOAD_ICO, m_uplBtn);
	DDX_Control(pDX, IDC_DLTAB, m_dlTab);
}

void CTransferWnd::SetInitLayout() {
		CRect rcDown,rcSpl,rcW;
		CWnd* pWnd;

		GetWindowRect(rcW);
		ScreenToClient(rcW);

		LONG splitpos=(theApp.glob_prefs->GetSplitterbarPosition()*rcW.Height())/100;

		pWnd = GetDlgItem(IDC_DOWNLOADLIST);
		pWnd->GetWindowRect(rcDown);
		ScreenToClient(rcDown);
		rcDown.right=rcW.right-7;
		rcDown.bottom=splitpos-5;
		downloadlistctrl.MoveWindow(rcDown);
		
		pWnd = GetDlgItem(IDC_UPLOADLIST);
		pWnd->GetWindowRect(rcDown);
		ScreenToClient(rcDown);
		rcDown.right=rcW.right-7;
		rcDown.bottom=rcW.bottom-20;
		rcDown.top=splitpos+20;
		uploadlistctrl.MoveWindow(rcDown);

		pWnd = GetDlgItem(IDC_QUEUELIST);
		pWnd->GetWindowRect(rcDown);
		ScreenToClient(rcDown);
		rcDown.right=rcW.right-7;
		rcDown.bottom=rcW.bottom-20;
		rcDown.top=splitpos+20;
		queuelistctrl.MoveWindow(rcDown);

		pWnd = GetDlgItem(IDC_CLIENTLIST);
		pWnd->GetWindowRect(rcDown);
		ScreenToClient(rcDown);
		rcDown.right=rcW.right-7;
		rcDown.bottom=rcW.bottom-20;
		rcDown.top=splitpos+20;
		clientlistctrl.MoveWindow(rcDown);

		rcSpl=rcDown;
		rcSpl.top=rcDown.bottom+4;rcSpl.bottom=rcSpl.top+7;rcSpl.left=(rcDown.right/2)-50;rcSpl.right=rcSpl.left+100;
		m_wndSplitter.MoveWindow(rcSpl,true);

		DoResize(0);
}

void CTransferWnd::DoResize(int delta)
{
	CSplitterControl::ChangeHeight(&downloadlistctrl, delta);
	CSplitterControl::ChangeHeight(&uploadlistctrl, -delta, CW_BOTTOMALIGN);
	CSplitterControl::ChangeHeight(&queuelistctrl, -delta, CW_BOTTOMALIGN);
	CSplitterControl::ChangeHeight(&clientlistctrl, -delta, CW_BOTTOMALIGN);

	UpdateSplitterRange();

	Invalidate();
	UpdateWindow();
}

// setting splitter range limits
void CTransferWnd::UpdateSplitterRange()
{
		CRect rcDown,rcUp,rcW,rcSpl;
		CWnd* pWnd;

		GetWindowRect(rcW);
		ScreenToClient(rcW);

		pWnd = GetDlgItem(IDC_DOWNLOADLIST);
		pWnd->GetWindowRect(rcDown);
		ScreenToClient(rcDown);

		pWnd = GetDlgItem(IDC_UPLOADLIST);
		pWnd->GetWindowRect(rcUp);
		ScreenToClient(rcUp);

		pWnd = GetDlgItem(IDC_QUEUELIST);
		pWnd->GetWindowRect(rcUp);
		ScreenToClient(rcUp);

		pWnd = GetDlgItem(IDC_CLIENTLIST);
		pWnd->GetWindowRect(rcUp);
		ScreenToClient(rcUp);

		theApp.glob_prefs->SetSplitterbarPosition((rcDown.bottom*100)/rcW.Height());

		RemoveAnchor(IDC_DOWNLOADLIST);
		RemoveAnchor(IDC_UPLOADLIST);
		RemoveAnchor(IDC_QUEUELIST);
		RemoveAnchor(IDC_CLIENTLIST);
		AddAnchor(IDC_DOWNLOADLIST,TOP_LEFT,CSize(100,theApp.glob_prefs->GetSplitterbarPosition() ));
		AddAnchor(IDC_UPLOADLIST,CSize(0,theApp.glob_prefs->GetSplitterbarPosition()),BOTTOM_RIGHT);
		AddAnchor(IDC_QUEUELIST,CSize(0,theApp.glob_prefs->GetSplitterbarPosition()),BOTTOM_RIGHT);
		AddAnchor(IDC_CLIENTLIST,CSize(0,theApp.glob_prefs->GetSplitterbarPosition()),BOTTOM_RIGHT);

		m_wndSplitter.SetRange(rcDown.top+50 , rcUp.bottom-40);

}


LRESULT CTransferWnd::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{
	switch (message) {
		// arrange transferwindow layout
		case WM_PAINT:
			if (m_wndSplitter) {
				CRect rcDown,rcSpl,rcW;
				CWnd* pWnd;


				GetWindowRect(rcW);
				ScreenToClient(rcW);

				pWnd = GetDlgItem(IDC_DOWNLOADLIST);
				pWnd->GetWindowRect(rcDown);
				ScreenToClient(rcDown);

				if (rcW.Height()>0) {
					// splitter paint update
					rcSpl=rcDown;
					rcSpl.top=rcDown.bottom+8;rcSpl.bottom=rcSpl.top+5;rcSpl.left=190;
					GetDlgItem(IDC_UPLOAD_ICO)->MoveWindow(10,rcSpl.top-4,170,18);
					m_wndSplitter.MoveWindow(rcSpl,true);
					UpdateSplitterRange();
				}
			}
			break;
		case WM_NOTIFY:
			if (wParam == IDC_SPLITTER)
			{	
				SPC_NMHDR* pHdr = (SPC_NMHDR*) lParam;
				DoResize(pHdr->delta);
			}
			break;
		case WM_WINDOWPOSCHANGED : 
			{
				CRect rcW;
				GetWindowRect(rcW);
				ScreenToClient(rcW);

				if (m_wndSplitter && rcW.Height()>0) Invalidate();
				break;
			}
		case WM_SIZE:
			if (m_wndSplitter) {
				CRect rcDown,rcSpl,rcW;
				CWnd* pWnd;

				GetWindowRect(rcW);
				ScreenToClient(rcW);

				if (rcW.Height()>0){
					pWnd = GetDlgItem(IDC_DOWNLOADLIST);
					pWnd->GetWindowRect(rcDown);
					ScreenToClient(rcDown);

					long splitpos=(theApp.glob_prefs->GetSplitterbarPosition()*rcW.Height())/100;

					rcSpl.right=rcDown.right;rcSpl.top=splitpos+10;rcSpl.bottom=rcSpl.top+7;rcSpl.left=(rcDown.right/2)-50;rcSpl.right=rcSpl.left+100;
					m_wndSplitter.MoveWindow(rcSpl,true);
				}

			}
			break;
	}

	return CResizableDialog::DefWindowProc(message, wParam, lParam);
}



// CTransferWnd message handlers
BOOL CTransferWnd::PreTranslateMessage(MSG* pMsg)
{
	if (pMsg->message== WM_LBUTTONDBLCLK && pMsg->hwnd== GetDlgItem(IDC_DLTAB)->m_hWnd) {
		OnDblclickDltab();
		return TRUE;
	}

	if (pMsg->message==WM_MOUSEMOVE) {
			POINT point;
			::GetCursorPos(&point);
			if (point.x!=m_pLastMousePoint.x || point.y!=m_pLastMousePoint.y) {
				m_pLastMousePoint=point;
				// handle tooltip updating, when mouse is moved from one item to another
				CPoint pt(point);
				m_nDropIndex=GetTabUnderMouse(&pt);
				if (m_nDropIndex!=m_nLastCatTT) {
					m_nLastCatTT=m_nDropIndex;
				    if (m_nDropIndex!=-1)
					    UpdateTabToolTips(m_nDropIndex);
				    m_tooltip.Update();
				}
			}
	}

	if (pMsg->message==WM_MBUTTONUP) {
		if (downloadlistactive) downloadlistctrl.ShowSelectedFileDetails();
		else {
			switch(windowtransferstate){
				case 2:
					queuelistctrl.ShowSelectedUserDetails();
					break;
				case 1:
					uploadlistctrl.ShowSelectedUserDetails();
					break;
				case 0:
					clientlistctrl.ShowSelectedUserDetails();
					break;
			}
		}
		return TRUE;
	}

	return CResizableDialog::PreTranslateMessage(pMsg);
}

int CTransferWnd::GetItemUnderMouse(CListCtrl* ctrl)
{
	CPoint pt;
	::GetCursorPos(&pt);
	ctrl->ScreenToClient(&pt);
	LVHITTESTINFO hit, subhit;
	hit.pt = pt;
	subhit.pt = pt;
	ctrl->SubItemHitTest(&subhit);
	int sel = ctrl->HitTest(&hit);
	if (sel != LB_ERR && (hit.flags & LVHT_ONITEM))
	{
		if (subhit.iSubItem == 0)
			return sel;
	}
	return LB_ERR;
}

void CTransferWnd::UpdateListCount(uint8 listindex) {
	CString buffer;
	if (windowtransferstate!=listindex) return;

	switch (windowtransferstate) {
		case 1: {
					buffer.Format(" (%i)",uploadlistctrl.GetItemCount());
					GetDlgItem(IDC_UPLOAD_ICO)->SetWindowText(GetResString(IDS_TW_UPLOADS)+buffer);
				}
				break;
		case 2: {
					buffer.Format(" (%i)",queuelistctrl.GetItemCount());
					GetDlgItem(IDC_UPLOAD_ICO)->SetWindowText(GetResString(IDS_ONQUEUE)+buffer);
				}
				break;
		default:{
					buffer.Format(" (%i)",clientlistctrl.GetItemCount());
					GetDlgItem(IDC_UPLOAD_ICO)->SetWindowText(GetResString(IDS_CLIENTLIST)+buffer);
				}
	}
}

void CTransferWnd::SwitchUploadList()
{
	if( windowtransferstate == 1){
		windowtransferstate = 2;		
		if( theApp.glob_prefs->IsQueueListDisabled()){
			SwitchUploadList();
			return;
		}
		uploadlistctrl.Hide();
		clientlistctrl.Hide();
		GetDlgItem(IDC_QUEUE_REFRESH_BUTTON)->ShowWindow(SW_SHOW);
		queuelistctrl.Visable();
		GetDlgItem(IDC_UPLOAD_ICO)->SetWindowText(GetResString(IDS_ONQUEUE));
	}
	else if( windowtransferstate == 2){
		windowtransferstate = 0;
		if( theApp.glob_prefs->IsKnownClientListDisabled()){
			SwitchUploadList();
			return;
		}
		uploadlistctrl.Hide();
		queuelistctrl.Hide();
		clientlistctrl.Visable();
		GetDlgItem(IDC_QUEUE_REFRESH_BUTTON)->ShowWindow(SW_HIDE);
		GetDlgItem(IDC_UPLOAD_ICO)->SetWindowText(GetResString(IDS_CLIENTLIST));
	}
	else{
		queuelistctrl.Hide();
		clientlistctrl.Hide();
		uploadlistctrl.Visable();
		GetDlgItem(IDC_QUEUE_REFRESH_BUTTON)->ShowWindow(SW_HIDE);
		windowtransferstate = 1;
		GetDlgItem(IDC_UPLOAD_ICO)->SetWindowText(GetResString(IDS_TW_UPLOADS));
	}
	UpdateListCount(windowtransferstate);
}

void CTransferWnd::Localize(){
	GetDlgItem(IDC_DOWNLOAD_TEXT)->SetWindowText(GetResString(IDS_TW_DOWNLOADS));
	GetDlgItem(IDC_UPLOAD_ICO)->SetWindowText(GetResString(IDS_TW_UPLOADS));
	GetDlgItem(IDC_TSTATIC1)->SetWindowText(GetResString(IDS_TW_QUEUE));

	GetDlgItem(IDC_QUEUE_REFRESH_BUTTON)->SetWindowText(GetResString(IDS_SV_UPDATE));

	uploadlistctrl.Localize();
	queuelistctrl.Localize();
	downloadlistctrl.Localize();
	clientlistctrl.Localize();
}

void CTransferWnd::OnBnClickedQueueRefreshButton()
{
	CUpDownClient* update = theApp.uploadqueue->GetNextClient(NULL);

	while( update ){
		theApp.emuledlg->transferwnd.queuelistctrl.RefreshClient( update);
		update = theApp.uploadqueue->GetNextClient(update);
	}
}

void CTransferWnd::OnHoverUploadList(NMHDR *pNMHDR, LRESULT *pResult)
{
	downloadlistactive=false;
	*pResult = 0;
}

void CTransferWnd::OnHoverDownloadList(NMHDR *pNMHDR, LRESULT *pResult)
{
	downloadlistactive=true;
	*pResult = 0;
}

void CTransferWnd::OnTcnSelchangeDltab(NMHDR *pNMHDR, LRESULT *pResult)
{
	downloadlistctrl.ChangeCategory(m_dlTab.GetCurSel());
	*pResult = 0;
}

// Ornis' download categories
void CTransferWnd::OnNMRclickDltab(NMHDR *pNMHDR, LRESULT *pResult)
{
	// Menu for category
	CTitleMenu menu;
	POINT point;
	::GetCursorPos(&point);

	CPoint pt(point);
	rightclickindex=GetTabUnderMouse(&pt);

	UINT flag;
	flag=(rightclickindex==0) ? MF_GRAYED:MF_STRING;

	CMenu m_CatMenu;
	m_CatMenu.CreateMenu();

	CMenu m_PrioMenu;
	m_PrioMenu.CreateMenu();

// ZZ DownloadManager -->
	m_PrioMenu.AppendMenu(MF_STRING,MP_PRIOLOW,GetResString(IDS_PRIOLOW));
    m_PrioMenu.CheckMenuItem(MP_PRIOLOW, theApp.glob_prefs->GetCategory(rightclickindex)->prio == PR_LOW ? MF_CHECKED : MF_UNCHECKED);

	m_PrioMenu.AppendMenu(MF_STRING,MP_PRIONORMAL,GetResString(IDS_PRIONORMAL));
    m_PrioMenu.CheckMenuItem(MP_PRIONORMAL, theApp.glob_prefs->GetCategory(rightclickindex)->prio != PR_LOW && theApp.glob_prefs->GetCategory(rightclickindex)->prio != PR_HIGH ? MF_CHECKED : MF_UNCHECKED);

    m_PrioMenu.AppendMenu(MF_STRING,MP_PRIOHIGH, GetResString(IDS_PRIOHIGH));
    m_PrioMenu.CheckMenuItem(MP_PRIOHIGH, theApp.glob_prefs->GetCategory(rightclickindex)->prio == PR_HIGH ? MF_CHECKED : MF_UNCHECKED);

    //m_PrioMenu.AppendMenu(MF_STRING,MP_PRIOAUTO, GetResString(IDS_PRIOAUTO));
// <-- ZZ DownloadManager

	menu.CreatePopupMenu();
	menu.AddMenuTitle(GetResString(IDS_CAT));

	if (rightclickindex==0 ){
		m_CatMenu.AppendMenu(MF_STRING,MP_CAT_SET0,GetResString(IDS_ALL) );
		m_CatMenu.AppendMenu(MF_STRING,MP_CAT_SET0+1,GetResString(IDS_ALLOTHERS) );
		m_CatMenu.AppendMenu(MF_SEPARATOR);
		m_CatMenu.AppendMenu(MF_STRING,MP_CAT_SET0+2,GetResString(IDS_STATUS_NOTCOMPLETED) );
		m_CatMenu.AppendMenu(MF_STRING,MP_CAT_SET0+3,GetResString(IDS_DL_TRANSFCOMPL) );
		m_CatMenu.AppendMenu(MF_STRING,MP_CAT_SET0+4,GetResString(IDS_WAITING) );
		m_CatMenu.AppendMenu(MF_STRING,MP_CAT_SET0+5,GetResString(IDS_DOWNLOADING) );
		m_CatMenu.AppendMenu(MF_STRING,MP_CAT_SET0+6,GetResString(IDS_ERRORLIKE) );
		m_CatMenu.AppendMenu(MF_STRING,MP_CAT_SET0+7,GetResString(IDS_PAUSED) );
		m_CatMenu.AppendMenu(MF_STRING,MP_CAT_SET0+8,GetResString(IDS_STOPPED) );
		m_CatMenu.AppendMenu(MF_SEPARATOR);
		m_CatMenu.AppendMenu(MF_STRING,MP_CAT_SET0+10,GetResString(IDS_VIDEO) );
		m_CatMenu.AppendMenu(MF_STRING,MP_CAT_SET0+11,GetResString(IDS_AUDIO) );
		m_CatMenu.AppendMenu(MF_STRING,MP_CAT_SET0+12,GetResString(IDS_SEARCH_ARC) );
		m_CatMenu.AppendMenu(MF_STRING,MP_CAT_SET0+13,GetResString(IDS_SEARCH_CDIMG) );
		
		m_CatMenu.CheckMenuItem( MP_CAT_SET0+theApp.glob_prefs->GetAllcatType() ,MF_CHECKED | MF_BYCOMMAND);

		menu.AppendMenu(MF_STRING|MF_POPUP,(UINT_PTR)m_CatMenu.m_hMenu, GetResString(IDS_CHANGECATVIEW) );
		menu.AppendMenu(MF_SEPARATOR);
	}

	menu.AppendMenu(MF_STRING,MP_CAT_ADD,GetResString(IDS_CAT_ADD));
	menu.AppendMenu(flag,MP_CAT_EDIT,GetResString(IDS_CAT_EDIT));
	menu.AppendMenu(flag,MP_CAT_REMOVE, GetResString(IDS_CAT_REMOVE));
	menu.AppendMenu(MF_SEPARATOR);
	menu.AppendMenu(MF_STRING|MF_POPUP,(UINT_PTR)m_PrioMenu.m_hMenu, GetResString(IDS_PRIORITY) );

	menu.AppendMenu(MF_STRING,MP_CANCEL,GetResString(IDS_MAIN_BTN_CANCEL) );
	menu.AppendMenu(MF_STRING,MP_STOP, GetResString(IDS_DL_STOP));
	menu.AppendMenu(MF_STRING,MP_PAUSE, GetResString(IDS_DL_PAUSE));
	menu.AppendMenu(MF_STRING,MP_RESUME, GetResString(IDS_DL_RESUME));
	menu.AppendMenu(MF_STRING,MP_RESUMENEXT, GetResString(IDS_DL_RESUMENEXT));

// ZZ DownloadManager -->
    if(rightclickindex != 0) {
        menu.AppendMenu(MF_STRING,MP_DOWNLOAD_ALPHABETICAL, GetResString(IDS_DOWNLOAD_ALPHABETICAL));	
        menu.CheckMenuItem(MP_DOWNLOAD_ALPHABETICAL, theApp.glob_prefs->GetCategory(rightclickindex)->downloadInAlphabeticalOrder ? MF_CHECKED : MF_UNCHECKED);
    }
// <-- ZZ DownloadManager

	menu.TrackPopupMenu(TPM_LEFTALIGN |TPM_RIGHTBUTTON, point.x, point.y, this);
	VERIFY( m_PrioMenu.DestroyMenu() );
	VERIFY( m_CatMenu.DestroyMenu() );
	VERIFY( menu.DestroyMenu() );

	*pResult = 0;
}

void CTransferWnd::OnLvnBegindrag(NMHDR *pNMHDR, LRESULT *pResult)
{
    int iSel = downloadlistctrl.GetSelectionMark();
	if (iSel==-1) return;
	if (((CtrlItem_Struct*)downloadlistctrl.GetItemData(iSel))->type != FILE_TYPE) return;
	
	m_bIsDragging = true;

	POINT pt;
	::GetCursorPos(&pt);

	LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
	m_nDragIndex = pNMLV->iItem;
	m_pDragImage = downloadlistctrl.CreateDragImage( downloadlistctrl.GetSelectionMark() ,&pt);
    m_pDragImage->BeginDrag( 0, CPoint(0,0) );
    m_pDragImage->DragEnter( GetDesktopWindow(), pNMLV->ptAction );
    SetCapture();
	m_nDropIndex = -1;

	*pResult = 0;
}

void CTransferWnd::OnMouseMove(UINT nFlags, CPoint point)
{
	if( !(nFlags & MK_LBUTTON) ) m_bIsDragging = false;

	if (m_bIsDragging){
		CPoint pt(point);           //get our current mouse coordinates
		ClientToScreen(&pt);        //convert to screen coordinates

		m_nDropIndex=GetTabUnderMouse(&pt);
		m_dlTab.SetCurSel(m_nDropIndex);
		m_dlTab.Invalidate();
		
		::GetCursorPos(&pt);
		pt.y-=10;
		m_pDragImage->DragMove(pt); //move the drag image to those coordinates
	}
}

void CTransferWnd::OnLButtonUp(UINT nFlags, CPoint point)
{

	if (m_bIsDragging)
	{
		ReleaseCapture ();
		m_bIsDragging = false;
		m_pDragImage->DragLeave (GetDesktopWindow ());
		m_pDragImage->EndDrag ();
		delete m_pDragImage;
		
		if (m_nDropIndex>-1 && (downloadlistctrl.curTab==0 ||
				(downloadlistctrl.curTab>0 && m_nDropIndex!=downloadlistctrl.curTab) )) {

			CPartFile* file;
			int index = -1; 
			POSITION pos = downloadlistctrl.GetFirstSelectedItemPosition(); 
			while(pos != NULL) 
			{ 
				index = downloadlistctrl.GetNextSelectedItem(pos); 
				if(index > -1) 
				{
					if (((CtrlItem_Struct*)downloadlistctrl.GetItemData(index))->type == FILE_TYPE) {
						file=(CPartFile*)((CtrlItem_Struct*)downloadlistctrl.GetItemData(index))->value;
						file->SetCategory(m_nDropIndex);
					}

				} 
			}
			m_dlTab.SetCurSel(downloadlistctrl.curTab);
			if (m_dlTab.GetCurSel()>0 || (theApp.glob_prefs->GetAllcatType()==1 && m_dlTab.GetCurSel()==0) )
				downloadlistctrl.ChangeCategory(m_dlTab.GetCurSel());
			UpdateCatTabTitles();

		} else m_dlTab.SetCurSel(downloadlistctrl.curTab);
		downloadlistctrl.Invalidate();
	}
}

BOOL CTransferWnd::OnCommand(WPARAM wParam,LPARAM lParam ){ 

	if (wParam>=MP_CAT_SET0 && wParam<=MP_CAT_SET0+20) {
		theApp.glob_prefs->SetAllcatType(wParam-MP_CAT_SET0);
		m_nLastCatTT=-1;
		m_dlTab.SetCurSel(0);
		downloadlistctrl.ChangeCategory(0);
		EditCatTabLabel(0,GetCatTitle( theApp.glob_prefs->GetAllcatType()));
	}

	switch (wParam){ 
		case MP_CAT_ADD: {
			m_nLastCatTT=-1;
			int newindex=AddCategorie("?",theApp.glob_prefs->GetIncomingDir(),"","",true);
			CCatDialog dialog(newindex);
			dialog.DoModal();
			theApp.emuledlg->searchwnd->UpdateCatTabs();
			EditCatTabLabel(newindex,theApp.glob_prefs->GetCategory(newindex)->title);
			theApp.glob_prefs->SaveCats();
			break;
		}
		case MP_CAT_EDIT: {
			m_nLastCatTT=-1;
			CCatDialog dialog(rightclickindex);
			dialog.DoModal();

			CString csName;
			csName.Format("%s", theApp.glob_prefs->GetCategory(rightclickindex)->title );
			EditCatTabLabel(rightclickindex,csName);
		
			theApp.emuledlg->searchwnd->UpdateCatTabs();
			theApp.glob_prefs->SaveCats();
			break;
		}
		case MP_CAT_REMOVE: {
			m_nLastCatTT=-1;
			theApp.downloadqueue->ResetCatParts(rightclickindex);
			theApp.glob_prefs->RemoveCat(rightclickindex);
			m_dlTab.DeleteItem(rightclickindex);
			m_dlTab.SetCurSel(0);
			downloadlistctrl.ChangeCategory(0);
			theApp.glob_prefs->SaveCats();
			if (theApp.glob_prefs->GetCatCount()==1) theApp.glob_prefs->SetAllcatType(0);
			theApp.emuledlg->searchwnd->UpdateCatTabs();
			VerifyCatTabSize();
			break;
		}

// ZZ DownloadManager -->
		case MP_PRIOLOW: {
			//theApp.downloadqueue->SetCatPrio(rightclickindex,PR_LOW);
            theApp.glob_prefs->GetCategory(rightclickindex)->prio = PR_LOW;
			theApp.emuledlg->searchwnd->UpdateCatTabs();
			theApp.glob_prefs->SaveCats();
			break;
		}
		case MP_PRIONORMAL: {
			//theApp.downloadqueue->SetCatPrio(rightclickindex,PR_NORMAL);
            theApp.glob_prefs->GetCategory(rightclickindex)->prio = PR_NORMAL;
			theApp.emuledlg->searchwnd->UpdateCatTabs();
			theApp.glob_prefs->SaveCats();
			break;
		}
		case MP_PRIOHIGH: {
			//theApp.downloadqueue->SetCatPrio(rightclickindex,PR_HIGH);
            theApp.glob_prefs->GetCategory(rightclickindex)->prio = PR_HIGH;
			theApp.emuledlg->searchwnd->UpdateCatTabs();
			theApp.glob_prefs->SaveCats();
			break;
		}
		//case MP_PRIOAUTO: {
		//	theApp.downloadqueue->SetCatPrio(rightclickindex,PR_AUTO);
		//	break;
		//}
// <-- ZZ DownloadManager

		case MP_PAUSE: {
			theApp.downloadqueue->SetCatStatus(rightclickindex,MP_PAUSE);
			break;
		}
		case MP_STOP : {
				theApp.downloadqueue->SetCatStatus(rightclickindex,MP_STOP);
			break;
		}
		case MP_CANCEL: {
			if (AfxMessageBox(GetResString(IDS_Q_CANCELDL),MB_ICONQUESTION|MB_YESNO) == IDYES)
				theApp.downloadqueue->SetCatStatus(rightclickindex,MP_CANCEL);
			break;
		}
		case MP_RESUME: {
			theApp.downloadqueue->SetCatStatus(rightclickindex,MP_RESUME);
			break;
		}
		case MP_RESUMENEXT: {
			theApp.downloadqueue->StartNextFile(rightclickindex);
			break;
		}

// ZZ DownloadManager -->
		case MP_DOWNLOAD_ALPHABETICAL: {
            BOOL newSetting = !theApp.glob_prefs->GetCategory(rightclickindex)->downloadInAlphabeticalOrder;
            theApp.glob_prefs->GetCategory(rightclickindex)->downloadInAlphabeticalOrder = newSetting;
			theApp.glob_prefs->SaveCats();
            if(newSetting) {
                // any auto prio files will be set to normal now.
                theApp.downloadqueue->RemoveAutoPrioInCat(rightclickindex, PR_NORMAL);
            }

            break;
		}
// <-- ZZ DownloadManager

		case IDC_UPLOAD_ICO: {
			SwitchUploadList();
			break;
		}
		case IDC_QUEUE_REFRESH_BUTTON: {
			OnBnClickedQueueRefreshButton();
			break;
		}
	}
	return TRUE;
}

void CTransferWnd::UpdateCatTabTitles() {
	for (uint8 i=0;i<m_dlTab.GetItemCount();i++)
		EditCatTabLabel(i,(i==0)? GetCatTitle( theApp.glob_prefs->GetAllcatType() ):theApp.glob_prefs->GetCategory(i)->title);
}

void CTransferWnd::EditCatTabLabel(int index,CString newlabel) {

	TCITEM tabitem;
	tabitem.mask = TCIF_PARAM;
	m_dlTab.GetItem(index,&tabitem);
	tabitem.mask = TCIF_TEXT;

// ZZ DownloadManager -->
    CString prioStr;
    switch(theApp.glob_prefs->GetCategory(index)->prio) {
        case PR_LOW:
            prioStr = " " + GetResString(IDS_PR_SHORT_LOW);
            break;

        case PR_HIGH:
            prioStr = " " + GetResString(IDS_PR_SHORT_HIGH);
            break;

        default:
            prioStr = "";
            break;
    }
// <-- ZZ DownloadManager


	if (theApp.glob_prefs->ShowCatTabInfos()) {
		CPartFile* cur_file;
		uint16 count,dwl;
		count=dwl=0;
		for (int i=0;i<theApp.downloadqueue->GetFileCount();i++) {
			cur_file=theApp.downloadqueue->GetFileByIndex(i);
			if (cur_file==0) continue;
			if (CheckShowItemInGivenCat(cur_file,index)) {
				count++;
				if (cur_file->GetTransferingSrcCount()>0) dwl++;
//				speed+=cur_file->GetDatarate()/1024.0f;
//				size+=cur_file->GetFileSize();
//				trsize+=cur_file->GetCompletedSize();
			}
		}

		CString title=newlabel;
		newlabel.Format("%s%s %i/%i",title, prioStr,dwl,count); // ZZ DownloadManager

// ZZ DownloadManager -->
    } else {
        newlabel += prioStr;
    }
// <-- ZZ DownloadManager

	tabitem.pszText = newlabel.LockBuffer();
	m_dlTab.SetItem(index,&tabitem);
	newlabel.UnlockBuffer();

	VerifyCatTabSize();
}

int CTransferWnd::AddCategorie(CString newtitle,CString newincoming,CString newcomment, CString newautocat, bool addTab){
	Category_Struct* newcat=new Category_Struct;

	sprintf(newcat->title,newtitle);
	newcat->prio=PR_NORMAL; // ZZ DownloadManager
	sprintf(newcat->incomingpath,newincoming);
	sprintf(newcat->comment,newcomment);
	newcat->autocat=newautocat;
    newcat->downloadInAlphabeticalOrder = FALSE; // ZZ DownloadManager

	int index=theApp.glob_prefs->AddCat(newcat);
	if (addTab) m_dlTab.InsertItem(index,newtitle);

	VerifyCatTabSize();
	
	return index;
}

int CTransferWnd::GetTabUnderMouse(CPoint* point) {
		TCHITTESTINFO hitinfo;
		CRect rect;
		m_dlTab.GetWindowRect(&rect);
		point->Offset(0-rect.left,0-rect.top);
		hitinfo.pt = *point;

		if( m_dlTab.GetItemRect( 0, &rect ) )
			if (hitinfo.pt.y< rect.top+30 && hitinfo.pt.y >rect.top-30)
				hitinfo.pt.y = rect.top;

		// Find the destination tab...
		unsigned int nTab = m_dlTab.HitTest( &hitinfo );
		if( hitinfo.flags != TCHT_NOWHERE )
			return nTab;
		else return -1;
}

void CTransferWnd::OnLvnKeydownDownloadlist(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMLVKEYDOWN pLVKeyDow = reinterpret_cast<LPNMLVKEYDOWN>(pNMHDR);
	if (downloadlistctrl.GetSelectionMark()!=-1) {
		uint8 action=EXPAND_COLLAPSE;
		if (pLVKeyDow->wVKey==VK_ADD || pLVKeyDow->wVKey==VK_RIGHT) action=EXPAND_ONLY;
		else if ( pLVKeyDow->wVKey==VK_SUBTRACT || pLVKeyDow->wVKey==VK_LEFT ) action=COLLAPSE_ONLY;
		if (action<EXPAND_COLLAPSE) downloadlistctrl.ExpandCollapseItem(downloadlistctrl.GetSelectionMark(),action,true);
	}
	*pResult = 0;
}

void CTransferWnd::UpdateTabToolTips(int tab)
{
	uint8 i;

	if (tab==-1) {

		for (i=0;i<m_tooltip.GetToolCount();i++)
			m_tooltip.DelTool(&m_dlTab,i+1);

		for (i = 0; i < m_dlTab.GetItemCount(); i++)
		{
			CRect r;
			m_dlTab.GetItemRect(i, &r);
			VERIFY(m_tooltip.AddTool(&m_dlTab, GetTabStatistic(i), &r, i+1));
		}
	} else {
		CRect r;
		m_dlTab.GetItemRect(tab, &r);

		m_tooltip.DelTool(&m_dlTab,tab+1);
		VERIFY(m_tooltip.AddTool(&m_dlTab, GetTabStatistic(tab), &r, tab+1));
	}
}

CString CTransferWnd::GetTabStatistic(uint8 tab) {
	uint16 count,dwl;
	count=dwl=0;
	float speed=0;
	uint64 size=0;
	uint64 trsize=0;
	uint64 disksize=0;

	CPartFile* cur_file;

	for (int i=0;i<theApp.downloadqueue->GetFileCount();++i) {
		cur_file=theApp.downloadqueue->GetFileByIndex(i);
		if (cur_file==0) continue;
		if (CheckShowItemInGivenCat(cur_file,tab)) {
			count++;
			if (cur_file->GetTransferingSrcCount()>0) ++dwl;
			speed+=cur_file->GetDatarate()/1024.0f;
			size+=cur_file->GetFileSize();
			trsize+=cur_file->GetCompletedSize();
			disksize+=cur_file->GetRealFileSize();
		}
	}

	CString title;
	title.Format("%s: %i/%i\n%s: %.1f %s\n%s: %s/%s\n%s%s",
		GetResString(IDS_DOWNLOADING), dwl,count,GetResString(IDS_DL_SPEED) ,speed,GetResString(IDS_KBYTESEC),
		GetResString(IDS_DL_SIZE),CastItoXBytes(trsize),CastItoXBytes(size),
		GetResString(IDS_ONDISK),CastItoXBytes(disksize)		);
	return title;
}


void CTransferWnd::OnDblclickDltab(){
	POINT point;
	::GetCursorPos(&point);
	CPoint pt(point);
	int tab=GetTabUnderMouse(&pt);
	if (tab<1) return;
	rightclickindex=tab;
	OnCommand(MP_CAT_EDIT,0);
}

void CTransferWnd::OnTabMovement(NMHDR *pNMHDR, LRESULT *pResult) {
	UINT from=m_dlTab.GetLastMovementSource();
	UINT to=m_dlTab.GetLastMovementDestionation();

	if (from==0 || to==0 || from==to-1) return;

	// do the reorder
	
	// rearrange the cat-map
	if (!theApp.glob_prefs->MoveCat(from,to)) return;

	// update partfile-stored assignment
	theApp.downloadqueue->MoveCat((uint8)from,(uint8)to);

	// move category of completed files
	downloadlistctrl.MoveCompletedfilesCat((uint8)from,(uint8)to);

	// of the tabcontrol itself
	m_dlTab.ReorderTab(from,to);

	UpdateCatTabTitles();
	theApp.emuledlg->searchwnd->UpdateCatTabs();

	if (to>from) --to;
	m_dlTab.SetCurSel(to);
	downloadlistctrl.ChangeCategory(to);
}

void CTransferWnd::VerifyCatTabSize() {
	CRect rect;
	int size=0;

	for (int i=0;i<m_dlTab.GetItemCount();i++) {
		m_dlTab.GetItemRect(i,&rect);
		size+= rect.Width();
	}
	size+=20;

	WINDOWPLACEMENT wpTabWinPos;
	m_dlTab.GetWindowPlacement(&wpTabWinPos);
	if (wpTabWinPos.rcNormalPosition.right<0) return;
	
	int left=wpTabWinPos.rcNormalPosition.right-size;
	if (left<200) left=200;
	wpTabWinPos.rcNormalPosition.left=left;

	RemoveAnchor(m_dlTab);
	m_dlTab.SetWindowPlacement(&wpTabWinPos);
	AddAnchor(m_dlTab,TOP_RIGHT);
}
