char	ProjectFilterStr[] = "C-- Project Files (*.CMP)\000*.CMP\000All Files (*.*)\000*.*\000";
dword	hProjectEdit;
byte	ProjectChange;
dword	hProject, hOut, ProjectOldProc;
byte	ProjectNotSave		= "Project not saved, save it now?";
byte	NotFound			= "File not found";
byte	Cmm					= "\\C--\\C-- ";
byte	ExtExe				= ".exe";
byte	CreatePipeError		= "Error during pipe creation";
byte	CreateProcessError	= "Error during process creation\n";
byte	szCr				= {0x0D,0};
byte	szQuote				= {'"',0};

void	RemoveFileExt(dword lpFileName)
{
	lstrlen(lpFileName);
	EDX = lpFileName;
	WHILE (EAX)
	{
		EAX--;
		IF(DSBYTE [EDX+EAX]=='.')
		{
			DSBYTE [EDX+EAX] = 0;
			BREAK;
		}
	}
}
void	run(dword lpFileName)
{
	byte	outbuffer[256];
	STARTUPINFO	startupinfo	= 0;
	PROCESS_INFORMATION	pinfo = 0;
	
	lstrcpy(#outbuffer,lpFileName);
	lstrlen(lpFileName);
	lstrcpy(#outbuffer[EAX-3],"exe");
	CreateProcess(0,#outbuffer,0,0,TRUE,0,0,0,#startupinfo,#pinfo);
}
dword	Compiles(dword hWnd,hOut,lpFileName,nCommand,fClear)
{
	byte	buffer[256],buffer2[256],outbuffer[512];
	SECURITY_ATTRIBUTES	sat;
	STARTUPINFO	startupinfo;
	PROCESS_INFORMATION	pinfo;
	dword	hRead,hWrite,bytesRead,fExitCode;

	fExitCode = 0;
	LoadCursor(0,IDC_WAIT);
	SetCursor(EAX);
	SetFocus(hOut);
	outbuffer = 0;
	IF((fClear==1)||(fClear==2))
	{
		SendMessage(hOut,WM_SETTEXT,0,#outbuffer);
		SendMessage(hOut,EM_SCROLLCARET,0,0);
	}
	EAX = nCommand;
	IF(EAX==1)
	{
		lstrcpy(#outbuffer,#Cmm);
		lstrcat(#outbuffer,#szQuote);
		lstrcat(#outbuffer,lpFileName);
		lstrcat(#outbuffer,#szQuote);
		EAX = #ExtExe;
	}
	ELSE
		jmp		EX
	IF(EAX)
	{
		//Delete old file
		push	EAX
		lstrcpy(#buffer2,lpFileName);
		RemoveFileExt(#buffer2);
		pop		EAX
		lstrcat(#buffer2,EAX);
		DeleteFile(#buffer2);
	}
	SendMessage(hOut,EM_REPLACESEL,FALSE,#szCr);
	SendMessage(hOut,EM_REPLACESEL,FALSE,#outbuffer);
	SendMessage(hOut,EM_REPLACESEL,FALSE,#szCr);
	SendMessage(hOut,EM_REPLACESEL,FALSE,#szCr);
	SendMessage(hOut,EM_SCROLLCARET,0,0);
	sat.nLength = sizeof (SECURITY_ATTRIBUTES);
	sat.lpSecurityDescriptor = NULL;
	sat.bInheritHandle = TRUE;
	IF(CreatePipe(#hRead,#hWrite,#sat,NULL)==NULL)
	{
		//CreatePipe failed
		LoadCursor(0,IDC_ARROW);
		SetCursor(EAX);
		MessageBox(hWnd,#CreatePipeError,#AppName,MB_ICONERROR+MB_OK);
	}
	else
	{
		startupinfo.cb = sizeof (STARTUPINFO);
		GetStartupInfo(#startupinfo);
		EAX = hWrite;
		startupinfo.hStdOutput = EAX;
		startupinfo.hStdError = EAX;
		startupinfo.dwFlags = STARTF_USESHOWWINDOW+STARTF_USESTDHANDLES;
		startupinfo.wShowWindow = SW_HIDE;
		//Create process
		IF(CreateProcess(NULL,#outbuffer,NULL,NULL,TRUE,NULL,NULL,NULL,#startupinfo,#pinfo)==NULL)
		{
			//CreateProcess failed
			CloseHandle(hRead);
			CloseHandle(hWrite);
			LoadCursor(0,IDC_ARROW);
			SetCursor(EAX);
			lstrcpy(#buffer,#CreateProcessError);
			lstrcat(#buffer,#outbuffer);
			MessageBox(hWnd,#buffer,#AppName,MB_ICONERROR+MB_OK);
		}
		else
		{
			CloseHandle(hWrite);
			CloseHandle(pinfo.hProcess);
			CloseHandle(pinfo.hThread);
			RtlZeroMemory(#outbuffer,sizeof (outbuffer));
			while (TRUE)
			{
				IF (ReadFile(hRead,#outbuffer,1,#bytesRead,NULL)==NULL) BREAK;
				ELSE
				{
					AL = outbuffer[0];
					IF (AL!=0Ah)
						SendMessage(hOut,EM_REPLACESEL,FALSE,#outbuffer);
					ELSE
						SendMessage(hOut,EM_SCROLLCARET,0,0);
				}
			}
			CloseHandle(hRead);
		}
		SendMessage(hOut,EM_SCROLLCARET,0,0);
		SetFocus(hOut);
	}
EX:
	LoadCursor(0,IDC_ARROW);
	SetCursor(EAX);
	return fExitCode;
}

void	OpenProject()
{
	EDITSTREAM	est;

	ofn.lpstrFile	= #ProjectName;
	ofn.lpstrFilter	= #ProjectFilterStr;
	ofn.Flags = OFN_HIDEREADONLY;

	IF(ProjectChange == TRUE)
	{
		IF(MessageBox(hWnd,#ProjectNotSave,#AppName,MB_YESNO | MB_ICONQUESTION)==IDYES)
			SaveProject();
	}
	IF(!GetOpenFileName(#ofn)) return;
	hProjectEdit = CreateWindowEx(WS_EX_CLIENTEDGE,#szRAEditClass,NULL,WS_CHILD | WS_VISIBLE | STYLE_NOBACKBUFFER | STYLE_NOCOLLAPSE,0,0,0,0,hWnd,NULL,hInstance,0);
	CreateFile(#ProjectName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
	IF(EAX != INVALID_HANDLE_VALUE)
	{
		hFile = EAX;
		est.dwCookie = EAX;
		est.pfnCallback = #StreamInProc;
		SendMessage(hProjectEdit,EM_STREAMIN,SF_TEXT,#est);
		SendMessage(hProjectEdit,EM_SETMODIFY,FALSE,0);
		CloseHandle(hFile);
		GetProjectPath();
		ListProjectFile();
	}
	ELSE
		MessageBox(hWnd,"New Project File",#AppName,MB_OK);
	SetFocus(hProject);
}
:dword ProjectProc(dword hWnd,uMsg,wParam,lParam)
{
	byte	FileSelect[128],FindName[128];
	WIN32_FIND_DATA	wf;
	EDITSTREAM	est;
	POINT	Pt;
	RECT	rect;
	dword	hSM,nInx;
	int		wmId;
	TC_ITEM	tci;

	switch	(uMsg)
	{
	CASE WM_KEYDOWN:
		SWITCH(wParam)
		{
		CASE VK_F6:		// Refresh
			Refresh();
			BREAK;
		}
		break;
	CASE WM_CREATE:
		ProjectChange = 0;
		break;
	CASE WM_LBUTTONDBLCLK:
		EDX = SendMessage(hProject,LB_GETCURSEL,0,0);
		SendMessage(hProject,LB_GETTEXT,EDX,#FileSelect);
		IF(EAX == LB_ERR) return;
		lstrcpy(#FileName,#ProjectPath);
		lstrcat(#FileName,#FileSelect);

		PUSH	EBX
		nInx = -1;
		tci.mask = TCIF_PARAM;
		EAX = TRUE;
		WHILE(EAX)
		{
			nInx++;
			IF(SendMessage(hTab,TCM_GETITEM,nInx,# tci))
			{
				EBX = tci.lParam;
				IF(lstrcmpi(#EBX.TABMEM.filename,#FileName)==0)
				{
					SendMessage(hTab,TCM_SETCURSEL,nInx,0);
					TabToolActivate();
					POP		EBX
					return;
				}
			}
		}
		POP		EBX
		lstrcpy(#FindName,#ProjectName);
		lstrlen(#FindName);
		EDX = #FindName;
		WHILE (EAX)
		{
			EAX--;
			IF(DSBYTE [EDX+EAX]==0x5c)
			{
				DSBYTE [EDX+EAX] = 0;
				BREAK;
			}
		}
		lstrcat(#FindName,"\\");
		lstrcat(#FindName,#FileSelect);
		FindFirstFile(#FileSelect,#wf);
		IF(EAX == INVALID_HANDLE_VALUE)
		{
			MessageBox(hWnd,#NotFound,#AppName,MB_OK);
			break;
		}
		lstrcpy(#FileName,#FindName);
		CreateRAEdit();
		LoadFile(hREd,#FileName);
		TabToolAdd(hREd,#FileName);
		SetWinCaption(#FileName);
		SendMessage(hREd,REM_SETBLOCKS,0,#blocks);
		SetProcMark(hREd);
		SetFocus(hREd);
		BREAK;
	case WM_RBUTTONDOWN:
		GetCursorPos(#Pt);
		hSM	= GetSubMenu(hProjectMenu,0);
		TrackPopupMenu(hSM,TPM_LEFTALIGN | TPM_LEFTBUTTON, Pt.x,Pt.y,0,	hWnd,NULL);
		BREAK;
	case WM_COMMAND:
		wmId = LOWORD(wParam);
		SWITCH	(wmId)
		{
		CASE IDM_PROJECT_POPUP_OPEN:
			OpenProject();
			BREAK;
		case IDM_PROJECT_POPUP_SAVE:
			SaveProject();
			BREAK;
		case IDM_PROJECT_POPUP_ADD:
			AddFile();
			BREAK;
		case IDM_PROJECT_POPUP_DEL:
			DelFile();
			BREAK;
		case IDM_PROJECT_POPUP_CLOSE:
			CloseProject();
			BREAK;
		}
	}
	CallWindowProc(ProjectOldProc,hWnd,uMsg,wParam,lParam);
}
:void	ListProjectFile()
{
	byte	line[256];
	dword	nLine = 0,tLine,hTemp;

	SendMessage(hProperty,LB_RESETCONTENT,0,0);
	SendMessage(hProject,LB_RESETCONTENT,0,0);
	tLine = SendMessage(hProjectEdit,EM_GETLINECOUNT,0,0);
	while(nLine	< tLine)
	{
		SSWORD[#line] = 256;
		ECX = SendMessage(hProjectEdit,EM_GETLINE,nLine,#line);
		IF(ECX!=0)
		{
			line[ECX] = 0;
			SendMessage(hProject,LB_ADDSTRING,0,#line);
			hTemp = CreateWindowEx(WS_EX_CLIENTEDGE,#szRAEditClass,NULL,WS_CHILD | WS_VISIBLE | STYLE_NOBACKBUFFER | STYLE_NOCOLLAPSE,0,0,0,0,hWnd,NULL,hInstance,0);		
			LoadFile(hTemp, #line);
			SetProcMark(hTemp);
			GetProc(hTemp);
			DestroyWindow(hTemp);
		}
	nLine++;
	}
}
:void	SaveProject()
{
	EDITSTREAM	est;
	byte	buffer2[8196],buffer1[64];
	dword	nList,i;

	SendMessage(hProjectEdit,WM_SETTEXT,0,0);
	nList = SendMessage(hProject,LB_GETCOUNT,0,0);
	SendMessage(hProject,LB_GETTEXT,0,#buffer2);
	lstrcat(#buffer2,"\n");
	FOR(i=1;i<=nList;i++)
	{
		buffer1 = 0;
		SendMessage(hProject,LB_GETTEXT,i,#buffer1);
		lstrcat(#buffer2,#buffer1);
		lstrcat(#buffer2,"\n");
	}
	SendMessage(hProjectEdit,WM_SETTEXT,0,#buffer2);
	CreateFile(#ProjectName,GENERIC_WRITE,FILE_SHARE_READ,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
	IF(EAX != INVALID_HANDLE_VALUE)
	{
		hFile = EAX;
		est.dwCookie = EAX;
		est.pfnCallback = #StreamOutProc;
		SendMessage(hProjectEdit,EM_STREAMOUT,SF_TEXT,#est);
		SendMessage(hProjectEdit,EM_SETMODIFY,FALSE,0);
		CloseHandle(hFile);
		ProjectChange = 0;
	}
	ELSE
		MessageBox(hWnd,#OpenFileFail,#AppName,MB_OK | MB_ICONERROR);
}
void	CloseProject()
{
	IF(ProjectChange == TRUE)
	{
		IF(MessageBox(hWnd,#ProjectNotSave,#AppName,MB_YESNO | MB_ICONQUESTION)==IDYES)
			SaveProject();
	}
	UpdateAll(WM_CLOSE);
	SendMessage(hProperty,LB_RESETCONTENT,0,0);
	SendMessage(hProject,LB_RESETCONTENT,0,0);
	UpdateAll(WM_CLOSE);
	ProjectChange = ProjectName = 0;
	TabToolClose();
	SetWinCaption(#NewFile);
}
void	AddFile()
{
	byte	buffer[128],TempFileName[128];
	dword	i,nList;
	
	ofn.lpstrFilter	= #FilterString;
	ofn.lpstrFile	= #FileName;
	ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST;
	IF(!GetOpenFileName(#ofn)) return;
	lstrcpy(#buffer,RemovePath(#FileName));
	nList = SendMessage(hProject,LB_GETCOUNT,0,0);
	FOR(i=0;i<nList;i++)
	{
		SendMessage(hProject,LB_GETTEXT,i,#TempFileName);
		IF(lstrcmp(#TempFileName,#buffer)==0)
		{
			MessageBox(hWnd,"Cannot add same file",#AppName,MB_OK);
			return;
		}
	}

	SendMessage(hProject,LB_ADDSTRING,0,#buffer);
	ProjectChange = TRUE;
}
void	DelFile()
{
	EDX = SendMessage(hProject,LB_GETCURSEL,0,0);
	SendMessage(hProject,LB_DELETESTRING,EDX,0);
	ProjectChange = TRUE;
}
void	GetProjectPath()
{
	lstrcpy(#ProjectPath,#ProjectName);
	lstrlen(#ProjectPath);
	EDX = #ProjectPath;
	WHILE (EAX)
	{
		EAX--;
		IF(DSBYTE [EDX+EAX]==0x5c)
		{
			DSBYTE [EDX+EAX] = 0;
			BREAK;
		}
	}
	lstrcat(#ProjectPath,"\\");
}