/************************************************
   THIS CODE AND INFORMATION IS PROVIDED 'AS IS' 
   WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO
   THE IMPLIED WARRANTIES OF MERCHANTABILITY 
   AND/OR FITNESS FOR A PARTICULAR PURPOSE.
   Author: Barretto VN  7/2002
*************************************************/


#include "Windows.h"
#include <commctrl.h>
#include "Resource.h"
#include "CCSplitter.h"
#include "ListView.h"
#include "lptvid.h"

int  giRowCtr = 0;

HWND	CreateListView (HINSTANCE appInstance, 
						HWND	hParent, 
						HWND hSplitter)		// Parent window handle
{
    DWORD dwStyle;

	dwStyle =   WS_TABSTOP | 
		        WS_CHILD | 
				WS_BORDER | 
				LVS_AUTOARRANGE | 
				LVS_REPORT | 
				LVS_EDITLABELS | 
				LVS_SHAREIMAGELISTS | 
				WS_VISIBLE;

	hWndListView = CreateWindowEx (
	                               WS_EX_CLIENTEDGE,		// Extended window style
	                               WC_LISTVIEW,			// Window class name
	                               "",		// Window name
	                               dwStyle, // Window style
	                               0, 0, 0, 0,			// Position & size
	                               hParent,			// Parent window handle
	                               (HMENU)ID_LISTVIEW,			// Menu handle
	                               appInstance,		// Application instance
	                               0);				// Parameter

	if (hWndListView == NULL) 
	{
	    MessageBox (0, "failed to create ListView", NULL, MB_ICONSTOP|MB_OK);
	    return NULL;
	}

	CCsplitter_SetHandle (hSplitter, 1, hWndListView);
	InitListView(hWndListView);

	return hWndListView;
}

BOOL InitListView(HWND hwnd) 
{ 
#define TOTAL_COLS 4
LV_COLUMN   lvColumn; 
int         i; 
TCHAR       szString[TOTAL_COLS][20] = {"Name", "Type", "Size", "Modified"};  
int         szColWidth[TOTAL_COLS] = {120, 80 , 60, 110};
	//empty the list 
	ListView_DeleteAllItems(hwnd);  //initialize the columns 
	lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; 
	lvColumn.fmt = LVCFMT_LEFT; 

	for(i = 0; i < TOTAL_COLS; i++)    
	{    
		lvColumn.pszText = szString[i];    
		lvColumn.cx = szColWidth[i];
		ListView_InsertColumn(hwnd, i, &lvColumn);    
	}  
  
	return TRUE; 
}  

BOOL InsertListViewItem(LPSHELLFOLDER lpsf, 
					    LPITEMIDLIST lpi,
					    LPITEMIDLIST lpifq)
{

char szBuff[MAX_PATH];
LPMALLOC lpMalloc;
LPTVITEMDATA* lptvid = NULL;
LPITEMIDLIST pidl = NULL;	
	
	UINT uFlags;
	LV_ITEM lvi;
	
	lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;

	GetName (lpsf, lpi, SHGDN_NORMAL, szBuff);

	lvi.iItem = giRowCtr++;
	lvi.iSubItem = 0 ; //COL_NAME;
	lvi.pszText =  szBuff; // LPSTR_TEXTCALLBACK;
	lvi.cchTextMax = MAX_PATH;
	uFlags = SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON;

    SHGetMalloc(&lpMalloc);
	lptvid = (LPTVITEMDATA*) lpMalloc->lpVtbl->Alloc (lpMalloc, sizeof (LPTVITEMDATA));
	pidl =  Concatenate(lpMalloc, lpifq,lpi);

	lvi.iImage = GetNormalIcon(pidl);  //I_IMAGECALLBACK;
	lptvid->lpsfParent = lpsf;
	lptvid->lpi = CopyItemID(lpMalloc, lpi);
	lptvid->lpifq = pidl; //csc.CopyItemID(lpMalloc, pidl);
	lvi.lParam = (LPARAM)lptvid;
	ListView_InsertItem (hWndListView, &lvi);
	lpMalloc->lpVtbl->Release(lpMalloc);

	return TRUE;
}

void    PopulateList(TV_ITEM tvi)
{
LPTVITEMDATA* lptvid = NULL;
HTREEITEM hItem = NULL;
HRESULT hr;
LPENUMIDLIST lpe = NULL;	
ULONG celtFetched;
LPITEMIDLIST pidlItems = NULL;
LPENUMIDLIST ppenum = NULL;
IShellFolder *psfProgFiles = NULL;
LPMALLOC m_pMalloc;
WIN32_FIND_DATA fd;

    hr = SHGetMalloc(&m_pMalloc);

	if(FAILED(hr))
		return;

    lptvid = (LPTVITEMDATA*) m_pMalloc->lpVtbl->Alloc (m_pMalloc, sizeof (LPTVITEMDATA));
	if (! lptvid)
	{
		return; // Error - could not allocate memory
	}

	lptvid = (LPTVITEMDATA*)tvi.lParam;
	if(lptvid == NULL)
		return;

	if(lptvid->bRoot)
		psfProgFiles = lptvid->lpsfParent;
	else
	{
		hr = lptvid->lpsfParent->lpVtbl->BindToObject(lptvid->lpsfParent , lptvid->lpi, NULL, &IID_IShellFolder, (LPVOID *) &psfProgFiles);
		if(FAILED(hr))
				return;
	}

    hr = psfProgFiles->lpVtbl->EnumObjects(psfProgFiles, NULL,SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN , &ppenum);
	if(FAILED(hr))
		return;

	SetCursor(LoadCursor(NULL,IDC_WAIT));
	
	SendMessage(hWndListView, WM_SETREDRAW, FALSE, 0L);

	ListView_DeleteAllItems(hWndListView);
	giRowCtr = 0;

	while( hr = ppenum->lpVtbl->Next(ppenum, 1,&pidlItems, &celtFetched) == S_OK && (celtFetched) == 1)
    {int toto;
		char fn[256] = "toto";
		ULONG uAttr = SFGAO_FOLDER;
		psfProgFiles->lpVtbl->GetAttributesOf(psfProgFiles, 1, (LPCITEMIDLIST *) &pidlItems, &uAttr);

	
		SHGetDataFromIDList(psfProgFiles, pidlItems, SHGDFIL_FINDDATA , &fd, sizeof(WIN32_FIND_DATA));

		if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) &&!(uAttr & SFGAO_FOLDER))
				InsertListViewItem(psfProgFiles , pidlItems , lptvid->lpifq);

		//psfProgFiles->lpVtbl->GetDisplayNameOf(psfProgFiles, pidlItems, SHGDN_FORPARSING | SHGDN_INFOLDER, fn);
		//StrRetToStr(LPSTRRET pstr, pidlItems, fn);
		toto = 0;
    }

	m_pMalloc->lpVtbl->Release(m_pMalloc);
	SetCursor(LoadCursor(NULL,IDC_ARROW));
	SendMessage(hWndListView, WM_SETREDRAW, TRUE, 0L);
	InvalidateRect(hWndListView, NULL, TRUE);

}

void onViewStyle(UINT uiStyle, HWND hWndMain)
{
	DWORD dwStyle = GetWindowLong(hWndListView, GWL_STYLE);
	dwStyle &= ~LVS_TYPEMASK;

	CheckMenuItem (GetMenu (hWndMain), IDM_VIEW_LARGEICONS , uiStyle == IDM_VIEW_LARGEICONS ? MF_CHECKED : MF_UNCHECKED);
	CheckMenuItem (GetMenu (hWndMain), IDM_VIEW_SMALLICONS , uiStyle == IDM_VIEW_SMALLICONS ? MF_CHECKED : MF_UNCHECKED);
	CheckMenuItem (GetMenu (hWndMain), IDM_VIEW_LIST       , uiStyle == IDM_VIEW_LIST       ? MF_CHECKED : MF_UNCHECKED);
	CheckMenuItem (GetMenu (hWndMain), IDM_VIEW_DETAIL     , uiStyle == IDM_VIEW_DETAIL    ? MF_CHECKED : MF_UNCHECKED);

	switch (uiStyle)
	{
	case IDM_VIEW_LARGEICONS:
		dwStyle |= LVS_ICON;
		break;
	case IDM_VIEW_SMALLICONS:
		dwStyle |= LVS_SMALLICON;
		break;
	case IDM_VIEW_LIST:
		dwStyle |= LVS_LIST;
		break;
	case IDM_VIEW_DETAIL:
		dwStyle |= LVS_REPORT;
		break;
	default:
		return;
	}
	SetWindowLong(hWndListView, GWL_STYLE, dwStyle);
}


BOOL ShowPopupStyleMenu(HINSTANCE appInstance)
{
static POINT point;
HMENU m_hMenu;
UINT id;
HMENU hMenuTrackPopup;

	GetCursorPos(&point);
	m_hMenu = LoadMenu( appInstance, MAKEINTRESOURCE(IDR_VIEW_POPUP));
	hMenuTrackPopup = GetSubMenu (m_hMenu, 0);
	id = TrackPopupMenu(hMenuTrackPopup, 
	          TPM_LEFTALIGN | TPM_RETURNCMD | TPM_RIGHTBUTTON, 
              point.x, point.y,0,
              hWndListView, NULL);

	onViewStyle(id, hWndListView);
	DestroyMenu(m_hMenu);

	return TRUE;
}

BOOL ShowStdMenu(LVITEM lvi , BOOL bShowMenu, HINSTANCE appInstance)
{
HRESULT hr;
HMENU hMenuPopup;
IContextMenu   *icm;
LPMALLOC m_pMalloc;
LPTVITEMDATA* lptvid = NULL;
UINT  id;
static POINT pt;
CMINVOKECOMMANDINFO  ici;

	if(!lvi.lParam)
	{
		// Click on an empty area of Listview
		ShowPopupStyleMenu(appInstance);		
		return TRUE;
	}

    hr = SHGetMalloc(&m_pMalloc);

	if(FAILED(hr))
		return FALSE;

    lptvid = (LPTVITEMDATA*) m_pMalloc->lpVtbl->Alloc (m_pMalloc, sizeof (LPTVITEMDATA));
	if (! lptvid)
		goto Done;


	lptvid = (LPTVITEMDATA*)lvi.lParam;
	if(lptvid == NULL)
		goto Done;

	hr = lptvid->lpsfParent->lpVtbl->GetUIObjectOf(
		                       lptvid->lpsfParent, 
		                       hWndListView, 
                               1, 
                               (LPCITEMIDLIST*)&lptvid->lpi,
                               &IID_IContextMenu, 
                               NULL, 
                               (LPVOID*)&icm);

    hMenuPopup = CreatePopupMenu();
    if(!hMenuPopup)
		goto Done;

    hr = icm->lpVtbl->QueryContextMenu(icm , hMenuPopup, 0, 1, 0x7fff, CMF_NORMAL | CMF_EXPLORE);
    if(FAILED(hr))
		goto Done;

    GetCursorPos(&pt);

	if(bShowMenu)
		id = TrackPopupMenu(hMenuPopup, 
                  TPM_LEFTALIGN | TPM_RETURNCMD | TPM_RIGHTBUTTON, 
                  pt.x, pt.y,0,
                  hWndListView,NULL);
	else
		// User Double-clicked on menu item, 
		// so we don't show the menu
		// and execute the command

	{
		//id = hr;
		char str[256];
		SHGetPathFromIDList((LPCITEMIDLIST)lptvid->lpi, str);
		MessageBox(NULL, str, "enfin!!!", MB_OK);
		goto Done;
	}
	if(!id)
		goto Done;


    ici.cbSize = sizeof(CMINVOKECOMMANDINFO);
    ici.fMask = 0;
    ici.hwnd = hWndListView;
    ici.lpVerb = (LPCSTR)(INT_PTR)(id - 1);
    ici.lpParameters = NULL;
    ici.lpDirectory = NULL;
    ici.nShow = SW_SHOWNORMAL;
    ici.dwHotKey = 0;
    ici.hIcon = NULL;
    hr = icm->lpVtbl->InvokeCommand(icm , &ici);

Done:
m_pMalloc->lpVtbl->Release(m_pMalloc);
return TRUE;

}

BOOL GetSelectedItem(LPNMHDR lpnmh , LV_ITEM* lvItem)
{
	LPNMLISTVIEW   lpnmlv = (LPNMLISTVIEW)lpnmh;
    lvItem->mask = LVIF_PARAM | LVIF_TEXT;
	lvItem->iItem = lpnmlv->iItem;
	if(ListView_GetItem(hWndListView, lvItem))
		return TRUE;
	else
		return FALSE;
}

void setDisplayInfo(LV_DISPINFO *lpdi)
{
LPMALLOC m_pMalloc;
HRESULT hr;
LPTVITEMDATA* pData = NULL;
char refTime[20];
WIN32_FIND_DATA fd;
SYSTEMTIME st;
STRRET srName;

//	LPITEMIDLIST pidl = (LPITEMIDLIST)lpdi->item.lParam;
	lpdi->item.mask |= LVIF_DI_SETITEM;	// dont ask us again
//	LPMYPIDLDATA pData = m_pPidlMgr->GetDataPointer(pidl);
//	if(!pData)
//		return;

    hr = SHGetMalloc(&m_pMalloc);

	if(FAILED(hr))
		return;

    pData = (LPTVITEMDATA*) m_pMalloc->lpVtbl->Alloc (m_pMalloc, sizeof (LPTVITEMDATA));
	if (! pData)
	{
		return; // Error - could not allocate memory
	}

	pData = (LPTVITEMDATA*)lpdi->item.lParam;
	if(pData == NULL)
		return;

	if(lpdi->item.iSubItem)	// Subitem information being requested
	{
		//is the text being requested?
		if(lpdi->item.mask & LVIF_TEXT)
		{
			switch (lpdi->item.iSubItem)
			{
			case SUBITEM_MODIFIED:
				{
					hr = SHGetDataFromIDList(pData->lpsfParent , pData->lpi, SHGDFIL_FINDDATA , (WIN32_FIND_DATA*)&fd , sizeof(fd));
					if(FAILED(hr))
						break;

					FileTimeToSystemTime( &fd.ftLastWriteTime, &st );
					wsprintf(refTime, "%02u-%02u-%04u" , st.wMonth, st.wDay, st.wYear ); 
					lstrcpy(lpdi->item.pszText, refTime);
				}
				break;
			case SUBITEM_SIZE:
				{
					hr = SHGetDataFromIDList(pData->lpsfParent , pData->lpi, SHGDFIL_FINDDATA , (WIN32_FIND_DATA*)&fd , sizeof(fd));
					if(FAILED(hr))
						break ;

					if(fd.nFileSizeLow)
					{
						char sNumBuff[30];
						if(fd.nFileSizeLow != 0)
							ltoa((long)fd.nFileSizeLow,sNumBuff,10);
						else
							strcpy(sNumBuff,"");
	
						lstrcpy(lpdi->item.pszText, sNumBuff);

					}
				}			
				break;
			case SUBITEM_TYPE:
        		GetTypeOf(pData->lpifq, &srName);
				lstrcpy(lpdi->item.pszText, srName.cStr);
        		break;

			}
		}
	}
	else	// The item information is being requested
	{
		if(lpdi->item.mask & LVIF_TEXT)
		{

			char szBuff[MAX_PATH];
			GetName(pData->lpsfParent, pData->lpi, SHGDN_NORMAL , szBuff);
			lpdi->item.pszText = (LPSTR)szBuff; 
			lpdi->item.cchTextMax = lstrlen(szBuff);
//			lpdi->item.iImage = GetIcon(pData->lpifq, FALSE);
		}
		
		if ((lpdi->item.mask & LVIF_IMAGE) == LVIF_IMAGE)
		{

//			if (m_fsFolderSettings.ViewMode != FVM_ICON)
//				lpdi->item.iImage = GetIcon(pData->lpi, FALSE);
//			else
//				lpdi->item.iImage = GetIcon(pData->lpi, TRUE);
		}
	}

m_pMalloc->lpVtbl->Release(m_pMalloc);

}

void GetTypeOf(LPITEMIDLIST pit, LPSTRRET lpName)
{
SHFILEINFO sfi;

    lpName->uType = STRRET_CSTR;
    lpName->cStr[0] = '\0';
    if (SHGetFileInfo((LPTSTR)pit, 
	                0, 
					&sfi, 
					sizeof(sfi),
    SHGFI_USEFILEATTRIBUTES | SHGFI_TYPENAME | SHGFI_PIDL))
    {
        lstrcpy(lpName->cStr, sfi.szTypeName);
    }
}


/********************************************************************************/
/* End of file									*/
/********************************************************************************/
