// ------------------------------------------------------------------------------------------------------------------------
//	Zip Studio 3.0 - Developer Edition
//	VC4Demo sample for Microsoft Visual C++ 4.0
//
//	Copyright Hexanet 1993-1996, All rights reserved
// ------------------------------------------------------------------------------------------------------------------------
//	Note:
//	To run VC4Demo.EXE you need ZS30W32.OCX and the Microsoft
//	DLLs: MSVCRT40.DLL, MFC40.DLL and OLEPRO32.DLL. (The
//	DLLs must be on the same directory or in WINDOWS/SYSTEM)
// ------------------------------------------------------------------------------------------------------------------------
#include "stdafx.h"
#include "VC4Demo.h"
#include "MainFrm.h"
#include "ZDoc.h"
#include "ZView.h"

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


// The ZIP or UNZIP dialog box handle we will use to redirect ZN.. messages

HWND gHwndInProcess;	// Either the Zip or UnZip box that will receieve the notification messages
											// from CZView.

#define PM_REDIRECT_ZNZIPPING2			(WM_USER + 1)
#define PM_REDIRECT_ZNEXPANDING			(WM_USER + 2)

// ----------------------------------------------------
//	AfxGiveTheHand = DoEvents
//	under VB4
// ----------------------------------------------------
void AfxGiveTheHand( )
	{
	MSG msg;
	while ( PeekMessage( &msg, 0, 0, 0, PM_REMOVE) )
		{
		TranslateMessage( &msg );
		DispatchMessage( &msg );
		}
	}

/////////////////////////////////////////////////////////////////////////////
// CZView

IMPLEMENT_DYNCREATE(CZView, CFormView)

BEGIN_MESSAGE_MAP(CZView, CFormView)
	//{{AFX_MSG_MAP(CZView)
	ON_WM_SIZE()
	ON_WM_DESTROY()
	ON_NOTIFY(LVN_GETDISPINFO, IDC_MYLIST, OnGetdispinfoMylist)
	ON_NOTIFY(LVN_COLUMNCLICK, IDC_MYLIST, OnColumnclickMylist)
	ON_NOTIFY(NM_DBLCLK, IDC_MYLIST, OnDblclkMylist)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CZView construction/destruction

CZView::CZView()
	: CFormView(CZView::IDD)
{
	//{{AFX_DATA_INIT(CZView)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	// TODO: add construction code here

}

CZView::~CZView()
{
}

void CZView::DoDataExchange(CDataExchange* pDX)
{
	CFormView::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CZView)
	DDX_Control(pDX, IDC_ZSCTRL1, m_zsctrl);
	//}}AFX_DATA_MAP
}

BOOL CZView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CFormView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CZView diagnostics

#ifdef _DEBUG
void CZView::AssertValid() const
{
	CFormView::AssertValid();
}

void CZView::Dump(CDumpContext& dc) const
{
	CFormView::Dump(dc);
}

CZDoc* CZView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CZDoc)));
	return (CZDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CZView message handlers
BOOL bLoaded = FALSE;


// Set the ListView attributes
void CZView::OnInitialUpdate() 
	{
	CFormView::OnInitialUpdate();
	UpdateData( FALSE );
	// 1 - Set the images list ---------
	if ( !bLoaded )
		{
		//	We must call <Initialize> before the others OCX method.
		//	Set <SerialNumer> to 0, and the other parameters to blank strings
		//  to evaluate the toolkit, or give your personal passwords here.
		m_zsctrl.Initialize( 0L, _T(""), _T("") );


		AfxGetApp()->BeginWaitCursor();
		
		//	Call this function to build the Zip Studio HIMAGELIST handles.
		//	You must not call this function twice. Once the program terminate
		//	we use <DestroyZIPITEMImageList> (see <OnDestroy> below)
		m_zsctrl.BuildZIPITEMImageList();
		AfxGetApp()->EndWaitCursor();
		bLoaded = TRUE;
		}
	
	//	Now we must set the ImageList for our ListView control.
	//	Our ListView control will automatically use these icons list and we won' t
	//	to paint anything by ourselves
	//	There are 2 ImageList: The first one for big icons ( <GetZIPITEMHImageList>( TRUE ) )
	//	and the next one for the small icons ( <GetZIPITEMHImageList>( FALSE ) )
	

	((CListCtrl*)GetDlgItem(IDC_MYLIST))->SetImageList( CImageList::FromHandle( (HIMAGELIST)(m_zsctrl.GetZIPITEMHImageList( TRUE ))), LVSIL_NORMAL );
	((CListCtrl*)GetDlgItem(IDC_MYLIST))->SetImageList( CImageList::FromHandle( (HIMAGELIST)m_zsctrl.GetZIPITEMHImageList( FALSE )), LVSIL_SMALL );
	
	
	// 2 - Add columns for the REPORT mode -----------
	LV_COLUMN lvc; 
    
	// Initialize the LV_COLUMN structure. 
    lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; 
    
	lvc.fmt = LVCFMT_LEFT; 
    lvc.cx = 200; 
    lvc.pszText = _T("File"); 
 	lvc.iSubItem = 0; 
   if ((int)((CListCtrl*)GetDlgItem(IDC_MYLIST))->SendMessage( LVM_INSERTCOLUMN, (WPARAM)(int)(0), (LPARAM)(const LV_COLUMN FAR*)(&lvc)) == -1 )
        return; 
   
	lvc.fmt = LVCFMT_RIGHT; 
    lvc.cx = 100; 
    lvc.pszText = _T("Size"); 
 	lvc.iSubItem = 1; 
   if ((int)((CListCtrl*)GetDlgItem(IDC_MYLIST))->SendMessage( LVM_INSERTCOLUMN, (WPARAM)(int)(1), (LPARAM)(const LV_COLUMN FAR*)(&lvc)) == -1 )
        return; 
   
	lvc.fmt = LVCFMT_LEFT; 
    lvc.cx = 150; 
    lvc.pszText = _T("Directory"); 
 	lvc.iSubItem = 2; 
    if ((int)((CListCtrl*)GetDlgItem(IDC_MYLIST))->SendMessage( LVM_INSERTCOLUMN, (WPARAM)(int)(2), (LPARAM)(const LV_COLUMN FAR*)(&lvc)) == -1 )
	     return; 
   	
	((CListCtrl*)GetDlgItem(IDC_MYLIST))->SetBkColor( ::GetSysColor( COLOR_WINDOW) );
	((CListCtrl*)GetDlgItem(IDC_MYLIST))->SetTextBkColor( ::GetSysColor( COLOR_WINDOW) );

}


// Resize the main ListView control according to the main window
void CZView::OnSize(UINT nType, int cx, int cy) 
{
	CFormView::OnSize(nType, cx, cy);
	if ( GetDlgItem( IDC_MYLIST) )
		{
		CRect r;
		GetClientRect( r );
  		HDWP h = ::BeginDeferWindowPos(2);
  		GetDlgItem( IDC_MYLIST )->MoveWindow(  r.left, r.top, r.right-r.left, r.bottom-r.top, TRUE );
		::EndDeferWindowPos(h);
		}
}

// We receive this message when we close the program.
//	We must delete the ListView items (and free the corresponding memory)
//	and delete the Zip Studio ImageLists.
void CZView::OnDestroy() 
{
//	This function will destroy all the items we have in the current ListView.
//	The items are ZIPITEMs and we stored them as the LPARAM values of our List.
m_zsctrl.DestroyZIPITEMLParam( (short)GetDlgItem(IDC_MYLIST)->m_hWnd);
//	Remove the HLISTIMAGEs of Zip Studio OCX
m_zsctrl.DestroyZIPITEMImageList(  );
// Remove temp. directories (for <View> and <BuildZIPITEMList>)
m_zsctrl.DeleteTempDirectories();

CFormView::OnDestroy();
}


//	We will receive this message each time the ListView control needs to repaint
//	an item.
//	As we use Visual C++ we can directly access the ZIPITEM value of the item by
//	casting the LPARAM value of the ListView (ZIPITEM* z = (ZIPITEM*)lParam )
//	Otherwise we have to call the Zip Studio <GetZIPITEM...> method to
//	retrieve this value.
//	We put the value to 'pDispInfo->item.pszText' as described in the SDK doc.
//	'pDispInfo->item.iSubItem' corresponds to the column index we are updating
//
void CZView::OnGetdispinfoMylist(NMHDR* pNMHDR, LRESULT* pResult) 
{
	LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
	CString sTemp(' ', 128);

	// TODO: Add your control notification handler code here
   if (pDispInfo->item.mask & LVIF_TEXT) 
		{ 
        if ( pDispInfo->item.lParam )
			{
		ZIPITEM *pItem = (ZIPITEM *) (pDispInfo->item.lParam); 
        if ( pDispInfo->item.iSubItem == 0 )
			{
			if ( pItem->bIsDir ) 
				lstrcpy(pDispInfo->item.pszText, pItem->szDir );
			else
				lstrcpy(pDispInfo->item.pszText, m_zsctrl.GetZIPITEMName( (long)(GetDlgItem(IDC_MYLIST)->m_hWnd), pDispInfo->item.iItem, TRUE ) );// /*pItem->szName*/ );
			pDispInfo->item.mask = pDispInfo->item.mask | LVIF_DI_SETITEM;
			}
		else if ( pDispInfo->item.iSubItem == 1  )
			{
			if ( !(pItem->bIsDir) )
				{
				sTemp.Format( _T("%ld"), (long)( m_zsctrl.GetZIPITEMOriginalSize( (short)(GetDlgItem(IDC_MYLIST)->m_hWnd), pDispInfo->item.iItem, TRUE ) ) ); //  ( pItem->lOriginalSize) );
				lstrcpy(pDispInfo->item.pszText, (LPCTSTR)sTemp );
				}
			}
		else if (  pDispInfo->item.iSubItem == 2 ) 
			{
			if ( !(pItem->bIsDir) )
				lstrcpy(pDispInfo->item.pszText, pItem->szDir );
			}
		if ( pDispInfo->item.pszText )
			{
			OemToChar( pDispInfo->item.pszText, pDispInfo->item.pszText);
			CharLower( pDispInfo->item.pszText );
			}
			}
		} 

	
	*pResult = 0;
}

// ListViewCompareFunc - sorts the list view control. It is a 
//     comparison function. 
// Returns a negative value if the first item should precede the 
//     second item, a positive value if the first item should 
//     follow the second item, and zero if the items are equivalent. 
// lParam1 and lParam2 - item data for the two items (in this 
//     case, pointers to application-defined MYITEM structures) 
// lParamSort - value specified by the LVM_SORTITEMS message 
//     (in this case, the index of the column to sort) 
int CALLBACK ListViewCompareFunc(  LPARAM lParam1, LPARAM lParam2,  LPARAM lParamSort) 
	{ 
    ZIPITEM *pItem1 = (ZIPITEM *) lParam1; 
    ZIPITEM *pItem2 = (ZIPITEM *) lParam2; 
 	int iResult;
	CString sItem1, sItem2;
	
	switch ( (int)lParamSort )	// The column
		{
		case 0: iResult = lstrcmp( (pItem1->szName != _T("")) ? pItem1->szName : pItem1->szDir,
												  (pItem2->szName != _T("")) ? pItem2->szName : pItem2->szDir ); break;
		case 1: if ( pItem1->lOriginalSize < pItem2->lOriginalSize )
						iResult =  -1;
					else if ( pItem1->lOriginalSize > pItem2->lOriginalSize )
						iResult =  1;
					else
						iResult = 0;
					break;
		default: sItem1 = ( strcmp( pItem1->szDir, _T("")) )? pItem1->szDir : _T(":");
					 sItem1 = sItem1 + pItem1->szName;
					 sItem2 = ( strcmp( pItem2->szDir, _T("")) )? pItem2->szDir : _T(":");
					 sItem2 = sItem2 + pItem2->szName;
					 iResult = lstrcmp( sItem1, sItem2 ); break;
		}
	return iResult;
} 


void CZView::OnColumnclickMylist(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
	// TODO: Add your control notification handler code here
	((CListCtrl*)GetDlgItem( IDC_MYLIST ))->SortItems( ListViewCompareFunc, (LPARAM) (pNMListView->iSubItem) ); 
	
	*pResult = 0;
}

void CZView::OnDblclkMylist(NMHDR* pNMHDR, LRESULT* pResult) 
{
	MessageBox( "Not implemented!");
	
	*pResult = 0;
}

//	Zip Studio OCX notification messages -------------
//	We send them back to the corresponding Dialog box

BEGIN_EVENTSINK_MAP(CZView, CFormView)
    //{{AFX_EVENTSINK_MAP(CZView)
	ON_EVENT(CZView, IDC_ZSCTRL1, 2 /* ZNExpanding */, OnZNExpandingZsctrl1, VTS_BSTR VTS_I2)
	ON_EVENT(CZView, IDC_ZSCTRL1, 16 /* ZNZipping2 */, OnZNZipping2Zsctrl1, VTS_BSTR VTS_I2)
	//}}AFX_EVENTSINK_MAP
END_EVENTSINK_MAP()




void CZView::OnZNExpandingZsctrl1(LPCTSTR szName, short iRateDone) 
{
if ( ( gHwndInProcess ) && ( ::IsWindowVisible(gHwndInProcess) ) )
	{
	::SendMessage( gHwndInProcess, PM_REDIRECT_ZNEXPANDING, (WPARAM)iRateDone, (LPARAM)szName );
	AfxGiveTheHand();
	}
}

void CZView::OnZNZipping2Zsctrl1(LPCTSTR szCurrentFile, short iRateDone) 
{
if ( ( gHwndInProcess ) && ( ::IsWindowVisible(gHwndInProcess) ) )
	{
	::SendMessage( gHwndInProcess, PM_REDIRECT_ZNZIPPING2, (WPARAM)iRateDone, (LPARAM)szCurrentFile );
	AfxGiveTheHand();
	}
	
}
