/************************************************
   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 "TreeView.h"
#include "lptvid.h"

HWND	CreateTreeView (HINSTANCE appInstance, HWND	hParent, HWND hSplitter)
{
    // Create the View windows
    DWORD dwStyle;

	dwStyle =   WS_TABSTOP | 
		        WS_CHILD | 
				WS_BORDER | 
				TVS_HASLINES | 
				TVS_LINESATROOT | 
				TVS_HASBUTTONS | 
				WS_VISIBLE;
  
	hWndTreeView = CreateWindowEx (
	                               WS_EX_CLIENTEDGE,		// Extended window style
	                               WC_TREEVIEW,			// Window class name
	                               "",		// Window name
	                               dwStyle, // Window style
	                               0, 0, 0, 0,			// Position & size
	                               hParent,			// Parent window handle
	                               (HMENU)ID_TREEVIEW,			// Menu handle
	                               NULL, //appInstance,		// Application instance
	                               0);				// Parameter

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

	CCsplitter_SetHandle (hSplitter, 0, hWndTreeView);

	return hWndTreeView;
}

void InitTreeView()
{
LPSHELLFOLDER lpsf = NULL;
HRESULT hr;
HTREEITEM hParent = NULL;

	hr = SHGetDesktopFolder (&lpsf);
	if (SUCCEEDED (hr))
	{
		hParent = InsertDesktopItem(lpsf);
		lpsf->lpVtbl->Release (lpsf);
	}
}

HTREEITEM InsertDesktopItem(LPSHELLFOLDER lpsf)
{
LPITEMIDLIST lpi = NULL;
HTREEITEM hParent = NULL;
char szBuff [MAX_PATH];
TVINSERTSTRUCT tvins;

	SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &lpi);
    InsertTreeItem(TRUE, &tvins, szBuff, NULL, NULL , lpsf , NULL, lpi , TRUE);
	hParent = TreeView_InsertItem(hWndTreeView, &tvins);
	TreeView_Expand(hWndTreeView, hParent, TVE_EXPAND);

	return hParent;
}

void    PopulateTree(TV_ITEM tvi)
{
LPTVITEMDATA* lptvid = NULL;
HTREEITEM hItem = NULL;
HTREEITEM hPrev;
HRESULT hr;
LPENUMIDLIST lpe = NULL;	
ULONG celtFetched;
LPITEMIDLIST pidlItems = NULL;
LPENUMIDLIST ppenum = NULL;
IShellFolder *psfProgFiles = NULL;
LPMALLOC pMalloc;

    hr = SHGetMalloc(&pMalloc);

	if(FAILED(hr))
		return;

    lptvid = (LPTVITEMDATA*) pMalloc->lpVtbl->Alloc (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(hWndTreeView, WM_SETREDRAW, FALSE, 0L);
	DeleteTreeChildren(tvi.hItem);

	while( hr = ppenum->lpVtbl->Next(ppenum, 1,&pidlItems, &celtFetched) == S_OK && (celtFetched) == 1)
    {

		char szBuff[MAX_PATH];
		TVINSERTSTRUCT tvins;
		ULONG uAttr = SFGAO_FOLDER | SFGAO_GHOSTED;
		psfProgFiles->lpVtbl->GetAttributesOf(psfProgFiles, 1, (LPCITEMIDLIST *) &pidlItems, &uAttr);
		if(uAttr & SFGAO_FOLDER ) 
		{
			InsertTreeItem(FALSE, &tvins, szBuff, tvi.hItem, NULL , psfProgFiles , lptvid->lpifq, pidlItems , TRUE);
			hPrev = TreeView_InsertItem(hWndTreeView, &tvins);
		}

	}

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

}


UINT DeleteTreeChildren(HTREEITEM hItem)
{

UINT nCount = 0;
HTREEITEM hChild = TreeView_GetChild(hWndTreeView, hItem);

    while (hChild != NULL) 
	{
        HTREEITEM hNextItem = TreeView_GetNextSibling(hWndTreeView, hChild);
        TreeView_DeleteItem (hWndTreeView, hChild);
        hChild = hNextItem;
        nCount++;

    }
    return nCount;

}

HTREEITEM InsertTreeItem(BOOL bRoot,
					   TVINSERTSTRUCT* tvins, 
					   char szBuff[MAX_PATH],
					   HTREEITEM hParent,
					   HTREEITEM hPrev, 
					   LPSHELLFOLDER lpsf,
					   LPITEMIDLIST lpifq,
					   LPITEMIDLIST lpi,
					   BOOL bChildValid)
{

TV_ITEM tvi; // tree view item
LPENUMIDLIST lpe = NULL;
LPITEMIDLIST lpiTemp = NULL, lpifqThisItem = NULL;
UINT uCount = 0;
HRESULT hr;
ULONG ulAttrs;
LPTVITEMDATA* lptvid;
LPMALLOC pMalloc;

	CoInitialize( NULL );
	hr = SHGetMalloc(&pMalloc);

	if(FAILED(hr))
		return NULL;

	ulAttrs = SFGAO_HASSUBFOLDER | SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_GHOSTED | SFGAO_LINK | SFGAO_SHARE;

	// Determine what type of object you have.
/*
	if(!(lpi) || (lpi->mkid.cb >= 82))
			return NULL;
*/
	lpsf->lpVtbl->GetAttributesOf(lpsf,	1, (const struct _ITEMIDLIST **)&lpi, &ulAttrs);

	tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;

	if (ulAttrs & SFGAO_HASSUBFOLDER)
	{
		// This item has subfolders, so put a plus sign in the 
		// tree view control. The first time the user clicks 
		// the item, you should populate the subfolders.
		if(bChildValid)
		{
			tvi.cChildren = 1;
			tvi.mask |= TVIF_CHILDREN;
		}
	}
	if (ulAttrs & SFGAO_GHOSTED)
	{
		tvi.mask |= LVIF_STATE;
		tvi.stateMask = LVIS_CUT;
		tvi.state = LVIS_CUT;
	}
	if (ulAttrs & SFGAO_LINK)
	{
		tvi.mask |= LVIF_STATE;
		tvi.stateMask = LVIS_OVERLAYMASK;
		tvi.state = INDEXTOOVERLAYMASK(2);
	}
	if (ulAttrs & SFGAO_SHARE)
	{
		tvi.mask |= LVIF_STATE;
		tvi.stateMask = LVIS_OVERLAYMASK;
		tvi.state = INDEXTOOVERLAYMASK(1);
	}


	// Get some memory for the ITEMDATA structure.
	lptvid = NULL;
	lptvid = (LPTVITEMDATA*) pMalloc->lpVtbl->Alloc (pMalloc, sizeof (LPTVITEMDATA));
	if (! lptvid)
	{
		goto Done; // Error - could not allocate memory
		return NULL;
	}

	// Now get the friendly name to 
	// put in the tree view control.
	if (! GetName (lpsf, lpi, SHGDN_NORMAL, szBuff))
	{
//				goto Done; // Error - could not get friendly name
	}

	tvi.pszText = szBuff;
	tvi.cchTextMax = MAX_PATH;

	// Now make a copy of the ITEMIDLIST.
	lptvid->lpi = CopyItemID (pMalloc, lpi);

	lptvid->lpsfParent = lpsf; // pointer to parent folder
	lpsf->lpVtbl->AddRef(lpsf);

    lptvid->bRoot = bRoot;
	lptvid->lpifq =  Concatenate(pMalloc, lpifq, lpi);
	GetNormalAndSelectedIcons (lptvid->lpifq, &tvi);
	tvi.lParam = (LPARAM)lptvid;

	// Populate the tree view insert structure.
	// The item is the one filled above.
	// Insert it after the last item inserted at this level,
	// and indicate that this is a root entry.
	tvins->item = tvi;
	tvins->hInsertAfter = hPrev;
	tvins->hParent = hParent; //NULL; //hParent;

	// Add the item to the tree.
//	hPrev = mTree->InsertItem (&tvins);
	
Done:
	pMalloc->lpVtbl->Release(pMalloc);      	
//	lpsf->Release();
    CoUninitialize();
	return hPrev;
}


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

