// DIRTREE.CPP Directory Dialog Box...

#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <direct.h>
#include "resrc1.h"

#define CX_BITMAP 16
#define CY_BITMAP 16
#define NUM_BITMAPS 3

int first=1;

BOOL CALLBACK DirTreeDlgProc (HWND hDlg,UINT iMsg,WPARAM wParam,LPARAM lParam);
BOOL CALLBACK NewDirDlgProc (HWND hDlg,UINT iMsg,WPARAM wParam,LPARAM lParam);

char * getvar(char*name);

static int g_nClosed,g_nOpen,g_nDrive;
static char retpath [MAX_PATH]; 


void SetText(HWND h,int id,char *format, ...);
extern HINSTANCE Instance;
// InitTreeViewImageLists - creates an image list, adds three bitmaps //     to it, and associates the image list with a tree-view control. 
// Returns TRUE if successful or FALSE otherwise. 
// hwndTV - handle of the tree-view control //
// Global variables and constants 
//     g_nOpen, g_nClosed, and g_nDocument - integer variables for 
//         indexes of the images 
//     CX_BITMAP and CY_BITMAP - width and height of an icon 
//     NUM_BITMAPS - number of bitmaps to add to the image list 
BOOL InitTreeViewImageLists(HWND hwndTV) 
{ 
    HIMAGELIST himl;  // handle of image list 
    HBITMAP hbmp;     // handle of bitmap      
    
    // Create the image list. 
    if ((himl = ImageList_Create(CX_BITMAP, CY_BITMAP, 
            ILC_COLOR8, NUM_BITMAPS, 0)) == NULL)         
            return FALSE;  
    
    // Add the open file, closed file, and document bitmaps. 
    hbmp = LoadBitmap(Instance, MAKEINTRESOURCE(IDB_OPENED)); 
    g_nOpen = ImageList_Add(himl, hbmp, (HBITMAP) NULL); 
    DeleteObject(hbmp);  
    hbmp = LoadBitmap(Instance, MAKEINTRESOURCE(IDB_CLOSED)); 
    g_nClosed = ImageList_Add(himl, hbmp, (HBITMAP) NULL); 
    DeleteObject(hbmp);  
    
    hbmp = LoadBitmap(Instance, MAKEINTRESOURCE(IDB_DRIVE)); 
    g_nDrive = ImageList_Add(himl, hbmp, (HBITMAP) NULL); 
    DeleteObject(hbmp);      // Fail if not all of the images were added. 
    
    if (ImageList_GetImageCount(himl) < 3)         
      return FALSE;

    TreeView_SetImageList(hwndTV, himl, TVSIL_NORMAL);      
    return TRUE; 
} 
 
// AddItemToTree - adds items to a tree-view control. 
// Returns the handle of the newly added item. 
// hwndTV - handle of the tree-view control 
// lpszItem - text of the item to add 
// nLevel - level at which to add the item 
HTREEITEM AddItemToTree(HWND hwndTV, LPSTR lpszItem,HTREEITEM father) 
{ 
  TV_ITEM tvi;     
  TV_INSERTSTRUCT tvins; 
  HTREEITEM hPrev; 

  tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;

  // Set the text of the item.
  tvi.pszText = lpszItem;
  tvi.cchTextMax = lstrlen(lpszItem);
  // Assume the item is not a parent item, so give it a
  // document image.
  if (!father)
  {
    tvi.iImage = g_nDrive;
    tvi.iSelectedImage = g_nDrive;
  }
  else
  {
    tvi.iImage = g_nClosed;
    tvi.iSelectedImage = g_nOpen;
  }
  // Save the heading level in the item's application-defined
  // data area.
//  tvi.lParam = (LPARAM) nLevel;
  tvins.item = tvi;
  tvins.hInsertAfter = father;
  // Set the parent item based on the specified level.     
  if (!father) 
    tvins.hParent = TVI_ROOT;     
  else  
    tvins.hParent = father;     
  // Add the item to the tree-view control. 
  hPrev = (HTREEITEM) SendMessage(hwndTV, TVM_INSERTITEM, 0,(LPARAM)(LPTV_INSERTSTRUCT) &tvins);  
  // Save the handle of the item.     
  return hPrev; 
} 

int DirTreeDialog (HWND parent,char * path)
{
  char * res;
  first=1;
  res=(char*)DialogBox(Instance,"GETDIRDEST",parent,(DLGPROC)DirTreeDlgProc);
  if (res<0)
    MessageBox(parent,"Could not create DirTree Dialog box","ERROR",NULL);
  else if (!res) 
    return 0;
  else
    strcpy(path,res);
  return 0;
}

char NewDirPath[MAX_PATH];
int NewDirDialog (HWND parent,char * path,HWND hTree,HTREEITEM father)
{
  char t[MAX_PATH];
  if (DialogBox(Instance,"NEWDIR",parent,(DLGPROC)NewDirDlgProc)<0)
    MessageBox(parent,"Could not create NewDir Dialog box","ERROR",NULL);
  strcpy(t,path);
  strcat(t,"\\");
  strcat(t,NewDirPath);
  TreeView_SelectItem(hTree,AddItemToTree(hTree,NewDirPath,father));
  TreeView_SortChildren(hTree,father,0);
  _mkdir(t);
  return 0;
}

int FillDirBox(HWND hDlg,HTREEITEM father,char *path)
{
	int res;
	long h;
	struct _finddata_t fileinfo;
	char buf[MAX_PATH];
  char * name;
  name="*.*";
  sprintf(buf,"%s\\*.*",path);
	h=_findfirst(buf,&fileinfo );
	res=h;
	while(res!=-1)
	{
		sprintf(buf,"%s\\%s",path,fileinfo.name);
		if (fileinfo.attrib&16 && strcmp(fileinfo.name,".") && strcmp(fileinfo.name,".."))
		{
      AddItemToTree(hDlg,fileinfo.name,father);
    }
		res=_findnext(h,&fileinfo );
	}
	if (h!=-1) _findclose(h);
  TreeView_SortChildren(hDlg,father,0);
  return 0;
}

int FillDriveBox(HWND hDlg)
{
	int res,n=0;
  char name[3];
  HTREEITEM h;

  strcpy(name,"a:");
//  *name='a';
	res=GetLogicalDrives();
	while(res)
	{
    n=GetDriveType(name);
		if (res&1 &&
        n!=DRIVE_UNKNOWN &&
        n!=DRIVE_REMOVABLE &&
        n!=DRIVE_CDROM &&
        n!=DRIVE_RAMDISK
        )
		{
      h=AddItemToTree(hDlg,name,NULL);
      FillDirBox(hDlg,h,name);
    }
    name[0]++;
		res>>=1;
	}
  return 0;
}

void TVPath(char * buf,HWND hDlg,HTREEITEM item)
{
  char buffer[MAX_PATH];
  HTREEITEM parent=TreeView_GetParent(hDlg,item);
  TV_ITEM tvitem;

  tvitem.hItem=item;
  tvitem.pszText=buffer;
  tvitem.cchTextMax=MAX_PATH;
  tvitem.mask=TVIF_TEXT;
  TreeView_GetItem(hDlg,&tvitem);
  if (!parent)
  {
    strcpy(buf,tvitem.pszText);
  }
  else
  {
    TVPath(buf,hDlg,parent);
    strcat(buf,"\\");
    strcat(buf,buffer);
  }
}

void TVEmptyItem (HWND hDlg,HTREEITEM item)
{
  HTREEITEM child=TreeView_GetChild(hDlg,item);
  while (child)
  {
    TreeView_DeleteItem(hDlg,child);
    child=TreeView_GetChild(hDlg,item);
  }
}

BOOL CALLBACK DirTreeDlgProc (HWND hDlg,UINT iMsg,WPARAM wParam,LPARAM lParam)
{
  HTREEITEM h=NULL;
  switch (iMsg)
  {
  case WM_INITDIALOG:
    if (InitTreeViewImageLists(GetDlgItem(hDlg,IDC_TREE))==FALSE) MessageBox(NULL,"Pas Bon","InitTreeViewImageLists",NULL);
    SetText(hDlg,IDC_CURDIR,getvar("NEWDIR_TTL"));
    SetWindowText(hDlg,getvar("NEWDIR_TTL"));
    SetText(hDlg,IDC_NEWDIR,getvar("NEWDIR_BTN"));
    FillDriveBox(GetDlgItem(hDlg,IDC_TREE));
    return TRUE;
  case WM_COMMAND:
    switch (LOWORD(wParam))
    {
    case IDOK:
      h=TreeView_GetSelection(GetDlgItem(hDlg,IDC_TREE));
      if (h)
      {
        TVPath(retpath,GetDlgItem(hDlg,IDC_TREE),h);
        EndDialog(hDlg,(int)retpath);
      }
      else
      {
        EndDialog(hDlg,0);
      }
      return TRUE;
    case IDCANCEL:
      EndDialog(hDlg,NULL);
      return TRUE;
    case IDC_NEWDIR:
      char buf [MAX_PATH];
      TVPath(buf,GetDlgItem(hDlg,IDC_TREE),TreeView_GetSelection(GetDlgItem(hDlg,IDC_TREE)));
      NewDirDialog (hDlg,buf,GetDlgItem(hDlg,IDC_TREE),TreeView_GetSelection(GetDlgItem(hDlg,IDC_TREE)));
      return TRUE;
    }
  case WM_NOTIFY:
    if (wParam==IDC_TREE)
    {
      NM_TREEVIEW FAR * treeview=(NM_TREEVIEW FAR *)lParam;
      switch (treeview->hdr.code)
      {
      case TVN_ITEMEXPANDING:
      case TVN_SELCHANGED:
        HTREEITEM child=TreeView_GetChild(GetDlgItem(hDlg,IDC_TREE),treeview->itemNew.hItem);
        char buf [MAX_PATH];
        TVPath(buf,GetDlgItem(hDlg,IDC_TREE),treeview->itemNew.hItem);
        SetText(hDlg,IDC_CURDIR,"%s\\",buf);
        if (strlen(buf)<4)
          EnableWindow(GetDlgItem(hDlg,IDOK),FALSE);
        else
          EnableWindow(GetDlgItem(hDlg,IDOK),TRUE);
        while (child)
        {
          TVEmptyItem (GetDlgItem(hDlg,IDC_TREE),child);
          TVPath(buf,GetDlgItem(hDlg,IDC_TREE),child);
          FillDirBox(GetDlgItem(hDlg,IDC_TREE),child,buf);
          child=TreeView_GetNextSibling(GetDlgItem(hDlg,IDC_TREE),child);
        }
        return TRUE;
        break;
      }
    }
  }
  return FALSE;
}

BOOL checkpath(const char * p)
{
  if (!*p) return FALSE;
  while (*p)
  {
     switch (*p)
     {
     case '\\':
     case '/':
     case '*':
     case '?':
     case ':': 
     case '<':
     case '>':
     case '|':
     case '\"':
       return FALSE;
     }
     p++;
  }
  return TRUE;
}

BOOL CALLBACK NewDirDlgProc (HWND hDlg,UINT iMsg,WPARAM wParam,LPARAM lParam)
{
  switch (iMsg)
  {
  case WM_INITDIALOG:
    SetText(hDlg,IDC_DIRNAME,getvar("NEWDIR_BTN"));
    PostMessage(GetDlgItem(hDlg,IDC_DIRNAME),EM_SETSEL,0,-1);
  case WM_SETFOCUS:
    SetFocus(GetDlgItem(hDlg,IDC_DIRNAME));
    return TRUE;
  case WM_COMMAND:
    switch (LOWORD(wParam))
    {
    case IDOK:
      GetDlgItemText(hDlg,IDC_DIRNAME,NewDirPath,MAX_PATH);
      if (checkpath(NewDirPath)) EndDialog(hDlg,0);
      return TRUE;
    case IDC_DIRNAME:
      return TRUE;
    }
  }
  return FALSE;
}
