// LocalView.cpp : 구현 파일입니다.
//

#include "stdafx.h"
#include "ConsoleApp.h"
#include "LocalView.h"

#include "MainFrm.h"
#include "RemoteView.h"
#include "RemoteTreeCtrl.h"
#include "RemoteListCtrl.h"
//#include "Winuser.h"

CString BYTE2KMBYTE(__int64 nBytes, int nFlag, bool bShowDecimalPoint);
CString NumericFormat(__int64 nNumeric);
CString GetErrorMessage(DWORD dwError);
BOOL DeleteDirectory(CString sDirectory);

// CLocalView

IMPLEMENT_DYNCREATE(CLocalView, CView)

CLocalView::CLocalView()
{
	m_bDragSplitter = FALSE;
	m_cxSplitter = COptions::GetOptionVal(OPTION_LOCALTREESIZE);

	m_nTimer             = 0;
	m_nSelectedCount     = 0;
	m_nSelectedBytes     = 0;
	m_nSelectedFiles     = 0;
	m_nSelectedSecialObj = 0;
	m_nTotalCount        = 0;
	m_nTotalBytes        = 0;

	m_pnodeRoot = NULL;

	m_bUpdating = FALSE;

	m_bIgnoreEvent = FALSE;
}

CLocalView::~CLocalView()
{
	COptions::SetOption(OPTION_LOCALTREESIZE, m_cxSplitter);
}


BEGIN_MESSAGE_MAP(CLocalView, CView)
	ON_WM_CREATE()
	ON_WM_SIZE()
	ON_WM_ERASEBKGND()
	ON_WM_TIMER()

	ON_BN_CLICKED(IDC_LOCAL_ADVERT, OnLocalAdvert)
	ON_BN_CLICKED(IDC_LOCAL_BTN_TOOLBAR, OnLocalBtnToolbar)
	ON_BN_CLICKED(IDC_LOCAL_BTN_UPLOAD, OnLocalBtnUpload)
	ON_BN_CLICKED(IDC_LOCAL_BTN_DOWNLOAD, OnLocalBtnDownload)
	ON_BN_CLICKED(IDC_LOCAL_BTN_NEWFOLDER, OnLocalBtnNewFolder)
	ON_BN_CLICKED(IDC_LOCAL_BTN_DELETE, OnLocalBtnDelete)
	ON_BN_CLICKED(IDC_LOCAL_TITLE, OnLocalTitle)
//	ON_BN_CLICKED(IDC_LOCAL_BTN_GO_ADDR, OnLocalBtnGoAddr)
	ON_BN_CLICKED(IDC_LOCAL_BTN_UP_ADDR, OnLocalBtnUpAddr)
	ON_BN_CLICKED(IDC_LOCAL_BTN_LISTSTYLE, OnLocalBtnListStyle)

	ON_COMMAND(ID_LIST_NEWFOLDER, OnListNewfolder)
	ON_COMMAND(ID_LIST_REFRESH, OnListRefresh)
	ON_COMMAND(ID_LIST_TYPE0, OnListType0)
	ON_COMMAND(ID_LIST_TYPE1, OnListType1)
	ON_COMMAND(ID_LIST_TYPE2, OnListType2)
	ON_COMMAND(ID_LIST_TYPE3, OnListType3)
	ON_COMMAND(ID_LIST_TYPE4, OnListType4)
	ON_COMMAND(ID_LIST_SORT1, OnListSort1)
	ON_COMMAND(ID_LIST_SORT2, OnListSort2)
	ON_COMMAND(ID_LIST_SORT3, OnListSort3)
	ON_COMMAND(ID_LIST_SORT4, OnListSort4)
	ON_COMMAND(ID_LIST_PASTE, OnListPaste)
	ON_COMMAND(ID_LIST_ALL, OnListAll)
END_MESSAGE_MAP()

// CLocalView 진단입니다.

#ifdef _DEBUG
void CLocalView::AssertValid() const
{
	CView::AssertValid();
}

void CLocalView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}
#endif //_DEBUG


// CLocalView 그리기

void CLocalView::OnDraw(CDC* pDC)
{
	RECT   rc, rcClient;
	CBrush br;

	GetClientRect(&rcClient);

	///////////////////////////////////////////////////////////////////////////////
	// 3D 음영
	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

	if (!pmf)
		return;

	int cyToolBar = pmf->m_bShowMidToolBar ? TOOLBAR_HEIGHT : 0;

	// 전체
	br.CreateSysColorBrush(COLOR_BTNFACE);
	rc = rcClient;
	pDC->FillRect(&rc, &br);
	br.DeleteObject();

	// 최상단
	br.CreateSysColorBrush(COLOR_BTNHIGHLIGHT);
	rc        = rcClient;
	rc.top    = cyToolBar;
	rc.bottom = cyToolBar + HIGHLIGHT_SIZE;
	pDC->FillRect(&rc, &br);

	// 맨좌측
	rc       = rcClient;
	rc.left  = 0;
	rc.right = HIGHLIGHT_SIZE;
	pDC->FillRect(&rc, &br);
	br.DeleteObject();

	// 맨우측
	br.CreateSysColorBrush(COLOR_BTNSHADOW);
	rc      = rcClient;
	rc.left = rc.right - 1;
	pDC->FillRect(&rc, &br);
	br.DeleteObject();

	RedrawFocus();
}

// CLocalView 메시지 처리기입니다.

BOOL CLocalView::PreTranslateMessage(MSG* pMsg)
{
	static int xOldSplitter = -77;

	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

	int x, y;

	switch (pMsg->message) {
	case WM_MOUSEMOVE:
		x = LOWORD(pMsg->lParam);
		y = HIWORD(pMsg->lParam);

		if (m_bDragSplitter) {
			if (xOldSplitter != -77)
				InvertTracker(xOldSplitter);

			InvertTracker(xOldSplitter = x + 2);

			return TRUE;
		}
		else if (pMsg->hwnd == m_hWnd) {
			RECT rc;
			GetClientRect(&rc);

			rc.left    = m_cxSplitter;
			rc.right   = m_cxSplitter + SPLITTER_SIZE;
			rc.top     = (pmf->m_bShowMidToolBar ? TOOLBAR_HEIGHT : TOOLBAR_BTN_HEIGHT) + CAPTION_HEIGHT;
			rc.bottom -= STATUS_HEIGHT;

			if (x >= rc.left && x <= rc.right && y >= rc.top && y <= rc.bottom)
				SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEWE));
		}

		break;
	case WM_LBUTTONDOWN:
		if (pmf->m_bShowMidToolBar) {
			if (HIWORD(pMsg->lParam) > TOOLBAR_HEIGHT)
				((CMainFrame*)AfxGetMainWnd())->SetFocus(this);
		}
		else 
			((CMainFrame*)AfxGetMainWnd())->SetFocus(this);

		x = LOWORD(pMsg->lParam);
		y = HIWORD(pMsg->lParam);

		if (pMsg->hwnd == m_hWnd) {
			RECT rc;
			GetClientRect(&rc);

			rc.left    = m_cxSplitter;
			rc.right   = m_cxSplitter + SPLITTER_SIZE;
			rc.top     = (pmf->m_bShowMidToolBar ? TOOLBAR_HEIGHT : TOOLBAR_BTN_HEIGHT) + CAPTION_HEIGHT;
			rc.bottom -= STATUS_HEIGHT;

			if (x >= rc.left && x <= rc.right && y >= rc.top && y <= rc.bottom) {
				GetWindowRect(&rc);
				ClipCursor(&rc);

				SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEWE));
				SetCapture();

				m_bDragSplitter = TRUE;

				xOldSplitter = -77;

				return TRUE;
			}
		}
		break;
	case WM_LBUTTONUP:
		if (m_bDragSplitter) {
			InvertTracker(xOldSplitter);

			ClipCursor(NULL);
			ReleaseCapture();
			SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));

			m_bDragSplitter = FALSE;

			RECT rc;
			GetClientRect(&rc);

			x = LOWORD(pMsg->lParam);
			if (x < MIN_TREE_WIDTH)
				x = MIN_TREE_WIDTH;
			else if (x > rc.right - MIN_LIST_WIDTH)
				x = rc.right - MIN_LIST_WIDTH;

			m_cxSplitter = x;
			RedrawControl(rc.right, rc.bottom);

			return TRUE;
		}
		break;
	case WM_RBUTTONDOWN:
		((CMainFrame*)AfxGetMainWnd())->SetFocus(this);
		break;
	}

	return CView::PreTranslateMessage(pMsg);
}

BOOL CLocalView::PreCreateWindow(CREATESTRUCT& cs)
{
	cs.style     |= WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
	cs.dwExStyle |= WS_EX_STATICEDGE;

	return CView::PreCreateWindow(cs);
}

int CLocalView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CView::OnCreate(lpCreateStruct) == -1)
		return -1;

	CMainFrame *pmf = (CMainFrame *)AfxGetMainWnd();

	CString sCaption;

	// 중간툴바
	if (!m_capToolBar.Create(this, "", CPWS_EX_RAISED_EDGE, WS_VISIBLE | WS_CLIPCHILDREN, CRect(0, 0, 0, 0), IDC_LOCAL_TOOLBAR)) {
		AfxMessageBox("IDC_LOCAL_TOOLBAR 생성 실패.\n");
		return -1;
	}

	if (!m_stcAdvert.Create("", WS_VISIBLE | BS_OWNERDRAW, CRect(0,0,0,0), this, IDC_LOCAL_ADVERT)) {
		AfxMessageBox("IDC_LOCAL_ADVERT 생성 실패.\n");
		return -1;
	}
	if (m_stcAdvert.Load(MAKEINTRESOURCE(IDR_ADVERT), _T("GIF")))
		m_stcAdvert.Draw();

	if (!m_btnToolBar.Create("", WS_VISIBLE | BS_OWNERDRAW, CRect(0,0,0,0), this, IDC_LOCAL_BTN_TOOLBAR)) {
		AfxMessageBox("IDC_LOCAL_BTN_TOOLBAR 생성 실패.\n");
		return -1;
	}

	if (!m_btnUpload.Create("올리기", WS_VISIBLE | BS_BITMAP, CRect(0,0,0,0), this, IDC_LOCAL_BTN_UPLOAD)) {
		AfxMessageBox("IDC_LOCAL_BTN_UPLOAD 생성 실패.\n");
		return -1;
	}
	m_btnUpload.SetXButtonStyle(BS_XT_WINXP_COMPAT);
	m_btnUpload.SetFont(&pmf->m_font);
	m_btnUpload.SetBitmap(0, IDB_BTN_UPLOAD);

	if (!m_btnDownload.Create("내리기", WS_VISIBLE | BS_BITMAP, CRect(0,0,0,0), this, IDC_LOCAL_BTN_DOWNLOAD)) {
		AfxMessageBox("IDC_LOCAL_BTN_DOWNLOAD 생성 실패.\n");
		return -1;
	}
	m_btnDownload.SetXButtonStyle(BS_XT_WINXP_COMPAT);
	m_btnDownload.SetFont(&pmf->m_font);
	m_btnDownload.SetBitmap(0, IDB_BTN_DOWNLOAD);

	if (!m_btnNewFolder.Create("새폴더", WS_VISIBLE | BS_OWNERDRAW, CRect(0,0,0,0), this, IDC_LOCAL_BTN_NEWFOLDER)) {
		AfxMessageBox("IDC_LOCAL_BTN_NEWFOLDER 생성 실패.\n");
		return -1;
	}
	m_btnNewFolder.SetXButtonStyle(BS_XT_WINXP_COMPAT);
	m_btnNewFolder.SetFont(&pmf->m_font);
	m_btnNewFolder.SetBitmap(0, IDB_BTN_NEWFOLDER);

	if (!m_btnDelete.Create("삭제", WS_VISIBLE | BS_OWNERDRAW, CRect(0,0,0,0), this, IDC_LOCAL_BTN_DELETE)) {
		AfxMessageBox("IDC_LOCAL_BTN_DELETE 생성 실패.\n");
		return -1;
	}
	m_btnDelete.SetXButtonStyle(BS_XT_WINXP_COMPAT);
	m_btnDelete.SetFont(&pmf->m_font);
	m_btnDelete.SetBitmap(0, IDB_BTN_DELETE);

	// 트리 생성
	if (!m_capTitleIcon.Create("", WS_VISIBLE | BS_OWNERDRAW, CRect(0,0,0,0), this, 0)) {
		AfxMessageBox("IDC_LOCAL_TITLEICON 생성 실패.\n");
		return -1;
	}
	m_capTitleIcon.LoadBitmaps(IDB_CAP_LOCAL);

	sCaption = "내 컴퓨터";
	if (!m_capTitle.Create(this, "     " + sCaption, CPWS_EX_CLOSEBUTTON, WS_VISIBLE, CRect(0, 0, 0, 0), IDC_LOCAL_TITLE)) {
		AfxMessageBox("IDC_LOCAL_TITLE 생성 실패.\n");
		return -1;
	}
	m_capTitle.SetFont(&pmf->m_font);

	if (!m_tree.Create("", WS_VISIBLE | WS_CHILD, CRect(0,0,0,0), this, IDC_LOCAL_TREE)) {
		AfxMessageBox( "IDC_LOCAL_TREE 생성 실패.\n" );
		return -1;
	}
//	m_tree.ModifyStyle(WS_BORDER | WS_THICKFRAME, NULL);
//	m_tree.ModifyStyleEx(NULL, WS_EX_STATICEDGE);

	// 리스트 생성
	sCaption = "위치";
	if (!m_capAddr.Create(sCaption, WS_VISIBLE | SS_CENTER | SS_CENTERIMAGE, CRect(0,0,0,0), this, IDC_LOCAL_STC_ADDR)) {
		AfxMessageBox("IDC_LOCAL_STC_ADDR 생성 실패.\n");
		return -1;
	}
	m_capAddr.SetFont(&pmf->m_font);

	if (!m_cboAddr.Create("", WS_VISIBLE, CRect(0,0,0,0), this, IDC_LOCAL_CBO_ADDR)) {
		AfxMessageBox("IDC_LOCAL_CBO_ADDR 생성 실패.\n");
		return -1;
	}

	if (!m_btnGoAddr.Create("", WS_VISIBLE | BS_OWNERDRAW, CRect(0,0,0,0), this, IDC_LOCAL_BTN_GO_ADDR)) {
		AfxMessageBox("IDC_LOCAL_BTN_GO_ADDR 생성 실패.\n");
		return -1;
	}
	m_btnGoAddr.SetXButtonStyle(BS_XT_WINXP_COMPAT);
	m_btnGoAddr.SetBitmap(0, IDB_BTN_GO);

	if (!m_btnUpAddr.Create("", WS_VISIBLE | BS_OWNERDRAW, CRect(0,0,0,0), this, IDC_LOCAL_BTN_UP_ADDR)) {
		AfxMessageBox("IDC_LOCAL_BTN_UP_ADDR 생성 실패.\n");
		return -1;
	}
	m_btnUpAddr.SetXButtonStyle(BS_XT_WINXP_COMPAT);
	m_btnUpAddr.SetBitmap(0, IDB_BTN_UP);

	if (!m_btnListStyle.Create("", WS_VISIBLE | BS_OWNERDRAW, CRect(0,0,0,0), this, IDC_LOCAL_BTN_LISTSTYLE)) {
		AfxMessageBox("IDC_LOCAL_BTN_LISTSTYLE 생성 실패.\n");
		return -1;
	}
	m_btnListStyle.SetXButtonStyle(BS_XT_WINXP_COMPAT);
	m_btnListStyle.SetBitmap(0, IDB_BTN_LISTSTYLE);

	if (!m_list.Create("", WS_VISIBLE | WS_CHILD | LVS_REPORT | LVS_SHAREIMAGELISTS | LVS_EDITLABELS, CRect(0,0,0,0), this, IDC_LOCAL_LIST)) {
		AfxMessageBox("IDC_LOCAL_LIST 생성 실패.\n");
		return -1;
	}
	m_list.put_MultiSelect(TRUE);

	if (!m_capStatus.Create(this, "", CPWS_EX_RAISED_EDGE, WS_VISIBLE, CRect(0, 0, 0, 0), 0)) {
		AfxMessageBox("IDC_LOCAL_STATUSBAR 생성 실패.\n");
		return -1;
	}
	m_capStatus.SetFont(&pmf->m_font);

	if (!m_prgStatusSpace.Create(WS_VISIBLE, CRect(0, 0, 0, 0), this, 0)) {
		AfxMessageBox("IDC_LOCAL_STATUS_SPACE 생성 실패.\n");
		return -1;
	}
	m_prgStatusSpace.SetFont(&pmf->m_font);
	m_prgStatusSpace.SetRange(0, 100);
	m_prgStatusSpace.SetText(" ");
	m_prgStatusSpace.SetStep(1);
	m_prgStatusSpace.ShowWindow(SW_HIDE);

	if (!m_stcStatusSpace.Create("", WS_VISIBLE, CRect(0, 0, 0, 0), this)) {
		AfxMessageBox("IDC_LOCAL_STATUS_SPACE 생성 실패.\n");
		return -1;
	}
	m_stcStatusSpace.SetFont(&pmf->m_font);

	if (!m_stcStatusObject.Create("", WS_VISIBLE, CRect(0, 0, 0, 0), this)) {
		AfxMessageBox("IDC_LOCAL_STATUS_OBJECT 생성 실패.\n");
		return -1;
	}
	m_stcStatusObject.SetFont(&pmf->m_font);

	if (!m_stcStatusMsg.Create("", WS_VISIBLE, CRect(0, 0, 0, 0), this)) {
		AfxMessageBox("IDC_LOCAL_STATUS_MSG 생성 실패.\n");
		return -1;
	}
	m_stcStatusMsg.SetFont(&pmf->m_font);

	if (!m_stcSeparator1.Create("", WS_VISIBLE | WS_BORDER, CRect(0, 0, 1, STATUS_HEIGHT - 2), this)) {
		AfxMessageBox("IDC_LOCAL_STATUS_SEPARATOR 생성 실패.\n");
		return -1;
	}
	m_stcSeparator1.ModifyStyleEx(NULL, WS_EX_STATICEDGE);

	if (!m_stcSeparator2.Create("", WS_VISIBLE | WS_BORDER, CRect(0, 0, 1, STATUS_HEIGHT - 2), this)) {
		AfxMessageBox("IDC_LOCAL_STATUS_SEPARATOR 생성 실패.\n");
		return -1;
	}
	m_stcSeparator2.ModifyStyleEx(NULL, WS_EX_STATICEDGE);

//	m_tree.put_ShList((IDispatch*)m_list.GetControlUnknown());
	m_cboAddr.put_ShTree((IDispatch*)m_tree.GetControlUnknown());
	// 허용시 OleDrop 에러발생
//	m_tree.put_ShList((IDispatch*)m_list.GetControlUnknown());

	ApplyListStyle();

	return 0;
}

void CLocalView::OnSize(UINT nType, int cx, int cy)
{
	CView::OnSize(nType, cx, cy);

	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

	m_cxSplitter = m_cxSplitter > 0 ? m_cxSplitter : 250;

	RedrawControl(cx, cy);

	if (pmf->m_bSizing) {
		m_cboAddr.SetRedraw(FALSE);
		m_tree.SetRedraw(FALSE);
		m_list.SetRedraw(FALSE);
	}

	RedrawControl(cx, cy);

	if (pmf->m_bSizing) {
		m_cboAddr.SetRedraw(TRUE);
		m_tree.SetRedraw(TRUE);
		m_list.SetRedraw(TRUE);
	}
}

BOOL CLocalView::OnEraseBkgnd(CDC* pDC)
{
	return TRUE;
}

void CLocalView::OnTimer(UINT nIDEvent)
{
//	EndWaitCursor();

	KillTimer(m_nTimer);
	m_nTimer = 0;

	if (nIDEvent == TIMER_ID_UPDATESTATUS) {
		if (m_nSelectedFiles > 0)
			m_stcStatusObject.SetWindowText(NumericFormat(m_nSelectedCount) + " 개체가 선택됨, " + BYTE2KMBYTE(m_nSelectedBytes, 0, TRUE));
		else
			m_stcStatusObject.SetWindowText(NumericFormat(m_nSelectedCount) + " 개체가 선택됨");
		AfxGetMainWnd()->PostMessage(WMU_UPDATE_CONTROL_STATUS);
	}
	else if (nIDEvent == TIMER_ID_CHANGEFOLDER) {
		m_list.put_Folder(m_tree.get_SelectedFolder());
		AfxGetMainWnd()->PostMessage(WMU_UPDATE_CONTROL_STATUS);
	}

	CView::OnTimer(nIDEvent);
}

void CLocalView::OnLocalAdvert()
{
	// 여기
}

void CLocalView::OnLocalBtnToolbar()
{
	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

	ASSERT_VALID(pmf);

	pmf->OnViewMidToolbar();
}

void CLocalView::OnLocalBtnUpload()
{
	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

	ASSERT_VALID(pmf);

	pmf->Upload(true);
}

void CLocalView::OnLocalBtnDownload()
{
	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

	ASSERT_VALID(pmf);

	pmf->Download();
}

void CLocalView::OnLocalBtnNewFolder()
{
	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

	ASSERT_VALID(pmf);

	if (pmf->m_fl == FL_LOCAL)
		OnListNewfolder();
	else
		((CRemoteListCtrl*)pmf->m_pRemoteView->GetListCtrl())->OnListNewfolder();
}

void CLocalView::OnLocalBtnDelete()
{
	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

	ASSERT_VALID(pmf);

	if (pmf->m_fl == FL_LOCAL)
		DeleteFile();
	else
		((CRemoteListCtrl*)pmf->m_pRemoteView->GetListCtrl())->OnListfileDelete();
}

void CLocalView::OnLocalTitle()
{
	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

	ASSERT_VALID(pmf);

	pmf->OnViewLtree();
}

/*
void CLocalView::OnLocalBtnGoAddr()
{
	IPTxShTreeNodes *pnodes = (IPTxShTreeNodes*)m_tree.get_Nodes();
	IPTxShTreeNode *pnode;

	long lNodeCount;
	pnodes->get_Count(&lNodeCount);

	BSTR bstrNode;

	for (int i = 0; i < lNodeCount - 1; i++) {
		pnodes->get_Item(i, &pnode);
		pnode->get_DisplayName(&bstrNode);

		CString sNode(bstrNode);

		if (sAddr == sNode) {
			m_tree.put_SelectedNode(pnode);
			break;
		}
	}
}
*/

void CLocalView::OnLocalBtnUpAddr()
{
	m_tree.GoUp(1);
}

void CLocalView::OnLocalBtnListStyle()
{
	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

	pmf->m_nLocalListType++;
	if (pmf->m_nLocalListType == 5)
		pmf->m_nLocalListType = 0;

	ApplyListStyle();
}

/////////////////////////////////////////////////////////////////////////////////////////
// TreeCtrl, ListCtrl event method

BEGIN_EVENTSINK_MAP(CLocalView, CView)
	ON_EVENT(CLocalView, IDC_LOCAL_CBO_ADDR, 100, OnMouseDownLocalCombo, VTS_I2 VTS_I2 VTS_R4 VTS_R4)
	ON_EVENT(CLocalView, IDC_LOCAL_TREE,  10, OnAfterSelChangeLocalTree, VTS_DISPATCH)
	ON_EVENT(CLocalView, IDC_LOCAL_TREE,  15, OnBeforeShellMenuPopupLocalTree, VTS_DISPATCH VTS_DISPATCH VTS_I4 VTS_PBOOL)
	ON_EVENT(CLocalView, IDC_LOCAL_TREE,  16, OnAfterShellMenuSelectionLocalTree, VTS_DISPATCH VTS_I4 VTS_PBOOL)
	ON_EVENT(CLocalView, IDC_LOCAL_TREE,  18, OnOleDragOverLocalTree, VTS_DISPATCH VTS_PI4 VTS_PI2 VTS_PI2 VTS_R4 VTS_R4 VTS_I2)
	ON_EVENT(CLocalView, IDC_LOCAL_TREE,  19, OnOleDragDropLocalTree, VTS_DISPATCH VTS_PI4 VTS_PI2 VTS_PI2 VTS_R4 VTS_R4)
	ON_EVENT(CLocalView, IDC_LOCAL_TREE, 100, OnMouseDownLocalTree, VTS_I2 VTS_I2 VTS_R4 VTS_R4)
	ON_EVENT(CLocalView, IDC_LOCAL_LIST,   7, OnFolderChangedLocalList, VTS_NONE)
	ON_EVENT(CLocalView, IDC_LOCAL_LIST,   8, OnBeforeSelectionChangeLocalList, VTS_DISPATCH VTS_PBOOL)
	ON_EVENT(CLocalView, IDC_LOCAL_LIST,  14, OnAfterFillLocalList, VTS_NONE)
	ON_EVENT(CLocalView, IDC_LOCAL_LIST,  15, OnBeforeShellMenuPopupLocalList, VTS_DISPATCH VTS_DISPATCH VTS_I4 VTS_PBOOL)
	ON_EVENT(CLocalView, IDC_LOCAL_LIST,  16, OnAfterShellMenuSelectionLocalList, VTS_DISPATCH VTS_I4 VTS_PBOOL)
	ON_EVENT(CLocalView, IDC_LOCAL_LIST,  17, OnItemContextMenuLocalList, VTS_DISPATCH VTS_R4 VTS_R4 VTS_PBOOL)
	ON_EVENT(CLocalView, IDC_LOCAL_LIST,  18, OnOleDragOverLocalList, VTS_DISPATCH VTS_PI4 VTS_PI2 VTS_PI2 VTS_R4 VTS_R4 VTS_I2)
	ON_EVENT(CLocalView, IDC_LOCAL_LIST,  19, OnOleDragDropLocalList, VTS_DISPATCH VTS_PI4 VTS_PI2 VTS_PI2 VTS_R4 VTS_R4)
	ON_EVENT(CLocalView, IDC_LOCAL_LIST, 102, OnMouseUpLocalList, VTS_I2 VTS_I2 VTS_R4 VTS_R4)
END_EVENTSINK_MAP()

void CLocalView::OnMouseDownLocalCombo(short aButton, short aShift, float ax, float ay)
{
	((CMainFrame*)AfxGetMainWnd())->SetFocus(this);
}

void CLocalView::OnAfterSelChangeLocalTree(LPDISPATCH aSelectedNode)
{
	if (!m_pnodeRoot)
		m_pnodeRoot = (IPTxShTreeNode*)aSelectedNode;

	m_nTimer = (UINT)SetTimer(TIMER_ID_CHANGEFOLDER, 1, 0);

	AfxGetMainWnd()->PostMessage(WMU_UPDATE_CONTROL_STATUS);
}

void CLocalView::OnBeforeShellMenuPopupLocalTree(LPDISPATCH aMenu, LPDISPATCH aSelectedNode, long aNextCustomMenuId, BOOL* aCancelMenu)
{
	IPTxContextMenu *pcontextmenu = (IPTxContextMenu *)aMenu;

	IPTxMenuItems *pmenuitems;
	pcontextmenu->get_MenuItems(&pmenuitems);

	IPTxMenuItem *pmenuitem;

	m_nPasteMenuId = -1;

	// 선택된 트리의 노드가 파일시스템?
	IPTxShTreeNode *pnode = (IPTxShTreeNode*)aSelectedNode;

	VARIANT_BOOL bFileSystem;
	pnode->get_IsFileSystem(&bFileSystem);
	if (!bFileSystem)
		return;

	BSTR bstr;
	pnode->get_PathName(&bstr);
	CString sPath(bstr);
	::SysFreeString(bstr);
	if (sPath == "")
		return;

	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

	// 클립보드에 데이터가 있나?
	COleDataObject odo;

	if (!(odo.AttachClipboard() && odo.IsDataAvailable(CF_HDROP))
		&& !(pmf->m_cbs != CBS_NONE && pmf->m_saDragSource.GetCount() > 0))
		return;

	DWORD dwAttr = GetFileAttributes(sPath);
	if (dwAttr == INVALID_FILE_ATTRIBUTES)
		return;

	if (!(dwAttr & FILE_ATTRIBUTE_DIRECTORY))
		return;

	int iCopyPos = -1, iPastePos = -1;

	long nCount;
	pmenuitems->get_Count(&nCount);
	for (int i = 0; i < nCount; i++) {
		pmenuitems->get_Item(i, &pmenuitem);

		BSTR bstr;
		pmenuitem->get_Caption(&bstr);
		CString sCaption(bstr);
		::SysFreeString(bstr);

		if (!sCaption.Left(4).Compare("복사"))
			iCopyPos = i;
		else if (!sCaption.Left(8).Compare("붙여넣기"))
			iPastePos = i;
	}

	if (iPastePos > 0) {
		pmenuitems->get_Item(iPastePos, &pmenuitem);
		pmenuitem->put_Enabled(TRUE);
		pmenuitem->get_CommandId(&m_nPasteMenuId);
	}
	else if (iCopyPos > 0 && iPastePos < 0) {
		m_nPasteMenuId = aNextCustomMenuId + 1;
		CString sMenuCaption = "붙여넣기(&P)";
		pmenuitems->InsertItem(iCopyPos + 1, m_nPasteMenuId, sMenuCaption.AllocSysString(), &pmenuitem);
		pmenuitem->put_Enabled(TRUE);
	}

	m_sSelectedPath = sPath;
}

void CLocalView::OnAfterShellMenuSelectionLocalTree(LPDISPATCH aSelectedNode, long aSelectedMenuId, BOOL* aCancelDefaultBehaviour)
{
	if (aSelectedMenuId == m_nPasteMenuId)
		m_list.PasteClipboard(m_sSelectedPath);
}

void CLocalView::OnOleDragOverLocalTree(LPDISPATCH AData, long* aEffect, short* aButton, short* aShift, float ax, float ay, short aState)
{
	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

	if (!pmf->m_bDragFromRemote)
		return;

	IPTxShTreeNode* pnode = (IPTxShTreeNode*)m_tree.HitTest(ax, ay);
	if (!pnode) {
		*aEffect = DROPEFFECT_NONE;
		return;
	}

	BSTR bstr;
	pnode->get_PathName(&bstr);
	CString sPath(bstr);
	::SysFreeString(bstr);

	if (sPath == "")
		*aEffect = DROPEFFECT_NONE;
	else
		*aEffect = DROPEFFECT_COPY;
}

void CLocalView::OnOleDragDropLocalTree(LPDISPATCH AData, long* aEffect, short* aButton, short* aShift, float ax, float ay)
{
	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

	if (!pmf->m_bDragFromRemote)
		return;

	IPTxShTreeNode* pnode = (IPTxShTreeNode*)m_tree.HitTest(ax, ay);
	if (!pnode)
		return;

	BSTR bstr;
	pnode->get_PathName(&bstr);
	CString sPath(bstr);
	::SysFreeString(bstr);

	if (sPath == "")
		return;

	pmf->m_sDragTarget = sPath;

	pmf->Download(false);
}

void CLocalView::OnMouseDownLocalTree(short aButton, short aShift, float ax, float ay)
{
	((CMainFrame *)AfxGetMainWnd())->SetFocus(this);
}

void CLocalView::OnFolderChangedLocalList()
{
	m_tree.put_SelectedFolder(m_list.get_Folder());
}

void CLocalView::OnBeforeSelectionChangeLocalList(LPDISPATCH aItem, BOOL* aCancel)
{
	if (m_bUpdating)
		return;

//	BeginWaitCursor();

	if (*aCancel != 0xEDBC0000) {
		IPTxShListItem *pitem = (IPTxShListItem *)aItem;

		INT64 nBytes;
		pitem->get_Size64(&nBytes);

		BSTR bstrPath;
		pitem->get_PathName(&bstrPath);
		CString sPath(bstrPath);
		::SysFreeString(bstrPath);

		VARIANT_BOOL bSelected;
		pitem->get_Selected(&bSelected);

		if (!bSelected) {
			if (sPath == "")
				m_nSelectedSecialObj++;

			if (nBytes >= 0)
				m_nSelectedFiles++;

			m_nSelectedCount++;
			m_nSelectedBytes += nBytes < 0 ? 0 : nBytes;
		}
		else {
			if (sPath == "")
				m_nSelectedSecialObj--;

			if (nBytes >= 0)
				m_nSelectedFiles--;

			m_nSelectedCount--;
			m_nSelectedBytes -= nBytes < 0 ? 0 : nBytes;
		}
	}
	else {
		m_nSelectedCount     = 0;
		m_nSelectedBytes     = 0;
		m_nSelectedFiles     = 0;
		m_nSelectedSecialObj = 0;
	}

	if (m_nSelectedCount > 0) {
		if (m_nTimer != 0)
			KillTimer(m_nTimer);

		m_nTimer = (UINT)SetTimer(TIMER_ID_UPDATESTATUS, 10, 0);
	}
	else {
		if (m_nTimer != 0)
			KillTimer(m_nTimer);

		if (m_nTotalBytes >= 0)
			m_stcStatusObject.SetWindowText(NumericFormat(m_nTotalCount) + " 개체, " + BYTE2KMBYTE(m_nTotalBytes, 0, TRUE));
		else
			m_stcStatusObject.SetWindowText(NumericFormat(m_nTotalCount) + " 개체");
	}

	AfxGetMainWnd()->PostMessage(WMU_UPDATE_CONTROL_STATUS);
}

void CLocalView::OnAfterFillLocalList()
{
	IPTxShTreeNode *pnode = (IPTxShTreeNode*)m_tree.get_SelectedNode();

	// Path 구하기
	BSTR bstr;
	pnode->get_PathName(&bstr);
	CString sPath(bstr);
	::SysFreeString(bstr);

	typedef BOOL (WINAPI *PGETDISKFREESPACEEX)(LPCSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);

	if (sPath.GetLength() > 0) {
		PGETDISKFREESPACEEX pGetDiskFreeSpaceEx;

		__int64 nTotalBytes, nFreeBytes;
		BOOL    bRet;

		pGetDiskFreeSpaceEx = (PGETDISKFREESPACEEX)GetProcAddress(GetModuleHandle("kernel32.dll"), "GetDiskFreeSpaceExA");

		if (pGetDiskFreeSpaceEx) {
			__int64 nFreeBytesToCaller;
			bRet = pGetDiskFreeSpaceEx(sPath, (PULARGE_INTEGER)&nFreeBytesToCaller, (PULARGE_INTEGER)&nTotalBytes, (PULARGE_INTEGER)&nFreeBytes);
		}
		else {
			DWORD dwSectPerClust, dwBytesPerSect, dwFreeClusters, dwTotalClusters;
			bRet = GetDiskFreeSpaceA(sPath, &dwSectPerClust, &dwBytesPerSect, &dwFreeClusters, &dwTotalClusters);

			nTotalBytes = dwTotalClusters * dwSectPerClust * dwBytesPerSect;
			nFreeBytes  = dwFreeClusters * dwSectPerClust * dwBytesPerSect;
		}

		if (bRet) {
			CString sText = " 디스크 여유 공간: ";
			sText += BYTE2KMBYTE(nFreeBytes, 0, TRUE);
			m_stcStatusSpace.SetWindowText(sText);

			int nPercent = (int)((nFreeBytes * 100) / nTotalBytes);
			sText.Format("%d%% 남음", nPercent);
			m_prgStatusSpace.SetPos(100 - nPercent, sText);
			m_prgStatusSpace.ShowWindow(SW_SHOW);
		}
		else {
			m_prgStatusSpace.ShowWindow(SW_HIDE);
			m_stcStatusSpace.SetWindowText(GetErrorMessage(GetLastError()));
		}
	}
	else {
		m_prgStatusSpace.ShowWindow(SW_HIDE);
		m_stcStatusSpace.SetWindowText("");
	}

	IPTxShListItems *pitems = (IPTxShListItems *)m_list.get_Items();

	long nTotalCount;

	pitems->get_Count(&nTotalCount);

	VARIANT_BOOL bFileSystem;

//	IPTxShTreeNode *pnode = (IPTxShTreeNode*)m_tree.get_SelectedNode();
	pnode->get_IsFileSystem(&bFileSystem);
	if (bFileSystem) {
		CFileStatus64 fs;
		__int64 nTotalBytes = 0;

		IPTxShListItem *pitem;
		for (int i = 0; i < nTotalCount; i++) {
			pitems->get_Item(i, &pitem);

			BSTR bstr;
			pitem->get_PathName(&bstr);
			CString sPath(bstr);
			::SysFreeString(bstr);

			if (GetStatus64(sPath, fs))
				nTotalBytes += fs.m_size;
		}

		m_stcStatusObject.SetWindowText(NumericFormat(nTotalCount) + " 개체, " + BYTE2KMBYTE(nTotalBytes, 0, TRUE));

		m_nTotalBytes = nTotalBytes;
	}
	else {
		m_stcStatusObject.SetWindowText(NumericFormat(nTotalCount) + " 개체");

		m_nTotalBytes = -1;
	}

	m_nTotalCount = nTotalCount;
}

void CLocalView::OnItemContextMenuLocalList(LPDISPATCH aItem, float ax, float ay, BOOL* aCancelDefaultMenu)
{
	m_bIgnoreEvent = TRUE;
}

void CLocalView::OnBeforeShellMenuPopupLocalList(LPDISPATCH aMenu, LPDISPATCH aSelectedItems, long aNextCustomMenuId, BOOL* aCancelMenu)
{
	IPTxContextMenu *pcontextmenu = (IPTxContextMenu *)aMenu;

	IPTxMenuItems *pmenuitems;
	pcontextmenu->get_MenuItems(&pmenuitems);

	IPTxMenuItem *pmenuitem;

	CString sMenuCaption = "***** 올리기 *****";
	pmenuitems->InsertItem(0, aNextCustomMenuId, sMenuCaption.AllocSysString(), &pmenuitem);

	pmenuitem->put_Enabled(!(m_btnUpload.GetStyle() & WS_DISABLED));
	pmenuitem->put_Break(TRUE);

	sMenuCaption = "-";
	pmenuitems->InsertItem(1, 0, sMenuCaption.AllocSysString(), &pmenuitem);

	m_nUploadMenuId = aNextCustomMenuId;

	m_nPasteMenuId = -1;

	// 선택된 트리의 노드가 파일시스템?
	IPTxShTreeNode *pnode = (IPTxShTreeNode*)m_tree.get_SelectedNode();

	VARIANT_BOOL bFileSystem;
	pnode->get_IsFileSystem(&bFileSystem);
	if (!bFileSystem)
		return;

	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

	// 클립보드에 데이터가 있나?
	COleDataObject odo;

	if (!(odo.AttachClipboard() && odo.IsDataAvailable(CF_HDROP))
		&& !(pmf->m_cbs != CBS_NONE && pmf->m_saDragSource.GetCount() > 0))
		return;

	// 선택된 
	if (m_nSelectedCount != 1)
		return;

	IPTxShListItems *pitems = (IPTxShListItems *)m_list.get_Items();

	long nCount;
	pitems->get_Count(&nCount);

	IPTxShListItem *pitem;
	for (int i = 0; i < nCount; i++) {
		pitems->get_Item(i, &pitem);

		VARIANT_BOOL bSelected;
		pitem->get_Selected(&bSelected);
		if (!bSelected)
			continue;

		BSTR bstr;
		pitem->get_PathName(&bstr);
		CString sPath(bstr);
		::SysFreeString(bstr);
		if (sPath == "")
			continue;

		DWORD dwAttr = GetFileAttributes(sPath);
		if (dwAttr == INVALID_FILE_ATTRIBUTES)
			break;

		if (!(dwAttr & FILE_ATTRIBUTE_DIRECTORY))
			break;

		int iCopyPos = -1, iPastePos = -1;
		pmenuitems->get_Count(&nCount);
		for (int i = 0; i < nCount; i++) {
			pmenuitems->get_Item(i, &pmenuitem);

			BSTR bstr;
			pmenuitem->get_Caption(&bstr);
			CString sCaption(bstr);
			::SysFreeString(bstr);

			if (!sCaption.Left(4).Compare("복사"))
				iCopyPos = i;
			else if (!sCaption.Left(8).Compare("붙여넣기"))
				iPastePos = i;
		}

		if (iPastePos > 0) {
			pmenuitems->get_Item(iPastePos, &pmenuitem);
			pmenuitem->put_Enabled(TRUE);
			pmenuitem->get_CommandId(&m_nPasteMenuId);
		}
		else if (iCopyPos > 0 && iPastePos < 0) {
			m_nPasteMenuId = aNextCustomMenuId + 1;
			sMenuCaption = "붙여넣기(&P)";
			pmenuitems->InsertItem(iCopyPos + 1, m_nPasteMenuId, sMenuCaption.AllocSysString(), &pmenuitem);
			pmenuitem->put_Enabled(TRUE);
		}

		m_sSelectedPath = sPath;

		break;
	}
}

void CLocalView::OnAfterShellMenuSelectionLocalList(LPDISPATCH aSelectedItems, long aSelectedMenuItemId, BOOL* aCancelDefaultBehaviour)
{
	if (aSelectedMenuItemId == m_nUploadMenuId)
		OnLocalBtnUpload();
	else if (aSelectedMenuItemId == m_nPasteMenuId)
		m_list.PasteClipboard(m_sSelectedPath);
}

void CLocalView::OnOleDragOverLocalList(LPDISPATCH AData, long* aEffect, short* aButton, short* aShift, float ax, float ay, short aState)
{
	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

	if (!pmf->m_bDragFromRemote)
		return;

	if (!m_pwndPrevFocused)
	{
		m_pwndPrevFocused = GetFocus();
		m_list.SendMessage(WM_SETFOCUS);
	}

	if (m_pitemPrev)
		m_pitemPrev->put_Selected(m_bPrevItemSelected);

	IPTxShListItem* pitem = (IPTxShListItem*)m_list.HitTest(ax, ay);
	if (!pitem)
	{
		m_pitemPrev = NULL;

		*aEffect = DROPEFFECT_COPY;
	}
	else
	{
		m_pitemPrev = pitem;
		pitem->get_Selected(&m_bPrevItemSelected);

		pitem->put_Selected(TRUE);

		*aEffect = DROPEFFECT_NONE;

		BSTR bstr;
		pitem->get_PathName(&bstr);
		CString sPath(bstr);
		::SysFreeString(bstr);

		if (sPath != "" && GetFileAttributes(sPath) & FILE_ATTRIBUTE_DIRECTORY)
			*aEffect = DROPEFFECT_COPY;
	}
}

void CLocalView::OnOleDragDropLocalList(LPDISPATCH AData, long* aEffect, short* aButton, short* aShift, float ax, float ay)
{
	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

	if (!pmf->m_bDragFromRemote)
		return;

	if (m_pitemPrev)
		m_pitemPrev->put_Selected(m_bPrevItemSelected);

	IPTxShListItem* pitem = (IPTxShListItem*)m_list.HitTest(ax, ay);
	if (!pitem)
	{
		IPTxShFolder* pfolder = (IPTxShFolder*)m_tree.get_SelectedFolder();

		BSTR bstr;
		pfolder->get_PathName(&bstr);
		CString sPath(bstr);
		::SysFreeString(bstr);

		pmf->m_sDragTarget = sPath;
	}
	else
	{
		*aEffect = DROPEFFECT_NONE;

		BSTR bstr;
		pitem->get_PathName(&bstr);
		CString sPath(bstr);
		::SysFreeString(bstr);

		if (sPath == "" || !(GetFileAttributes(sPath) & FILE_ATTRIBUTE_DIRECTORY))
			return;

		pmf->m_sDragTarget = sPath;
	}

	pmf->Download(false);
}

void CLocalView::OnMouseUpLocalList(short aButton, short aShift, float ax, float ay)
{
	if (aButton != 2 || m_list.HitTest(ax, ay) || m_bIgnoreEvent) {
		m_bIgnoreEvent = FALSE;
		return;
	}

	CMainFrame *pmf = (CMainFrame *)AfxGetMainWnd();

	CMenu menu, *pmenu;

	menu.LoadMenu(IDR_POP_LLIST);
	pmenu = menu.GetSubMenu(0);
	ASSERT(pmenu != NULL);

	pmenu->SetMenuItemBitmaps(ID_LIST_NEWFOLDER, MF_BYCOMMAND, &pmf->m_bmFolder, &pmf->m_bmFolder);
	pmenu->SetMenuItemBitmaps(ID_LIST_PASTE, MF_BYCOMMAND, &pmf->m_bmPaste, &pmf->m_bmPaste);

	switch (pmf->m_nLocalListType) {
	case 0:
		pmenu->CheckMenuItem(ID_LIST_TYPE0, MF_CHECKED);
		break;
	case 1:
		pmenu->CheckMenuItem(ID_LIST_TYPE1, MF_CHECKED);
		break;
	case 2:
		pmenu->CheckMenuItem(ID_LIST_TYPE2, MF_CHECKED);
		break;
	case 3:
		pmenu->CheckMenuItem(ID_LIST_TYPE3, MF_CHECKED);
		break;
	case 4:
		pmenu->CheckMenuItem(ID_LIST_TYPE4, MF_CHECKED);
		break;
	}

	switch (abs(m_list.get_SortColumn())) {
	case 1:
	case 5:
		pmenu->CheckMenuItem(ID_LIST_SORT1, MF_CHECKED);
		break;
	case 2:
		pmenu->CheckMenuItem(ID_LIST_SORT2, MF_CHECKED);
		break;
	case 3:
		pmenu->CheckMenuItem(ID_LIST_SORT3, MF_CHECKED);
		break;
	case 4:
		pmenu->CheckMenuItem(ID_LIST_SORT4, MF_CHECKED);
		break;
	}

	COleDataObject odo;

	if (!(odo.AttachClipboard() && odo.IsDataAvailable(CF_HDROP))
		&& !(pmf->m_cbs != CBS_NONE && pmf->m_saDragSource.GetCount() > 0))
		pmenu->EnableMenuItem(ID_LIST_PASTE, MF_GRAYED);

	CPoint pt((int)ax + 1, (int)ay + 1);
	m_list.ClientToScreen(&pt);
	pmenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, this);
}

void CLocalView::OnListNewfolder()
{
	m_list.CreateNewFolder(TRUE);
}

void CLocalView::OnListRefresh() 
{
	m_tree.Refresh();
	m_list.Refresh();
}

void CLocalView::OnListType0() 
{
	CMainFrame *pmf = (CMainFrame *)AfxGetMainWnd();

	pmf->OnViewLlistType0();
}

void CLocalView::OnListType1() 
{
	CMainFrame *pmf = (CMainFrame *)AfxGetMainWnd();

	pmf->OnViewLlistType1();
}

void CLocalView::OnListType2() 
{
	CMainFrame *pmf = (CMainFrame *)AfxGetMainWnd();

	pmf->OnViewLlistType2();
}

void CLocalView::OnListType3() 
{
	CMainFrame *pmf = (CMainFrame *)AfxGetMainWnd();

	pmf->OnViewLlistType3();
}

void CLocalView::OnListType4() 
{
	CMainFrame *pmf = (CMainFrame *)AfxGetMainWnd();

	pmf->OnViewLlistType4();
}

void CLocalView::OnListSort1() 
{
	int nSort = m_list.get_SortColumn();

	if (abs(nSort) == 1)
		m_list.put_SortColumn(-nSort);
	else if (nSort > 0)
		m_list.put_SortColumn(1);
	else
		m_list.put_SortColumn(-1);
}

void CLocalView::OnListSort2() 
{
	int nSort = m_list.get_SortColumn();

	if (abs(nSort) == 2)
		m_list.put_SortColumn(-nSort);
	else if (nSort > 0)
		m_list.put_SortColumn(2);
	else
		m_list.put_SortColumn(-2);
}

void CLocalView::OnListSort3() 
{
	int nSort = m_list.get_SortColumn();

	if (abs(nSort) == 3)
		m_list.put_SortColumn(-nSort);
	else if (nSort > 0)
		m_list.put_SortColumn(3);
	else
		m_list.put_SortColumn(-3);
}

void CLocalView::OnListSort4() 
{
	int nSort = m_list.get_SortColumn();

	if (abs(nSort) == 4)
		m_list.put_SortColumn(-nSort);
	else if (nSort > 0)
		m_list.put_SortColumn(4);
	else
		m_list.put_SortColumn(-4);
}

void CLocalView::OnListPaste() 
{
	m_list.PasteClipboard();
}

void CLocalView::OnListAll() 
{
	IPTxShListItems* pitems = (IPTxShListItems*)m_list.get_Items();

	long nCount;
	pitems->get_Count(&nCount);

	IPTxShListItem* pitem;
	for (int i = 0; i < nCount; i++)
	{
		pitems->get_Item(i, &pitem);

		pitem->put_Selected(TRUE);
	}
}


/////////////////////////////////////////////////////////////////////////////////////////
// User defined method

void CLocalView::RedrawFocus()
{
	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

	if (!pmf->m_bShowLocalTree)
		return;

	RECT rc;
	GetClientRect(&rc);

	CDC* pDC = GetDC();

	CBrush br;

	br.CreateSysColorBrush(COLOR_CAPTIONTEXT);
	rc.left  = m_cxSplitter;
	rc.right = m_cxSplitter + SPLITTER_SIZE;
	rc.top   = (pmf->m_bShowMidToolBar ? TOOLBAR_HEIGHT : TOOLBAR_BTN_HEIGHT) + CAPTION_HEIGHT + 1;
	pDC->FillRect(&rc, &br);
	br.DeleteObject();

	br.CreateSysColorBrush(pmf->m_fl == FL_LOCAL ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION);
	rc.left  = m_cxSplitter + 1;
	rc.right = m_cxSplitter + SPLITTER_SIZE - 2;
	pDC->FillRect(&rc, &br);
	br.DeleteObject();

	ReleaseDC(pDC);
}

void CLocalView::RedrawControl(int cx, int cy)
{
	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

	if (!pmf)
		return;

	int cxList;
	int cyToolBar   = pmf->m_bShowMidToolBar  ? TOOLBAR_HEIGHT : TOOLBAR_BTN_HEIGHT;
	int cyStatusBar = pmf->m_bShowLocalStatus ? STATUS_HEIGHT  : 0;

	m_btnToolBar.LoadBitmaps(pmf->m_bShowMidToolBar ? IDB_BTN_TOOLBAR1 : IDB_BTN_TOOLBAR2);

	HDWP hdwp = BeginDeferWindowPos(22);
	if (hdwp) {
		DeferWindowPos(hdwp, m_capToolBar.m_hWnd, HWND_TOP, 0, 0, cx, pmf->m_bShowMidToolBar ? cyToolBar : 0, SWP_NOZORDER);
		DeferWindowPos(hdwp, m_btnToolBar.m_hWnd, HWND_TOP, cx - (TOOLBAR_BTN_WIDTH + 1), 0, TOOLBAR_BTN_WIDTH, TOOLBAR_BTN_HEIGHT, SWP_NOZORDER);
		if (pmf->m_bShowMidToolBar) {
			DeferWindowPos(hdwp, m_stcAdvert.m_hWnd, HWND_TOP, 10, 3, 285, 35, SWP_NOZORDER);
			DeferWindowPos(hdwp, m_btnUpload.m_hWnd, HWND_TOP, 350, 7, 80, 26, SWP_NOZORDER);
			DeferWindowPos(hdwp, m_btnDownload.m_hWnd, HWND_TOP, 435, 7, 80, 24, SWP_NOZORDER);
			DeferWindowPos(hdwp, m_btnNewFolder.m_hWnd, HWND_TOP, 520, 7, 80, 24, SWP_NOZORDER);
			DeferWindowPos(hdwp, m_btnDelete.m_hWnd, HWND_TOP, 605, 7, 80, 24, SWP_NOZORDER);
		}
		else {
			DeferWindowPos(hdwp, m_stcAdvert.m_hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER);
			DeferWindowPos(hdwp, m_btnUpload.m_hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER);
			DeferWindowPos(hdwp, m_btnDownload.m_hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER);
			DeferWindowPos(hdwp, m_btnNewFolder.m_hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER);
			DeferWindowPos(hdwp, m_btnDelete.m_hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER);
		}
		if (pmf->m_bShowLocalTree) {
			cxList = m_cxSplitter + SPLITTER_SIZE;
			DeferWindowPos(hdwp, m_capTitleIcon.m_hWnd, HWND_TOP, HIGHLIGHT_SIZE + 3, HIGHLIGHT_SIZE + cyToolBar + 3, 16, 16, SWP_NOZORDER);
			DeferWindowPos(hdwp, m_capTitle.m_hWnd, HWND_TOP, HIGHLIGHT_SIZE, HIGHLIGHT_SIZE + cyToolBar, m_cxSplitter + 1, CAPTION_HEIGHT, SWP_NOZORDER);
			DeferWindowPos(hdwp, m_tree.m_hWnd, HWND_TOP, -1, HEADER_HEIGHT + cyToolBar, m_cxSplitter + 1, cy - HEADER_HEIGHT - cyStatusBar - cyToolBar, SWP_NOZORDER);
		}
		else {
			cxList = 0;
			DeferWindowPos(hdwp, m_capTitleIcon.m_hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER);
			DeferWindowPos(hdwp, m_capTitle.m_hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER);
			DeferWindowPos(hdwp, m_tree.m_hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER);
		}
		DeferWindowPos(hdwp, m_capAddr.m_hWnd, HWND_TOP, cxList - 3, HIGHLIGHT_SIZE + cyToolBar, ADDRESS_WIDTH + 3, CAPTION_HEIGHT, SWP_NOZORDER);
		DeferWindowPos(hdwp, m_cboAddr.m_hWnd, HWND_TOP, cxList + ADDRESS_WIDTH, HIGHLIGHT_SIZE + cyToolBar, cx - (cxList + (ADDRESS_BTN_WIDTH << 1)) - ADDRESS_WIDTH - 1, 200, SWP_NOZORDER);
		DeferWindowPos(hdwp, m_btnUpAddr.m_hWnd, HWND_TOP, cx - (ADDRESS_BTN_WIDTH << 1) - 1, HIGHLIGHT_SIZE + cyToolBar + 1, ADDRESS_BTN_WIDTH, CAPTION_HEIGHT, SWP_NOZORDER);
		DeferWindowPos(hdwp, m_btnListStyle.m_hWnd, HWND_TOP, cx - ADDRESS_BTN_WIDTH - 1, HIGHLIGHT_SIZE + cyToolBar + 1, ADDRESS_BTN_WIDTH, CAPTION_HEIGHT, SWP_NOZORDER);
		DeferWindowPos(hdwp, m_list.m_hWnd, HWND_TOP, cxList - 1, HEADER_HEIGHT + cyToolBar, cx - cxList + 1, cy - HEADER_HEIGHT - cyStatusBar - cyToolBar, SWP_NOZORDER);
		DeferWindowPos(hdwp, m_capStatus.m_hWnd, HWND_TOP, 0, cy - cyStatusBar, cx, cyStatusBar, SWP_NOZORDER);
		if (pmf->m_bShowLocalStatus) {
			int nTop = cy - cyStatusBar + 4;
			DeferWindowPos(hdwp, m_prgStatusSpace.m_hWnd, HWND_TOP, 0, nTop - 4, 77, cyStatusBar - 1, SWP_NOZORDER | SWP_FRAMECHANGED);
			DeferWindowPos(hdwp, m_stcStatusSpace.m_hWnd, HWND_TOP, 80, nTop, 170, STATUS_TEXT_HEIGHT, SWP_NOZORDER | SWP_FRAMECHANGED);
			DeferWindowPos(hdwp, m_stcStatusObject.m_hWnd, HWND_TOP, 255, nTop, 170, STATUS_TEXT_HEIGHT, SWP_NOZORDER);
			DeferWindowPos(hdwp, m_stcStatusMsg.m_hWnd, HWND_TOP, 430, nTop, cx - 435, STATUS_TEXT_HEIGHT, SWP_NOZORDER);
			DeferWindowPos(hdwp, m_stcSeparator1.m_hWnd, HWND_TOP, 253, nTop - 3, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
			DeferWindowPos(hdwp, m_stcSeparator2.m_hWnd, HWND_TOP, 428, nTop - 3, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
		}
		else {
			DeferWindowPos(hdwp, m_prgStatusSpace.m_hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER);
			DeferWindowPos(hdwp, m_stcStatusSpace.m_hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER);
			DeferWindowPos(hdwp, m_stcStatusObject.m_hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER);
			DeferWindowPos(hdwp, m_stcStatusMsg.m_hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER);
			DeferWindowPos(hdwp, m_stcSeparator1.m_hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
			DeferWindowPos(hdwp, m_stcSeparator2.m_hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
		}
		EndDeferWindowPos(hdwp);
	}

	RedrawFocus();
}

void CLocalView::RedrawControlEx()
{
	RECT rc;
	GetClientRect(&rc);

	RedrawControl(rc.right, rc.bottom);
}

void CLocalView::ApplyListStyle()
{
	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

	ASSERT(pmf);

	switch (pmf->m_nLocalListType) {
	case 0:
		m_list.put_ViewStyle(m_list.ptvsThumbnails);
		break;
	case 1:
		m_list.put_ViewStyle(m_list.ptvsIcon);
		break;
	case 2:
		m_list.put_ViewStyle(m_list.ptvsSmallIcon);
		break;
	case 3:
		m_list.put_ViewStyle(m_list.ptvsList);
		break;
	case 4:
		m_list.put_ViewStyle(m_list.ptvsReport);
		break;
	}
}

BOOL CLocalView::GetSelectedObject(CStringArray& saObject)
{
	CMainFrame *pmf = (CMainFrame *)AfxGetMainWnd();

	BOOL bFoundSystemObject = FALSE;

	VARIANT_BOOL vbool;
	BSTR         bstr;
	if (pmf->m_pwndLocal == &m_list) {
		IPTxShListItems *pitems = (IPTxShListItems *)m_list.get_Items();

		long nCount;
		pitems->get_Count(&nCount);

		IPTxShListItem *pitem;
		for (int i = 0; i < nCount; i++) {
			pitems->get_Item(i, &pitem);

			pitem->get_Selected(&vbool);
			if (!vbool)
				continue;

			pitem->get_IsFileSystem(&vbool);
			if (!vbool) {
				bFoundSystemObject = TRUE;
				continue;
			}

			pitem->get_PathName(&bstr);

			CString sPath(bstr);

			::SysFreeString(bstr);

			saObject.Add(sPath);
		}
	}
	else {
		IPTxShTreeNode *pnode = (IPTxShTreeNode *)m_tree.get_SelectedNode();

		pnode->get_IsFileSystem(&vbool);
		if (!vbool)
			bFoundSystemObject = TRUE;
		else {
			pnode->get_PathName(&bstr);

			CString sPath(bstr);

			::SysFreeString(bstr);

			saObject.Add(sPath);
		}
	}

	if (bFoundSystemObject)
		AfxMessageBox("시스템 파일은 업로드 할 수 없습니다.", MB_ICONEXCLAMATION);

	return saObject.GetCount() > 0 ? TRUE : FALSE;
}

BOOL CLocalView::SetPath(CString sPath)
{
	return TRUE;
}

CString CLocalView::GetSelectedPath()
{
	IPTxShFolder* pfolder = (IPTxShFolder*)m_tree.get_SelectedFolder();

	BSTR bstrPath;
	pfolder->get_PathName(&bstrPath);
	CString sPath(bstrPath);
	::SysFreeString(bstrPath);

	return sPath;
}

BOOL CLocalView::IsSelected()
{
	return m_nSelectedCount > 0 ? TRUE : FALSE;
}

BOOL CLocalView::IsSpecialObjectSelected()
{
	return m_nSelectedSecialObj > 0 ? TRUE : FALSE;
}

void CLocalView::InvertTracker(int x)
{
	CMainFrame *pmf = (CMainFrame *)AfxGetMainWnd();

	CRect rc;
	GetWindowRect(&rc);
	pmf->ScreenToClient(&rc);

	rc.top    += ((pmf->m_bShowMidToolBar ? TOOLBAR_HEIGHT : TOOLBAR_BTN_HEIGHT) + CAPTION_HEIGHT + 2);
	rc.bottom -= (STATUS_HEIGHT + 2);

	CDC* pDC = pmf->GetDC();

	CBrush* pBrush    = CBrush::FromHandle((HBRUSH)::GetStockObject(WHITE_BRUSH));
	HBRUSH  hOldBrush = NULL;

	if (pBrush != NULL)
		hOldBrush = (HBRUSH)SelectObject(pDC->m_hDC, pBrush->m_hObject);

	pDC->PatBlt(x, rc.top, SPLITTER_SIZE - 1, rc.Height(), PATINVERT);

	if (hOldBrush != NULL)
		SelectObject(pDC->m_hDC, hOldBrush);

	ReleaseDC(pDC);
}

void CLocalView::StartDrag()
{
	m_bUpdating = TRUE;

	m_pwndPrevFocused = NULL;
	m_pitemPrev       = NULL;
}

void CLocalView::EndDrag()
{
	m_bUpdating = FALSE;

	if (m_pwndPrevFocused)
		m_pwndPrevFocused->SetFocus();
}

void CLocalView::RefreshItem()
{
	m_tree.Refresh();
	m_list.Refresh();
}

BOOL CLocalView::CopyClipboard(COleDataObject& odo, CString sTargetPath, BOOL bErase)
{
	STGMEDIUM sm;
	FORMATETC fe = {CF_HDROP, (DVTARGETDEVICE FAR*)NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};

	if (!odo.GetData(CF_HDROP, &sm, &fe))
		return FALSE;

	HDROP hdrop = (HDROP)sm.hGlobal;

	int nDragCount = ::DragQueryFile(hdrop, 0xFFFFFFFF, NULL, 0);
	if (nDragCount == 0)
		return FALSE;

	CMainFrame* pmf = (CMainFrame*)AfxGetMainWnd();

	pmf->m_saDragSource.RemoveAll();

	char szFile[MAX_PATH];
	int  nBufSize = 0;
	for (int i = 0; i < nDragCount; i++)
	{
		::DragQueryFile(hdrop, i, szFile, sizeof(szFile));

		CString sFile(szFile);
		if (sFile.Find('\\') < 0)
			continue;

		pmf->m_saDragSource.Add(sFile);
		nBufSize += sFile.GetLength() + 2;
	}

	if (pmf->m_saDragSource.GetCount() == 0)
		return FALSE;

	char* pszBuf = new char[nBufSize];

	WORD wFlag = FOF_MULTIDESTFILES;

	int iPos = 0;
	for (i = 0; i < pmf->m_saDragSource.GetCount(); i++) {
		CopyMemory(&pszBuf[iPos], pmf->m_saDragSource[i], pmf->m_saDragSource[i].GetLength());
		iPos += pmf->m_saDragSource[i].GetLength();
		CopyMemory(&pszBuf[iPos], "\0\0", 2);
		iPos += 2;

		if (pmf->m_saDragSource[i].Left(pmf->m_saDragSource[i].ReverseFind('\\')) == sTargetPath)
			wFlag |= FOF_RENAMEONCOLLISION;
	}

	SHFILEOPSTRUCT shfo;
	ZeroMemory(&shfo, sizeof(shfo));
	shfo.wFunc  = FO_COPY;
	shfo.fFlags = wFlag;
	shfo.pFrom  = pszBuf;
	shfo.pTo    = sTargetPath;

	int nRet = SHFileOperation(&shfo);

	delete pszBuf;

	return (nRet == 0);
}

void CLocalView::DeleteFile()
{
	IPTxShListItems* pitems = (IPTxShListItems*)m_list.get_Items();

	long nCount;
	pitems->get_Count(&nCount);

	BeginWaitCursor();

	VARIANT_BOOL bSelected;

	IPTxShListItem* pitem;
	for (int i = 0; i < nCount; i++) {
		pitems->get_Item(i, &pitem);

		pitem->get_Selected(&bSelected);
		if (!bSelected)
			continue;

		BSTR bstrPath;
		pitem->get_PathName(&bstrPath);
		CString sPath(bstrPath);
		::SysFreeString(bstrPath);

		if (sPath == "")
			continue;

		DeleteDirectory(sPath);
	}

	EndWaitCursor();
}
