#include <windows.h>
#include <commctrl.h>
#include <commdlg.h>
#include <richedit.h>
#include <stdio.h>

#define PROJVERS 1
#include "header.h"
#include <ctype.h>

LRESULT  CALLBACK _export YesNoProc( HWND hwnd, UINT iMessage, WPARAM wParam,
                                 LPARAM lParam ) ;
extern HINSTANCE hInstance ;
extern HWND hwndClient,hwndStatus,hwndFrame ;
extern char szProjectFilter[],szSourceFilter[], szTargetFilter[] ;
extern HWND hwndTab, hwndWatch ;
extern int docking ;

HWND hwndProject ;
PROJLIST *projectList ;
PROJLIST *selectedProject ;

static char szProjectClassName[] = "xccProjectClass" ;
static char szProjectTitle[256] ;
static char szProjectName[256] ;
static HWND treeWindow ;
static HBITMAP flyellow,flred,flgreen,flwhite,flcyan,fldll,fllib,flexe ;
static int ilyellow, ilred,ilgreen,ilwhite,ilcyan,ildll,illib,ilexe ;
static HIMAGELIST treeIml ;
static int treeViewSelected ;

void FindModuleName(char *out, char *in) 
{
   PROJLIST *l = projectList ;
	int i = 0 ;
	while (l) {
		int j = 0;
		FILELIST *m = l->files ;
		while (m) {
         if (!xstricmpz(in,m->name)) {
            strcpy(out,in) ;
            return ;
         }
         if (!xstricmpz(in,m->title)) {
            strcpy(out,m->name) ;
            return ;
         }
			m = m->next ;
		}
		l = l->next ;
	}
}                
int imageof(char *name)
{
	name = strrchr(name,'.') ;
   if (!name)
      return ilyellow ;
	if (!xstricmpz(name,".asm"))
		return ilred ;
	if (!xstricmpz(name,".c") || !xstricmpz(name,".cpp"))
		return ilcyan ;
	if (!xstricmpz(name,".rc"))
		return ilgreen ;
	if (!xstricmpz(name,".h"))
		return ilyellow ;
	if (!xstricmpz(name,".exe"))
		return ilexe ;
	if (!xstricmpz(name,".lib"))
		return illib ;
	if (!xstricmpz(name,".dll"))
		return ildll ;

	return ilwhite ;
}
HTREEITEM TVInitInsert(HWND hTree, HTREEITEM hParent, HTREEITEM after, char * title, int toexpand)
{
	HTREEITEM rv ;
	TV_INSERTSTRUCT t;
	memset(&t,0,sizeof(t)) ;
	t.hParent =hParent ;
	t.hInsertAfter = after ;
	t.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
	t.item.hItem = 0;	
	t.item.pszText = title ;
	t.item.cchTextMax = strlen(title) ;
	t.item.iImage = t.item.iSelectedImage = imageof(title) ;
	rv = TreeView_InsertItem(hTree,&t) ;
	if (toexpand)
		TreeView_Expand(treeWindow,hParent,	TVE_EXPAND) ;
   return rv ;
}
void AddFileInternal(PROJLIST *p, int selected, char *name, char *title)
{
			FILELIST *x =p->files ;
			while (x) {
            if (!xstricmp(x->name,name))
					return ;
				x = x->next ;
			}
			x = malloc(sizeof(FILELIST)) ;
			memset(x,0,sizeof(*x)) ;
			if (x) {
				FILELIST **y = &p->files ;
				int i;
				HTREEITEM item = TVI_FIRST ;
				for (i=0; i < selected; i++) {
					item = (*y)->treeHandle ;
					y = &(*y)->next ;
				}
				x->next = (*y) ;
				
				*y = x ;
            strcpy(x->name,name) ;
            strcpy(x->title,title) ;
				x->treeHandle = TVInitInsert(treeWindow,p->treeHandle,item,x->title,TRUE) ;
			}
}
void ProjectAddFile(PROJLIST *p, int selected)
{
	if (hwndProject) {
		OPENFILENAME ofn ;
      if (OpenFileDialog(&ofn,0,hwndProject,FALSE,TRUE,szSourceFilter,"FILEDIR")) {
         char *q = ofn.lpstrFile ;
         char path[256] ;
         char filename[256],*r ;
         strcpy(path,q) ;
         q = q + strlen(q) + 1 ;
         if (*q) {
            while (*q) {
               sprintf(filename,"%s\\%s",path,q) ;
               AddFileInternal(p,selected,filename,q) ;
               q = q + strlen(q) + 1 ;
            }
         } else {
            r = strrchr(path,'\\') ;
            if (!r)
               r = path ;
            else
               r++ ;
            AddFileInternal(p,selected,path,r) ;
         }
		}
	}
}
void ProjectAddTarget(PROJLIST *p)
{
	if (hwndProject) {
		OPENFILENAME ofn ;
      if (OpenFileDialog(&ofn,0,hwndProject,FALSE,FALSE,szTargetFilter,"FILEDIR")) {

			PROJLIST *x =projectList ;
			while (x) {
				if (!xstricmp(x->name,ofn.lpstrFile))
					return ;
				x = x->next ;
			}
			x = malloc(sizeof(PROJLIST)) ;
			memset(x,0,sizeof(*x)) ;
			if (x) {
            int rootproj = FALSE ;
            if (!strchr(ofn.lpstrFile,'.')) {
               strcat(ofn.lpstrFile,".exe") ;
               strcat(ofn.lpstrFileTitle,".exe") ;
            }
				strcpy(x->name,ofn.lpstrFile) ;
				strcpy(x->title,ofn.lpstrFileTitle) ;
				if (!projectList) {
               rootproj = TRUE ;
					projectList = x ;
					x->treeHandle = TVInitInsert(treeWindow,TVI_ROOT,TVI_FIRST,ofn.lpstrFileTitle,FALSE) ;
				} else {
					if (!p) {
						p = projectList ;
						while (p->next)
							p = p->next ;
					}
					x->treeHandle = TVInitInsert(treeWindow,TVI_ROOT,p->treeHandle,ofn.lpstrFileTitle,FALSE) ;
					p->next = x ;
				}
            if (lstrlen(x->name) > 4)
               if (!xstricmpz(".dll",x->name + lstrlen(x->name) - 4) )
                  x->buildType = BT_DLL ;
               else if (!xstricmpz(".lib",x->name + lstrlen(x->name) - 4) )
                  x->buildType = BT_LIBRARY ;
               else {
                  x->buildType = BT_CONSOLE ;
                  x->buildFlags = BF_BREAKWINMAIN | BF_DEBUGTOOLTIPS    
                        | BF_DEBUGINFO ;
                  if (rootproj)
                     x->buildFlags |= BF_CHOSENPROJECT ;
               }
			}
		}
	}
}
void DeleteDepends(DEPENDSLIST *l)
{
	while (l) {
		DEPENDSLIST *n = l->next ;
		if (l->treeHandle)
			TreeView_DeleteItem(treeWindow,l->treeHandle) ;
		free(l) ;
		l = n ;
	}
}
void DeleteFiles(FILELIST *l)
{
	while (l) {
		FILELIST *n = l->next ;
		DeleteDepends(l->depends) ;
		if (l->treeHandle)
			TreeView_DeleteItem(treeWindow,l->treeHandle) ;
		free(l) ;
		l = n ;
	}
}
void ProjectDeleteFile(PROJLIST *p, int selected)
{
	if (hwndProject) {
		int i ;
		FILELIST **y = &p->files,*x ; 
		if (*y) {
			for (i=1; i < selected; i++)
				y = &(*y)->next ;
			x = *y ;
			*y = (*y)->next ;
			DeleteDepends(x->depends) ;
			TreeView_DeleteItem(treeWindow,x->treeHandle) ;
			free(x) ;
		}
	}
}
void ProjectDeleteTarget(PROJLIST *proj)
{
	if (hwndProject) {
		int i;
		PROJLIST **y = &projectList,*x ; 
		while (*y && *y != proj) 
			y= &(*y)->next ;
		x = *y ;
		*y = (*y)->next ;
		DeleteFiles(x->files) ;
		TreeView_DeleteItem(treeWindow,x->treeHandle) ;
		free(x) ;

	}
}
void ProjectFreeList (void ) 
{
	
	while (projectList) {
		PROJLIST *temp = projectList->next ;
		ProjectDeleteTarget(projectList) ;
		free(projectList) ;
		projectList = temp ;
	}
}
void ProjectNewList(PROJLIST *list)
{
	projectList = list ;
}
PROJLIST * LoadErr(char *name, PROJLIST *list, FILE *in)
{
	projectList = list ;
	ProjectFreeList() ;
	ExtendedMessageBox("Load error",0,"File %s is the wrong format",name) ;
	return 0 ;
}
int ReadString(char *buf, FILE *in, char *compare)
{
	int l ;
	if (feof(in))
		return 1 ;
	fgets(buf,256,in) ;
	l = strlen(buf) ;
	if (buf[l-1] == '\n') 
		buf[--l] = 0 ;
	if (compare)
		return xstricmp(buf,compare) ;
	return 0 ;
}
PROJLIST *ProjectLoadList(char *name, RECT *rect)
{
	PROJLIST *plist=0,**pl=&plist ;
	FILE *in = fopen(name,"r") ;
   RECT wrect ;
	char buf[256] ;
   int temp ;
	if (!in) {
		ExtendedMessageBox("Error",0,"File Not Found") ;
		return 0;
	}
   if (ReadString(buf,in,"<PROJECT "))
		return LoadErr(name,plist,in) ;
	if (ReadString(buf,in,"<TARGETS>"))
		return LoadErr(name,plist,in) ;
	while (TRUE) {
		if (ReadString(buf,in,"<TARGET "))
			break ;
		*pl = malloc(sizeof(*plist)) ;
		if (pl) {
			char *p = buf + 8;
			int i = 0 ;
			FILELIST *list=0,**l=&list,*lastlist = 0 ;
			memset(*pl,0,sizeof(*plist)) ;
			while (*p && *p != ';')
				(*pl)->name[i++] = *p++ ;
			if (*p) 
				p++ ;
			i = 0;
			while (*p && *p != '>')
				(*pl)->title[i++] = *p++ ;	
			if (ReadString(buf,in,"<PATHS"))
            return LoadErr(name,plist,in) ;
			p = buf + 7 ;
			i = 0 ;
			while (*p && *p != ';')
				(*pl)->includePath[i++] = *p++ ;
			if (*p) 
				p++ ;
			i = 0;
			while (*p && *p != '>')
				(*pl)->outputPath[i++] = *p++ ;	
			if (ReadString(buf,in,"<BUILD "))
            return LoadErr(name,plist,in) ;
         sscanf(buf+7,"%d %x",&(*pl)->buildType, &(*pl)->buildFlags) ;
         if (ReadString(buf,in,"<OPTS "))
            return LoadErr(name,plist,in) ;
         sscanf(buf+6,"\"%[^\"]\" \"%[^\"]\" \"%[^\"]\" \"%[^\"]\" ",
            (*pl)->compileopts, (*pl)->assembleopts, (*pl)->linkopts, (*pl)->libopts) ;
         if (ReadString(buf,in,0))
            return LoadErr(name,plist,in) ;
         if (buf[strlen(buf)-1] == '\n')
            buf[strlen(buf)-1] = 0 ;
         strcpy((*pl)->cmdline,buf) ;
			while (TRUE) {
				if (ReadString(buf,in,0))
					return LoadErr(name,plist,in) ;
				if (buf[0] == '<')
					if (!xstricmp(buf,"<DEPENDS>")) {
						DEPENDSLIST *dlist=0,**dl =&dlist ;
						if (!list)
							return LoadErr(name,plist,in) ;
						while (TRUE) {
							if (ReadString(buf,in,0))
								return LoadErr(name,plist,in) ;
							if (buf[0] == '<')
								break ;
							*dl = malloc(sizeof(*dlist)) ;
							if (*dl) {
								char *p = buf ;
								int i = 0 ;
								memset(*dl,0,sizeof(*dlist)) ;
								while (*p && *p != ';')
									(*dl)->name[i++] = *p++ ;
								if (*p) 
									p++ ;
								i = 0;
								while (*p && *p != '>')
									(*dl)->title[i++] = *p++ ;	
								dl = &(*dl)->next ;
							}
						}
						if (xstricmp(buf,"</DEPENDS>"))
							return LoadErr(name,plist,in) ;
						lastlist->depends = dlist ;
						continue ;
					} else
						break ;
				*l = malloc(sizeof(*list)) ;
				if (*l) {
					char *p = buf ;
					int i = 0 ;
					memset(*l,0,sizeof(*list)) ;
					while (*p && *p != ';')
						(*l)->name[i++] = *p++ ;
					if (*p) 
						p++ ;
					i = 0;
					while (*p)
						(*l)->title[i++] = *p++ ;	
					lastlist = *l ;
					l = &(*l)->next ;
				}
			}
			if (xstricmp(buf,"</TARGET>"))
				return LoadErr(name,plist,in) ;
			(*pl)->files = list ;
			pl = &(*pl)->next ;
		}
	}
	if (xstricmp(buf,"</TARGETS>"))
		return LoadErr(name,plist,in) ;
   if (ReadString(buf,in,0))
      return LoadErr(name,plist,in) ;
   if (xstricmp(buf,"<PROJWIN"))
		return LoadErr(name,plist,in) ;
   sscanf(buf+9,"%d %d %d %d %d",&rect->left,&rect->top,&rect->right,&rect->bottom,&temp) ;
   if (temp & 1)
      docking |= DF_PROJECT ;
   else
      docking &= ~DF_PROJECT ;
   if (temp & 2)
      docking |= HF_PROJECT ;
   else
      docking &= ~HF_PROJECT ;
   if (ReadString(buf,in,0))
      return LoadErr(name,plist,in) ;
   if (xstricmp(buf,"<WATCHWIN"))
		return LoadErr(name,plist,in) ;
   sscanf(buf+9,"%d %d %d %d %d",&wrect.left,&wrect.top,&wrect.right,&wrect.bottom,&temp) ;
   if (temp & 1)
      docking |= DF_WATCH ;
   else
      docking &= ~DF_WATCH ;
   if (temp & 2)
      docking |= HF_WATCH ;
   else
      docking &= ~HF_WATCH ;
	CloseAll() ;
	if (RestoreWindows(in))
		return LoadErr(name,plist,in) ;
	if (ReadString(buf,in,"</PROJECT>"))
		return LoadErr(name,plist,in) ;
	fclose(in) ;
   MoveWindow(hwndTab,rect->left,rect->top,rect->right-rect->left,rect->bottom-rect->top,TRUE) ;
   MoveWindow(hwndWatch,wrect.left,wrect.top,wrect.right-wrect.left,wrect.bottom-wrect.top,TRUE) ;
   PostMessage(hwndFrame,WM_REDOSIZING,0,0) ;
		
	return plist ;
}
void ProjectSaveList(void)
{
	OPENFILENAME ofn ;
	PROJLIST *list = projectList ;
	FILE *out; 
   RECT r ;
   POINT p ;
   if (!projectList)
      return ;
	if (!szProjectTitle[0]) {
      if (!SaveFileDialog(&ofn,0,hwndProject,TRUE,szProjectFilter,"ProjDir")) 
			return ;
		out = fopen(ofn.lpstrFile,"w") ;
	} else
		out = fopen(szProjectName,"w") ;
   fprintf(out,"<PROJECT %d>\n<TARGETS>\n",PROJVERS) ;
	while (list) {
		FILELIST *list1 = list->files ;
		fprintf(out,"<TARGET %s;%s>\n",list->name,list->title) ;
		fprintf(out,"<PATHS %s;%s>\n",list->includePath, list->outputPath) ;
      fprintf(out,"<BUILD %d %x>\n",list->buildType,list->buildFlags) ;
      fprintf(out,"<OPTS \"%s\" \"%s\" \"%s\" \"%s\">\n",list->compileopts,
               list->assembleopts, list->linkopts, list->libopts) ;
      fprintf(out,"%s\n",list->cmdline) ;
		while (list1) {
			fprintf(out,"%s;%s\n",list1->name,list1->title) ;
			if (list1->depends) {
				DEPENDSLIST *d = list1->depends ;
				fprintf(out,"<DEPENDS>\n") ;
				while (d) {
					fprintf(out,"%s;%s\n",d->name,d->title) ;
					d = d->next ;
				}
				fprintf(out,"</DEPENDS>\n") ;
			}
			list1 = list1->next ;
		}
		fprintf(out,"</TARGET>\n") ;
		list = list->next ;
	}
	fprintf(out,"</TARGETS>\n") ;
   GetWindowRect(hwndTab,&r) ;
   p.x = r.left ;
   p.y = r.top ;
   if (docking & DF_PROJECT)
      ScreenToClient(hwndFrame,&p) ;
   else
      ScreenToClient(hwndClient,&p) ;
   fprintf(out,"<PROJWIN %d %d %d %d %d>\n",p.x,p.y,r.right-r.left+p.x,r.bottom-r.top+p.y,
               (docking&DF_PROJECT?1 : 0) | (docking &HF_PROJECT ?2 : 0));    
   GetWindowRect(hwndWatch,&r) ;
   p.x = r.left ;
   p.y = r.top ;
   if (docking & DF_WATCH)
      ScreenToClient(hwndFrame,&p) ;
   else
      ScreenToClient(hwndClient,&p) ;
   fprintf(out,"<WATCHWIN %d %d %d %d %d>\n",p.x,p.y,r.right-r.left+p.x,r.bottom-r.top+p.y,
               (docking&DF_WATCH?1 : 0) | (docking &HF_WATCH ?2 : 0));    
	SaveWindows(out) ;
	fprintf(out,"</PROJECT>\n") ;
   fclose(out) ;
}
static void InitItems(HWND hTree, PROJLIST *projlist)
{
	PROJLIST *l = projlist ;
	int i = 0 ;
	HTREEITEM h = TVI_FIRST ;
   TreeView_DeleteAllItems(hTree) ;
	while (l) {
		int j = 0;
		FILELIST *m = l->files ;
		HTREEITEM k = TVI_FIRST ;
		h = l->treeHandle = TVInitInsert(hTree,TVI_ROOT,h,l->title,FALSE) ;
		while (m) {
			DEPENDSLIST *n = m->depends ;
			HTREEITEM t = TVI_FIRST ;
			k = m->treeHandle = TVInitInsert(hTree,l->treeHandle,k,m->title,FALSE) ;
			while (n) {
				t = n->treeHandle = TVInitInsert(hTree,m->treeHandle,t,n->title,FALSE) ;
				n = n->next ;
			}
			m = m->next ;
		}
		l = l->next ;
	}
}                
int InsideRect(RECT *r, POINT *q)
{
	if (r->left <=q->x && r->top <= q->y)
      if (r->right > q->x && r->bottom > q->y) {
			return TRUE ;
      }
	return FALSE ;
}    
void FindItemByWind(HWND hwnd, PROJLIST **list, int *sel)
{
	PROJLIST *l =projectList ;
	FILELIST *m ;
	DWINFO *info = (DWINFO *)GetWindowLong(hwnd,0) ;
	*list = 0 ;
	if (!info)
		return ;
	while (l) {
		int i = 1 ;
		m = l->files ;
		while (m) {
			if (!xstricmpz(m->name,info->dwName)) {
				*list = l ;
				*sel = i ;
				return ;
			}
			i++ ;
			m = m->next ;
		}
		l = l->next ;
	}
}
void FindItemByPoint(HWND hwnd, PROJLIST **list, int *pos, int *depend)
{
	POINT q ;
	PROJLIST *l = *list = projectList ;
	GetCursorPos(&q) ;
	ScreenToClient(hwnd,&q) ;
	*pos = -1 ;
	*depend = 0 ;
	if (!l)
		return ;
	while (l) {
		int i = 0 ;
		RECT r ;
		FILELIST *m = l->files ;
		if (TreeView_GetItemRect(treeWindow,l->treeHandle,&r,0)) {
			if (InsideRect(&r,&q)) {
				*pos = i ;
				*list = l ;
				return ;
			}
		}
		while (m) {
			int j = 0 ;
			DEPENDSLIST *n = m->depends ;
			++i ;
			if (TreeView_GetItemRect(treeWindow,m->treeHandle,&r,0)) {
				if (InsideRect(&r,&q)) {
					*pos = i ;
					*list = l ;
					return ;
				}
			}
			while (n) {
				j++ ;
				if (TreeView_GetItemRect(treeWindow,n->treeHandle,&r,0)) {
					if (InsideRect(&r,&q)) {
						*pos = i ;
						*list = l ;
						*depend = j ;
						return ;
					}
				}
				n = n->next ;
			}	
			m = m->next ;
		}	
		l = l->next ;
	}

}
void FindItemBySelected(HWND hwnd, PROJLIST **list, int *pos, int *depend)
{
	PROJLIST *l = *list = projectList ;
	*pos = -1 ;
	*depend = 0 ;
	if (!l)
		return ;
	while (l) {
		int i = 0 ;
		RECT r ;
		FILELIST *m = l->files ;
    if (treeViewSelected == l->treeHandle) {
      *pos = i ;
      *list = l ;
      return ;
    }
		while (m) {
			int j = 0 ;
			DEPENDSLIST *n = m->depends ;
			++i ;
      if (treeViewSelected == m->treeHandle) {
        *pos = i ;
        *list = l ;
        return ;
      }
			while (n) {
				j++ ;
        if (treeViewSelected == n->treeHandle) {
          *pos = i ;
          *depend = j ;
          *list = l ;
          return ;
        }
				n = n->next ;
			}	
			m = m->next ;
		}	
		l = l->next ;
	}

}
PROJLIST *ProjectFindSelectedEXE(void)
{
	PROJLIST *l = projectList ;
   if (!hwndProject || !l)
		return 0 ;
   if (!l->next) {
      selectedProject = l ;
      return l ;
   }
   /* Did they select a project in the project window? */
	while (l) {
		FILELIST *m = l->files ;
      selectedProject = l ;
      if (l->buildFlags & BF_CHOSENPROJECT)
         return l ;
		l = l->next ;
	}
   /* no look for a selection */
   l = projectList ;
	if (treeViewSelected == 0)
		return 0 ;
	while (l) {
		FILELIST *m = l->files ;
      selectedProject = l ;
		if (treeViewSelected == l->treeHandle)
         return l ;
		while (m) {
			FILELIST *n = l->files ;
			if (treeViewSelected == m->treeHandle)
            return l ;
			while (n) {
				if (treeViewSelected == n->treeHandle)
               return l ;
				n = n->next ;
			}
			m = m->next ;
		}
		l = l->next ;
	}
	return 0 ;
}
	
LRESULT  CALLBACK _export ProjectProc( HWND hwnd, UINT iMessage, WPARAM wParam,
																		LPARAM lParam)
{
	static int selectedItem,selectedHeader ;
	int i;
   RECT rs,*rt;
	static PROJLIST *selectedProj ;
	NM_TREEVIEW *nm ;
	FILELIST *list ;
	DWINFO info ;
	HMENU menu,popup ;
	POINT pos ;
	switch(iMessage) {
		case WM_SYSCOMMAND :
			if (wParam == SC_CLOSE)
				SendMessage(hwnd,WM_CLOSE,0,0) ;
			break ;
		case WM_NOTIFY:
			nm = (NM_TREEVIEW *)lParam ;
			switch (nm->hdr.code) {
            case NM_DBLCLK:
               FindItemByPoint(hwnd,&selectedProj,&selectedItem,&selectedHeader) ;
               PostMessage(hwnd,WM_COMMAND,IDM_OPENFILES,0) ;
               return 0 ;
				case NM_RCLICK:
                 FindItemByPoint(hwnd,&selectedProj,&selectedItem,&selectedHeader) ;
                 menu  = LoadMenu( hInstance, "PROJECTMENU" ) ;
                 popup = GetSubMenu( menu, 0 );
                  if (!selectedItem) {
							EnableMenuItem(menu,IDM_OPENFILES,MF_GRAYED) ;
							EnableMenuItem(menu,IDM_COMPILEFILE,MF_GRAYED) ;
						} else if (!selectedHeader && selectedItem != -1) {
							EnableMenuItem(menu,IDM_PROJECTPROPERTIES, MF_GRAYED) ;
							EnableMenuItem(menu,IDM_CALCDEPENDS,MF_GRAYED) ;
							EnableMenuItem(menu,IDM_ADDTARGET,MF_GRAYED) ;
							EnableMenuItem(menu,IDM_REMOVETARGET,MF_GRAYED) ;
						} else {
							EnableMenuItem(menu,IDM_CALCDEPENDS,MF_GRAYED) ;
							if (selectedItem != -1)
								EnableMenuItem(menu,IDM_ADDTARGET,MF_GRAYED) ;
							else
								EnableMenuItem(menu,IDM_OPENFILES,MF_GRAYED) ;
							EnableMenuItem(menu,IDM_REMOVETARGET,MF_GRAYED) ;
							EnableMenuItem(menu,IDM_ADDFILES,MF_GRAYED) ;
							EnableMenuItem(menu,IDM_REMOVEFILES,MF_GRAYED) ;
							EnableMenuItem(menu,IDM_COMPILEFILE,MF_GRAYED) ;
							EnableMenuItem(menu,IDM_PROJECTPROPERTIES, MF_GRAYED) ;
						}
  					GetCursorPos( &pos );
  					TrackPopupMenuEx( popup, TPM_BOTTOMALIGN | TPM_LEFTBUTTON,
								pos.x, pos.y, hwnd, NULL );
  					DestroyMenu( menu );
					break ;
				case TVN_SELCHANGED:
					nm = (NM_TREEVIEW *)lParam ;
					treeViewSelected = nm->itemNew.hItem ;
          FindItemBySelected(hwnd,&selectedProj,&selectedItem,&selectedHeader) ;
					break ;
			}	
			break ;
		case WM_COMMAND:
			switch(LOWORD(wParam)) {
				case IDM_CALCDEPENDS:
					CalcDepends(treeWindow,projectList) ;
					break ;
				case IDM_ADDFILES:
					ProjectAddFile(selectedProj,selectedItem) ;
					break ;
				case IDM_REMOVEFILES:
					ProjectDeleteFile(selectedProj,selectedItem) ;
					break ;
				case IDM_ADDTARGET:
					ProjectAddTarget(selectedProj) ;
					break ;
				case IDM_REMOVETARGET:
					ProjectDeleteTarget(selectedProj) ;
					break ;
				case IDM_COMPILEFILE:
					Compiler(selectedProj,selectedItem) ;
					break ;
				case IDM_BUILDALL :
					markProjects(0) ;
					CalcRebuilds() ;
					markProjects(1) ;
					Maker() ;
               CheckEditWindowChanged() ;
					break ;
				case IDM_MAKE:
					markProjects(0) ;
					CalcRebuilds() ;
					Maker() ;
               CheckEditWindowChanged() ;
					break ;
				case IDM_PROJECTPROPERTIES:
					TargetProperties(hInstance,hwnd, selectedProj) ;
					break ;
				case IDM_OPENFILES:
doopen:
					selectedItem-- ;
					list = selectedProj->files ;
					for (i=0; i < selectedItem ; i++)
						if (list)
							list = list->next ;
					if (selectedHeader) {
						DEPENDSLIST *llist = list->depends ;
						for (i=1; i < selectedHeader; i++)
							if (llist)
								llist = llist->next ;
						if (llist) {
							strcpy(info.dwName,llist->name) ;
							strcpy(info.dwTitle,llist->title) ;
							info.dwLineNo = -1 ;
							CreateDrawWindow(&info) ;
						}
							
					} else if (list) {
						strcpy(info.dwName,list->name) ;
						strcpy(info.dwTitle,list->title) ;
						info.dwLineNo = -1 ;
						CreateDrawWindow(&info) ;
					}
					break;
				case IDM_CLOSE:
					SendMessage(hwnd,WM_CLOSE,0,0) ;
					break ;
				default:
					return DefMDIChildProc(hwnd,iMessage,wParam,lParam) ;
			}
			break ;
		case WM_SETFOCUS:
			SendMessage(hwndFrame,WM_REDRAWTOOLBAR,0,0) ;
			break ;
		case WM_CREATE:
			hwndProject = hwnd ;
			SetWindowText(hwnd,szProjectTitle) ;
			GetClientRect(hwnd,&rs) ;

			treeViewSelected = 0 ;
			flyellow = LoadBitmap(hInstance,"ID_FLYELLOW") ;
			flred = LoadBitmap(hInstance,"ID_FLRED") ;
			flcyan = LoadBitmap(hInstance,"ID_FLCYAN") ;
			flgreen = LoadBitmap(hInstance,"ID_FLGREEN") ;
			flwhite = LoadBitmap(hInstance,"ID_FLWHITE") ;
			fllib = LoadBitmap(hInstance,"ID_FLLIB") ;
			fldll = LoadBitmap(hInstance,"ID_FLDLL") ;
			flexe = LoadBitmap(hInstance,"ID_FLEXE") ;
			treeIml = ImageList_Create(16,16,FALSE,8,0) ;
			ilyellow = ImageList_Add(treeIml, flyellow, 0) ;
			ilred = ImageList_Add(treeIml, flred, 0) ;
			ilcyan = ImageList_Add(treeIml, flcyan, 0) ;
			ilgreen = ImageList_Add(treeIml, flgreen, 0) ;
			ilwhite = ImageList_Add(treeIml, flwhite, 0) ;
			illib = ImageList_Add(treeIml, fllib, 0) ;
			ildll = ImageList_Add(treeIml, fldll, 0) ;
			ilexe = ImageList_Add(treeIml, flexe, 0) ;
			DeleteObject(flyellow) ;
			DeleteObject(flred) ;
			DeleteObject(flcyan) ;
			DeleteObject(flgreen) ;
			DeleteObject(flwhite) ;
			DeleteObject(fllib) ;
			DeleteObject(fldll) ;
			DeleteObject(flexe) ;
			treeWindow = CreateWindowEx(0,WC_TREEVIEW,"",
					WS_VISIBLE | WS_CHILD | WS_BORDER | TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS,
					0,0,rs.right,rs.bottom,hwnd, (HMENU) ID_TREEVIEW, hInstance, NULL) ;
			TreeView_SetImageList(treeWindow,treeIml,TVSIL_NORMAL) ;
			InitItems(treeWindow, projectList) ;
         selectedProj = 0 ;
         selectedItem = selectedHeader = 0 ;
			return 0 ;
		case WM_CLOSE:
			break ;
		case WM_DESTROY:
			DestroyWindow(treeWindow) ;
			ProjectSaveList() ;
			hwndProject = 0 ;
			ProjectFreeList() ;
			break ;
		case WM_SIZE:       
			MoveWindow(treeWindow,0,0,LOWORD(lParam),HIWORD(lParam),TRUE) ;
			break ;
		default: 
			break ;
	}
	return DefMDIChildProc(hwnd,iMessage,wParam,lParam) ;
}
void RegisterProjectWindow(void)
{
		WNDCLASS wc ;
      wc.style = CS_DBLCLKS ;
		wc.lpfnWndProc = &ProjectProc ;
		wc.cbClsExtra = 0;
		wc.cbWndExtra = sizeof(void *) ;
		wc.hInstance = hInstance ;
		wc.hIcon = LoadIcon(0,IDI_APPLICATION) ;
		wc.hCursor = LoadCursor(0,IDC_ARROW) ;
		wc.hbrBackground = GetStockObject(WHITE_BRUSH) ;
		wc.lpszMenuName = 0 ;
		wc.lpszClassName = szProjectClassName ;
		RegisterClass(&wc) ;
}
void NewProject (char *name)
{
	PROJLIST *list = 0 ;
   RECT rect ;
   if (projectList)
		ProjectSaveList() ;
   strcpy(szProjectName,name) ;
   strcpy(szProjectTitle,name) ;
   if (!(list = ProjectLoadList(szProjectName, &rect)))
      return ;
   ProjectFreeList() ;
   ProjectNewList(list );
   InitItems(treeWindow,projectList) ;
   SetWindowText(hwndProject,szProjectTitle) ;
}
void CreateProjectWindow(int new, HWND parent)
{
	MDICREATESTRUCT mc ;
	PROJLIST *list = 0 ;
	OPENFILENAME ofn ;
   RECT rect ;
   if (projectList)
		ProjectSaveList() ;
	if (!new) {
      if (!(OpenFileDialog(&ofn,0,hwndClient,TRUE,FALSE,szProjectFilter,"ProjDir")))
			return ;
		strcpy(szProjectTitle, ofn.lpstrFileTitle) ;
      strcpy(szProjectName, ofn.lpstrFile) ;
      if (!(list = ProjectLoadList(szProjectName, &rect)))
			return ;
	} else {
      
      if (new == 2) {
         if (!SaveFileDialog(&ofn,0,hwndProject,TRUE,szProjectFilter,"ProjDir")) 
            return ;
         strcpy(szProjectTitle, ofn.lpstrFileTitle) ;
         strcpy(szProjectName, ofn.lpstrFile) ;
      } else {
         szProjectTitle[0] = 0 ;
            szProjectName[0] = 0 ;
      }
	}
	if (hwndProject) {
		ProjectFreeList() ;
		ProjectNewList(list );
      InitItems(treeWindow,projectList) ;
		SetWindowText(hwndProject,szProjectTitle) ;
	} else {
      ProjectNewList(list );
      GetTabRect(&rect) ;
      hwndProject = CreateWindow( szProjectClassName, szProjectTitle,
            WS_VISIBLE | WS_CHILD,
            rect.left,                               
            rect.top,
            rect.right-rect.left,
            rect.bottom-rect.top, parent, 0 ,hInstance, 0) ;
	}
}