#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include "header.h"
#include "dir.h"
#include "wargs.h"

extern int numberofdrawwindows ;
extern HWND hwndFind, hwndProject,hwndError, hwndASM;
extern HWND  hwndRegister, hwndDump, hwndTab, hwndWatch, hwndStack ;
extern DWINFO *mrulist[MAX_MRU] ;
extern HANDLE BreakpointSem ;
extern enum DebugStates uState ;
extern char *lines[] ;
extern int curline ;
extern CONTEXT StoppedRegs ;
extern HMODULE htmlLib ;

int docking = DF_PROJECT | DF_ERROR | DF_WATCH ;

#define psShow "Show"
static char szFrameClassName[] = "xccFrame" ;

char szInstallPath[256] ;
HANDLE hMenuMain, hAccel, hwndFrame, hwndClient, hMRUSubMenu, hwndStatus;
HINSTANCE hInstance ;
int iFindMessage ;
HANDLE editLib ;
HWND hwndToolBar ;

void ProjSetup(char select, char *string);
ARGLIST ArgList[] = { 
   {'p',ARG_CONCATSTRING,ProjSetup },
	{0,0,0} 
} ;

	static char *hints[] = {
    "New","Open","Save","","Cut","Copy","Paste","Undo","",
		"Find","Find Next", "Replace ", "", "Goto","","Compile","Make","Build",
      "","Start/Stop debugging","","Breakpoint","","Stop", "" ,"Run","Run to", "", "Step in", "Step over", "Step out"
} ;
	static TBBUTTON tbButtons[]  = {
    { 0, IDM_NEWDRAW, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
    { 1, IDM_OPEN, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0,0},
		{ 2, IDM_SAVE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
      { 0,0,0,TBSTYLE_SEP, 0, 0 },
		{ 4, IDM_CUT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
		{ 5, IDM_COPY, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
		{ 6, IDM_PASTE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
		{ 7, IDM_UNDO, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
		{ 0,0,0,TBSTYLE_SEP, 0, 0 },
		{ 9, IDM_FIND, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
		{ 10, IDM_FINDNEXT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
		{ 11, IDM_REPLACE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
		{ 0,0,0,TBSTYLE_SEP, 0, 0 },
		{ 12, IDM_GOTO, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
		{ 0,0,0,TBSTYLE_SEP, 0, 0 },
		{ 13, IDM_COMPILEFILE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
		{ 14, IDM_MAKE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
		{ 15, IDM_BUILDALL, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
		{ 0,0,0,TBSTYLE_SEP, 0, 0 },
      { 23, IDM_STARTSTOP, TBSTATE_ENABLED, TBSTYLE_CHECK, 0, 0 } ,
      { 0,0,0,TBSTYLE_SEP, 0, 0 },
		{ 18, IDM_BREAKPOINT, 0, TBSTYLE_BUTTON, 0, 0},
		{ 0,0,0,TBSTYLE_SEP, 0, 0 },
		{ 22, IDM_STOP, 0, TBSTYLE_BUTTON, 0, 0},
		{ 0,0,0,TBSTYLE_SEP, 0, 0 },
		{ 16, IDM_RUN, 0, TBSTYLE_BUTTON, 0, 0},
      { 17, IDM_RUNTO, 0, TBSTYLE_BUTTON, 0, 0},
		{ 0,0,0,TBSTYLE_SEP, 0, 0 },
		{ 19, IDM_STEPIN, 0, TBSTYLE_BUTTON, 0, 0},
		{ 20, IDM_STEPOVER, 0, TBSTYLE_BUTTON, 0, 0},
		{ 21, IDM_STEPOUT, 0, TBSTYLE_BUTTON, 0, 0},

		} ;

VOID WINAPI CenterWindow(HWND hWnd)
{
    RECT rect;
    WORD wWidth,
         wHeight;
         
    // find out how big we are
    GetWindowRect(hWnd,&rect);

    // get screen size
    wWidth =GetSystemMetrics(SM_CXSCREEN);
    wHeight=GetSystemMetrics(SM_CYSCREEN);

    // move to center
    MoveWindow(hWnd,(wWidth/2)   - ((rect.right -  rect.left)/2),
                    (wHeight/2)  - ((rect.bottom - rect.top) /2),
                     rect.right  -   rect.left,
                     rect.bottom -   rect.top, 
                     FALSE);
}
int ExtendedMessageBox(char *title,int flag, char *fmt,...)
{
	char string[512];
	va_list argptr;

	va_start( argptr, fmt);
  	vsprintf(string, fmt, argptr);
	va_end(argptr);
   return MessageBox(0,string,title,flag);
}
void ProjSetup(char select, char *string)
{
   NewProject(string) ;
}
int IsSpecialWindow(HWND hwnd)
{
   return hwnd == hwndFind || hwnd == hwndProject || hwnd == hwndError ||
         hwnd == hwndASM || hwnd == hwndRegister || hwnd == hwndDump || 
         hwnd == hwndTab || hwnd == hwndWatch || hwnd == hwndStack ;
}
LRESULT  CALLBACK _export WaitingProc( HWND hwnd, UINT iMessage, WPARAM wParam,
																		LPARAM lParam)
{
	switch(iMessage) {
		case WM_COMMAND:
			if (wParam == IDOK)
				EndDialog(hwnd,0) ;
			break ;
		case WM_INITDIALOG:
			CenterWindow(hwnd) ;
			break ;
	}
	return 0 ;
}
LRESULT  CALLBACK _export YesNoProc( HWND hwnd, UINT iMessage, WPARAM wParam,
                                 LPARAM lParam )
{
	switch(iMessage) {
		case WM_COMMAND:
			switch(wParam) {
				case IDYES:
					EndDialog(hwnd,1) ;
					break ;
				case IDNO:
					EndDialog(hwnd,0) ;
					break ;
				case IDCANCEL:
					EndDialog(hwnd,-1) ;
					break ;
			}
			break ;
		case WM_INITDIALOG:
			CenterWindow(hwnd) ;
			break ;
	}
	return 0 ;
}
LRESULT  CALLBACK _export gotoProc( HWND hwnd, UINT iMessage, WPARAM wParam,
																		LPARAM lParam)
{
	switch(iMessage) {
		case WM_COMMAND:
			if (wParam == IDOK) {
				int i = GetEditFieldValue(hwnd,IDC_GOTO);
				EndDialog(hwnd,i) ;
			}
			break ;
		case WM_CLOSE:
			EndDialog(hwnd,0) ;
			break ;
		case WM_INITDIALOG:
			CenterWindow(hwnd) ;
			SetEditField(hwnd,IDC_GOTO,"") ;
			break ;
	}
	return 0 ;
}
LRESULT  CALLBACK _export gotoProc2( HWND hwnd, UINT iMessage, WPARAM wParam,
																		LPARAM lParam)
{
	char buf[256] ;
	int i ;
	switch(iMessage) {
		case WM_COMMAND:
			if (wParam == IDOK) {
				GetEditField(hwnd,IDC_GOTO,buf);
				for (i=0; i < strlen(buf) ; i++)
					if (!isxdigit(buf[i])) {
						ExtendedMessageBox("Error", 0, "Illegal Value") ;
						return 0 ;
					}
				sscanf(buf,"%x",&i) ;
				EndDialog(hwnd,i) ;
			}
			break ;
		case WM_CLOSE:
			EndDialog(hwnd,0xffffffff) ;
			break ;
		case WM_INITDIALOG:
			CenterWindow(hwnd) ;
			SetEditField(hwnd,IDC_GOTO,"") ;
			break ;
	}
	return 0 ;
}
LRESULT CALLBACK _export WatchAddProc (HWND hwnd, UINT iMessage, WPARAM wParam,
                                                        LPARAM lParam)
{
   static char buf[256] ;
   switch (iMessage) {
      case WM_COMMAND:
         switch (LOWORD(wParam)) {
            case IDOK:
               GetEditField(hwnd,IDC_EDWATCH,buf) ;
               EndDialog(hwnd, (int)buf) ;
               break ;
            case IDCANCEL:
               EndDialog(hwnd,0) ;
               break ;
         }
         break ;
      case WM_CLOSE:
         PostMessage(hwnd,WM_COMMAND,IDCANCEL,0) ;
         break ;
      case WM_INITDIALOG:
         CenterWindow(hwnd) ;
         SetEditField(hwnd,IDC_EDWATCH,"") ;
         SetFocus(GetDlgItem(hwnd,IDC_EDWATCH)) ;
         break ;
   }
   return 0 ;
}                                                        

void MakeToolBar(HWND hwnd)
{

   hwndToolBar = CreateToolbarEx(hwnd,WS_CHILD | TBSTYLE_TOOLTIPS , 
                        ID_TOOLBAR,24,hInstance,
                        ID_TOOLBAR, tbButtons, 31, 16,15,16,15,sizeof(TBBUTTON)) ;
	ShowWindow(hwndToolBar, SW_SHOW) ;
}
char *exceptval (int num)
{
	switch (num) {
    case EXCEPTION_ACCESS_VIOLATION          : return "ACCESS VIOLATION" ;
    case EXCEPTION_DATATYPE_MISALIGNMENT     : return "DATATYPE MISALIGNMENT" ;
    case EXCEPTION_ARRAY_BOUNDS_EXCEEDED     : return "ARRAY BOUNDS EXCEEDED" ;
    case EXCEPTION_FLT_DENORMAL_OPERAND      : return "FLOAT DENORMAL OPERAND" ;
    case EXCEPTION_FLT_DIVIDE_BY_ZERO        : return "FLOAT DIVIDE BY ZERO" ;
    case EXCEPTION_FLT_INEXACT_RESULT        : return "FLOAT INEXACT RESULT" ;
    case EXCEPTION_FLT_INVALID_OPERATION     : return "FLOAT INVALID OPERATION" ;
    case EXCEPTION_FLT_OVERFLOW              : return "FLOAT OVERFLOW" ;
    case EXCEPTION_FLT_STACK_CHECK           : return "FLOAT STACK CHECK" ;
    case EXCEPTION_FLT_UNDERFLOW             : return "FLOAT UNDERFLOW" ;
    case EXCEPTION_INT_DIVIDE_BY_ZERO        : return "INTEGER DIVIDE BY ZERO" ;
    case EXCEPTION_INT_OVERFLOW              : return "INTEGER OVERFLOW" ;
    case EXCEPTION_PRIV_INSTRUCTION          : return "PRIVILEGED INSTRUCTION" ;
    case EXCEPTION_IN_PAGE_ERROR             : return "IN PAGE ERROR" ;
    case EXCEPTION_ILLEGAL_INSTRUCTION       : return "ILLEGALINSTRUCTION" ;
    case EXCEPTION_NONCONTINUABLE_EXCEPTION  : return "NONCONTINUABLE EXCEPTION" ;
    case EXCEPTION_STACK_OVERFLOW            : return "STACK OVERFLOW" ;
    case EXCEPTION_INVALID_DISPOSITION       : return "INVALID DISPOSITION" ;
    case EXCEPTION_GUARD_PAGE                : return "GUARD PAGE VIOLATION" ;
		default : return "Unknown Exception" ;
	}
}
void GetFrameInternalRect(RECT *r)
{
   RECT rs, rt ;
   GetRelativeRect(hwndFrame,hwndStatus,&rs) ;
   GetRelativeRect(hwndFrame,hwndToolBar, &rt) ;
   GetClientRect(hwndFrame, r) ;
   r->top = rt.bottom ;
   r->bottom = rs.top ;

}
void newParent(HWND hwnd, int toframe)
{
   HWND parent = toframe ? hwndFrame : hwndClient ;
   if (parent != GetParent(hwnd))
     SetParent(hwnd,parent) ;
}
LRESULT  CALLBACK _export WndProc( HWND hwnd, UINT iMessage, WPARAM wParam,
                                 LPARAM lParam )
{                
   static int timerid ;
	PROJLIST *proj;
	int sel ;
	CLIENTCREATESTRUCT csx ;
	static DEBUG_EVENT *dbe ;
   static int initted ;
	HWND win ;
	int mf_state,x_state ;
	RECT rs,rf ;
   RECT rp,rt  ;
	POINT pt ;
	int parts[3],i ;
	LPTOOLTIPTEXT lpt ;
	char *name ;
   PROJLIST *plist ;
   char module[256] ;
   int linenum ;
   HDWP deferstruct ;
	switch(iMessage) {
      case WM_ACTIVATE:
         if (LOWORD(wParam) != WA_INACTIVE)
            CheckEditWindowChanged() ;
         if (!initted) {
            initted = TRUE ;
            CreateErrorWindow() ;
            CreateTabWindow() ;
            CreateWatchWindow() ;
         }
         break ;
      case WM_SYSCOMMAND:
         if (wParam == SC_CLOSE) {
            PostMessage(hwnd,WM_COMMAND,IDM_EXIT,0) ;
            return 0 ;
         }
         break ;
		case WM_EXCEPTION:
			CreateASMWindow() ;
			dbe = (DEBUG_EVENT *) lParam ;
			SendMessage(hwndASM,WM_COMMAND, ID_SETADDRESS,lParam) ;
         ExtendedMessageBox("Exception",MB_TASKMODAL| MB_SETFOREGROUND,"%s",exceptval(dbe->u.Exception.ExceptionRecord.ExceptionCode)) ;
			break ;
		case WM_BREAKPOINT:
			dbe = (DEBUG_EVENT *) lParam ;
         if (uState != notDebugging) {
            if (!GetBreakpointLine((DWORD)dbe->u.Exception.ExceptionRecord.ExceptionAddress, &module, &linenum))
               CreateASMWindow() ;
            else
               ApplyBreakAddress(module,linenum) ;
            if (hwndASM)
               SendMessage(hwndASM,WM_COMMAND, ID_SETADDRESS,lParam) ;
         }
			break ;
		case WM_NOTIFY:
			switch(((LPNMHDR)lParam)->code) {
				case TTN_NEEDTEXT :
					lpt = (LPTOOLTIPTEXT)lParam ;	
					for (i=0; i < sizeof(tbButtons)/sizeof(TBBUTTON) ; i++)
						if (tbButtons[i].idCommand == lpt->hdr.idFrom) {
							lpt->lpszText = hints[i] ;
							break ;
						}
				break ;
			}
			break ;
		case WM_CREATE :
			csx.hWindowMenu = hMenuMain ;
			csx.idFirstChild = IDM_FIRSTCHILD ;
			hwndStatus = CreateStatusWindow(WS_VISIBLE | WS_CHILD,"",hwnd,ID_STATUS_WINDOW) ;
			MakeToolBar(hwnd) ; 
			GetClientRect(hwnd,&rf) ;
			GetWindowRect(hwndStatus,&rs) ;
			pt.x = rs.right ;
			pt.y = rs.top ;
			ScreenToClient(hwnd,&pt) ;
			rf.bottom = pt.y ;
			GetClientRect(hwndToolBar,&rs) ;
			rf.top = rs.bottom;

			hwndClient = CreateWindowEx( 0, "MDICLIENT", 0,
            WS_CHILD + WS_CLIPCHILDREN + WS_VISIBLE + WS_CLIPSIBLINGS, 
            rf.left,
            rf.top,
				rf.right-rf.left,
				rf.bottom-rf.top, hwnd, 0 ,hInstance, &csx) ;
			SendMessage(hwndClient,WM_MDISETMENU,(WPARAM)hMenuMain,(LPARAM)GetSubMenu(hMenuMain,ProjectsMenuItem)) ;
			parts[0] = rf.right - 180 ;
			parts[1] = rf.right - 100 ;
			parts[2] = rf.right - 20;
			SendMessage(hwndStatus,SB_SETPARTS,3,(LPARAM)&parts[0]) ;
			SendMessage(hwnd, WM_REDRAWTOOLBAR,0,0) ;
         break ;
		case WM_COMMAND:
         switch(wParam & 0xffff) {
            case IDM_WINHELP:
               ShowHelp(0) ;
               break ;
            case IDM_ADDWATCH:
               name = DialogBoxParam(hInstance,"ADDWATCHDIALOG",hwnd,(DLGPROC)WatchAddProc,0) ;
               if (name)
                  SendMessage(hwndWatch,WM_ADDWATCH,StoppedRegs.Eip,(LPARAM)name) ;
               break ;
            case IDM_ADDWATCHINDIRECT:
               if (IsWindow(win = (HWND) SendMessage(hwndClient,WM_MDIGETACTIVE,0,0)))
                  if (SendMessage(win,WM_WORDUNDERCURSOR,0,(LPARAM)module))
                     SendMessage(hwndWatch,WM_ADDWATCH,StoppedRegs.Eip,(LPARAM)module) ;
                        // fixme
               break ;
            case IDM_DELETEWATCH:
               SendMessage(hwndWatch,iMessage,wParam,lParam) ;
               break ;
            case IDM_STARTSTOP:
               i = SendMessage(hwndToolBar, TB_GETSTATE, IDM_STARTSTOP,0) ;
               if (!(i & TBSTATE_CHECKED)) {
                  abortDebug() ;
                  break;
               }
               // fall through 
				case IDM_STARTDEBUGGING:
               plist = ProjectFindSelectedEXE() ;
               if (!plist) {
						ExtendedMessageBox("Debug error",0,"Please select a target in the project window") ;
					} else {
                  if (xstricmp(plist->name +strlen(plist->name)-4,".exe",4))
							ExtendedMessageBox("Debug error",0,"Selected target is not an EXE file") ;
                  else {
                     PostMessage(hwnd, WM_COMMAND, IDM_VIEWWATCH,0) ;
                     initiateDebug(plist) ;
                     if ((wParam & 0xffff) != IDM_STARTSTOP) {
                        i = SendMessage(hwndToolBar, TB_GETSTATE, IDM_STARTSTOP,0) ;
                        SendMessage(hwndToolBar, TB_SETSTATE, IDM_STARTSTOP, MAKELONG(TBSTATE_CHECKED | i,0)) ;
                     }
                     break ;
                  }
					}
               i = SendMessage(hwndToolBar, TB_GETSTATE, IDM_STARTSTOP,0) ;
               SendMessage(hwndToolBar, TB_SETSTATE, IDM_STARTSTOP, MAKELONG(~TBSTATE_CHECKED & i,0)) ;
					break ;			
				case IDM_STOPDEBUGGING:
					abortDebug() ;
               i = SendMessage(hwndToolBar, TB_GETSTATE, IDM_STARTSTOP,0) ;
               SendMessage(hwndToolBar, TB_SETSTATE, IDM_STARTSTOP, MAKELONG(~TBSTATE_CHECKED & i,0)) ;
					break ;
				case IDM_STEPIN:
               if (uState != notDebugging && uState != Running ) {
                  StepIn(dbe) ;
                  if (hwndASM)
                     InvalidateRect(hwndASM,0,1) ;
               }
					break ;
				case IDM_RUN:
               if (uState != notDebugging && uState != Running ) {
                  ReleaseSemaphore(BreakpointSem,1,0) ;
                  if (hwndASM)
                     InvalidateRect(hwndASM,0,1) ;
               } else if (uState == notDebugging) {
                  PostMessage(hwnd, WM_COMMAND, IDM_STARTDEBUGGING, 0) ;
               }
					break ;
				case IDM_STOP:
					StopRunning(nullState) ;
					break ;
				case IDM_STEPOVER:
               if (uState != notDebugging && uState != Running ) {
                  StepOver(dbe) ;
                  if (hwndASM)
                     InvalidateRect(hwndASM,0,1) ;
               }
					break ;
				case IDM_STEPOUT:
               if (uState != notDebugging && uState != Running ) {
                  StepOut(dbe) ;
                  if (hwndASM)
                     InvalidateRect(hwndASM,0,1) ;
               }
					break ;
				case IDM_RUNTO:
					if (RunTo(dbe)) {
						if (hwndASM)
							InvalidateRect(hwndASM,0,1) ;
					}
					break ;
				case IDM_BREAKPOINT:
					SetBP(dbe) ;
					break ;
            case IDM_VIEWSTACK:
               CreateStackWindow() ;
               break ;
				case IDM_VIEWASM:
					CreateASMWindow() ;
					break ;
				case IDM_VIEWDUMP:
					CreateDumpWindow(dbe) ;
					break ;
				case IDM_VIEWPROJECT:
               if (docking & HF_PROJECT) {
                  ShowWindow(hwndTab,SW_SHOW) ;
                  docking &= ~HF_PROJECT;
               }
               SendMessage(hwnd,WM_REDOSIZING,0,0) ;
               SetFocus(hwndTab) ;
					return 0;
            case IDM_VIEWWATCH:
               if (docking & HF_WATCH) {
                  ShowWindow(hwndWatch,SW_SHOW) ;
                  docking &= ~HF_WATCH;
               }
               SendMessage(hwnd,WM_REDOSIZING,0,0) ;
               SetFocus(hwndWatch) ;
					return 0;
				case IDM_VIEWERROR:
               if (docking & HF_ERROR) {
                  docking &= ~ HF_ERROR ;
                  PostMessage(hwnd, WM_REDOSIZING,0, 0) ;
                  ShowWindow(hwndError,SW_SHOW) ;
                  if (docking & DF_ERROR) {
                     if (docking & DF_PROJECT) {
                        GetRelativeRect(hwndFrame,hwndError,&rs) ;
                        GetRelativeRect(hwndFrame,hwndTab,&rp) ;
                        rp.bottom = rs.top ;
                        MoveWindow(hwndTab,rp.left,rp.top,rp.right-rp.left,rp.bottom-rp.top,TRUE) ;
                     }
                     if (docking & DF_WATCH) {
                        GetRelativeRect(hwndFrame,hwndError,&rs) ;
                        GetRelativeRect(hwndFrame,hwndWatch,&rp) ;
                        rp.bottom = rs.top ;
                        MoveWindow(hwndWatch,rp.left,rp.top,rp.right-rp.left,rp.bottom-rp.top,TRUE) ;
                     }
                  }
               }
               SendMessage(hwnd,WM_REDOSIZING,0,0) ;
               SetFocus(hwndError) ;
					return 0;
				case IDM_ABOUT :
       		DialogBoxParam(hInstance,"ABOUTDLG",hwnd,(DLGPROC)WaitingProc,0) ;
					return 0 ;
				case IDM_NEWDRAW:   
					CreateDrawWindow((DWINFO *)-1) ;
					return 0 ;
				case IDM_OPEN:
					CreateDrawWindow(0) ;
					return 0 ;
				case IDM_EXIT:
					if (SendMessage(hwnd,WM_QUERYENDSESSION,0,0)) 
						SendMessage(hwnd,WM_CLOSE,0,0) ;
					return 0 ;
				case IDM_CASCADE:
					SendMessage(hwndClient,WM_MDICASCADE,0,0) ;
					return 0 ;
				case IDM_TILE:
					SendMessage(hwndClient,WM_MDITILE,0,0) ;
					return 0 ;
				case IDM_ARRANGE:
					SendMessage(hwndClient,WM_MDIICONARRANGE,0,0) ;
					return 0 ;
				case IDM_NEWPROJECT:
               if (docking & HF_PROJECT) {
                  ShowWindow(hwndTab,SW_SHOW) ;
                  docking &= ~HF_PROJECT;
               }
               CreateProjectWindow(2,0) ;
					break ;
				case IDM_OPENPROJECT:
               if (docking & HF_PROJECT) {
                  ShowWindow(hwndTab,SW_SHOW) ;
                  docking &= ~HF_PROJECT;
               }
               CreateProjectWindow(FALSE,0) ;
					break ;
				case IDM_CLOSEPROJECT:
               if (docking & HF_PROJECT) {
                  ShowWindow(hwndTab,SW_SHOW) ;
                  docking &= ~HF_PROJECT;
               }
               ProjectSaveList() ;
               ProjectFreeList() ;
               SendMessage(hwndTab,WM_CLOSE,0,0 ) ;
					break ;
            case IDM_SAVEPROJECT:
               ProjectSaveList() ;
               break ;
            case IDM_ADDTARGET:
               if (docking & HF_PROJECT) {
                  ShowWindow(hwndTab,SW_SHOW) ;
                  docking &= ~HF_PROJECT;
               }
               SendMessage(hwndProject,iMessage,wParam,lParam) ;
               break ;
				case IDM_GOTO:
					if (IsWindow(win = (HWND) SendMessage(hwndClient,WM_MDIGETACTIVE,0,0))
							&& win != hwndProject && win != hwndError && win != hwndRegister) {
						if (win == hwndASM || win == hwndDump) {
							i = DialogBox(hInstance,"GOTODIALOG2",hwnd,(DLGPROC)gotoProc2) ;
							if (i != 0xffffffff)
								SendMessage(win,WM_COMMAND,wParam,i) ;
						} else {
							i = DialogBox(hInstance,"GOTODIALOG",hwnd,(DLGPROC)gotoProc) ;
							if (i)
								SendMessage(win,WM_COMMAND,wParam,i) ;
						}
					}
					break ;
				case IDM_GENERALPROPERTIES:
					DisplayProperties(hInstance, hwndClient) ;
					break ;
				case IDM_COMPILEFILE:
					win = (HWND) SendMessage(hwndClient,WM_MDIGETACTIVE,0,0) ;
					FindItemByWind(win,&proj,&sel) ;
					Compiler(proj,sel) ;
               CheckEditWindowChanged() ;
					break ;
				case IDM_MAKE:
				case IDM_BUILDALL:
				case IDM_PROJECTPROPERTIES:
				case IDM_CALCDEPENDS:
					if (hwndProject) {
						PostMessage(hwndProject,WM_COMMAND,wParam,lParam) ;
					}
					break ;
				default:
					if (wParam >= ID_MRU_LIST && wParam < ID_MRU_LIST + MAX_MRU) {
						mrulist[wParam-ID_MRU_LIST]->dwLineNo = -1 ;
						CreateDrawWindow(mrulist[wParam-ID_MRU_LIST]) ;
						return 0 ;
					}
					if (IsWindow(win = (HWND) SendMessage(hwndClient,WM_MDIGETACTIVE,0,0)))
						SendMessage(win,WM_COMMAND,wParam,lParam) ;
					break ;
			}
			break ;
		case WM_DESTROY:
			PostQuitMessage(0) ;
			return 0 ;
		case WM_REDRAWTOOLBAR:
         win = (HWND)SendMessage(hwndClient,WM_MDIGETACTIVE,0,0) ;
			mf_state = FALSE ;
			if (numberofdrawwindows && IsWindow(win)) 
            if (!IsSpecialWindow(win))
					mf_state = TRUE ;
			SendMessage(hwndToolBar,TB_ENABLEBUTTON,IDM_CUT,MAKELONG(mf_state,0)) ;
			SendMessage(hwndToolBar,TB_ENABLEBUTTON,IDM_COPY,MAKELONG(mf_state,0)) ;
			SendMessage(hwndToolBar,TB_ENABLEBUTTON,IDM_PASTE,MAKELONG(mf_state,0)) ;
			SendMessage(hwndToolBar,TB_ENABLEBUTTON,IDM_UNDO,MAKELONG(mf_state,0)) ;
			SendMessage(hwndToolBar,TB_ENABLEBUTTON,IDM_FIND,MAKELONG(mf_state,0)) ;
			SendMessage(hwndToolBar,TB_ENABLEBUTTON,IDM_FINDNEXT,MAKELONG(mf_state,0)) ;
			SendMessage(hwndToolBar,TB_ENABLEBUTTON,IDM_REPLACE,MAKELONG(mf_state,0)) ;
			SendMessage(hwndToolBar,TB_ENABLEBUTTON,IDM_GOTO,MAKELONG(mf_state || win == hwndASM || win == hwndDump,0)) ;
			if (mf_state) {
				FindItemByWind(win,&proj,&sel) ;
				if (!proj)
					mf_state = FALSE ;
			}
			SendMessage(hwndToolBar,TB_ENABLEBUTTON,IDM_COMPILEFILE,MAKELONG(mf_state,0)) ;
			mf_state = hwndProject ? TRUE : FALSE ;
			SendMessage(hwndToolBar,TB_ENABLEBUTTON,IDM_MAKE,MAKELONG(mf_state,0)) ;
			SendMessage(hwndToolBar,TB_ENABLEBUTTON,IDM_BUILDALL,MAKELONG(mf_state,0)) ;

			mf_state = uState == atBreakpoint || uState == atException ;
			SendMessage(hwndToolBar, TB_ENABLEBUTTON, IDM_RUN, MAKELONG(mf_state,0)) ;
			SendMessage(hwndToolBar, TB_ENABLEBUTTON, IDM_RUNTO, MAKELONG(mf_state,0)) ;
			SendMessage(hwndToolBar, TB_ENABLEBUTTON, IDM_STEPOVER, MAKELONG(mf_state,0)) ;
			SendMessage(hwndToolBar, TB_ENABLEBUTTON, IDM_STEPIN, MAKELONG(mf_state,0)) ;
			SendMessage(hwndToolBar, TB_ENABLEBUTTON, IDM_STEPOUT, MAKELONG(mf_state,0)) ;

			mf_state = !mf_state && uState != notDebugging ;
			SendMessage(hwndToolBar, TB_ENABLEBUTTON, IDM_STOP, MAKELONG(mf_state,0)) ;

			SendMessage(hwndToolBar, TB_ENABLEBUTTON, IDM_BREAKPOINT, MAKELONG(uState !=notDebugging,0)) ;

			break ;
		case WM_INITMENUPOPUP:
			mf_state = MF_GRAYED ;
      win = (HWND)SendMessage(hwndClient,WM_MDIGETACTIVE,0,0) ;
         if (numberofdrawwindows && IsWindow(win) && !IsSpecialWindow(win))
				mf_state = MF_ENABLED ;
      EnableMenuItem(hMenuMain,IDM_CLOSE,mf_state) ;
      EnableMenuItem(hMenuMain,IDM_SAVEAS,mf_state) ;
      EnableMenuItem(hMenuMain,IDM_SAVE,mf_state) ;
      EnableMenuItem(hMenuMain,IDM_CUT,mf_state) ;
      EnableMenuItem(hMenuMain,IDM_COPY,mf_state) ;
      EnableMenuItem(hMenuMain,IDM_PASTE,mf_state) ;
      EnableMenuItem(hMenuMain,IDM_SELECTALL,mf_state) ;
      EnableMenuItem(hMenuMain,IDM_FIND,mf_state) ;
      EnableMenuItem(hMenuMain,IDM_FINDNEXT,mf_state) ;
      EnableMenuItem(hMenuMain,IDM_REPLACE,mf_state) ;
			x_state == mf_state ;
			if (win == hwndASM || win == hwndDump)
				x_state = MF_ENABLED ;
         EnableMenuItem(hMenuMain,IDM_GOTO,x_state) ;
         if (!IsSpecialWindow(win)) {
				FindItemByWind(win,&proj,&sel) ;
				if (!proj)
					mf_state = MF_GRAYED ;
            else 
               mf_state = MF_ENABLED ;
         } else
            mf_state = MF_GRAYED ;
			
      EnableMenuItem(hMenuMain,IDM_COMPILEFILE,mf_state) ;
			mf_state = MF_GRAYED ;
			if (IsWindow(win))
				mf_state = MF_ENABLED ;
      EnableMenuItem(hMenuMain,IDM_CASCADE,mf_state) ;
      EnableMenuItem(hMenuMain,IDM_TILE,mf_state) ;
      EnableMenuItem(hMenuMain,IDM_ARRANGE,mf_state) ;

			mf_state = MF_GRAYED ;
			if (hwndProject)
				mf_state = MF_ENABLED ;
			EnableMenuItem(hMenuMain,IDM_CLOSEPROJECT,mf_state) ;
			EnableMenuItem(hMenuMain,IDM_ADDTARGET,mf_state) ;
			EnableMenuItem(hMenuMain,IDM_VIEWPROJECT,mf_state) ;
			EnableMenuItem(hMenuMain,IDM_MAKE,mf_state) ;
			EnableMenuItem(hMenuMain,IDM_BUILDALL,mf_state) ;
			if (IsWindow(win))
				EnableMenuItem(hMenuMain,IDM_UNDO,SendMessage(win,EM_CANUNDO,0,0) ? MF_ENABLED : MF_GRAYED) ;
			
			mf_state = uState == notDebugging ? MF_ENABLED : MF_GRAYED ;
			EnableMenuItem(hMenuMain,IDM_STARTDEBUGGING, mf_state ) ;
			mf_state = uState != notDebugging ? MF_ENABLED : MF_GRAYED ;
			EnableMenuItem(hMenuMain,IDM_STOPDEBUGGING, mf_state ) ;
			EnableMenuItem(hMenuMain,IDM_VIEWASM, mf_state ) ;
			EnableMenuItem(hMenuMain,IDM_VIEWDUMP, mf_state ) ;
         EnableMenuItem(hMenuMain,IDM_VIEWSTACK, mf_state ) ;
         mf_state = htmlLib ? MF_ENABLED : MF_GRAYED ;
         EnableMenuItem(hMenuMain,IDM_WINHELP, mf_state ) ;
			return 0 ;

		case WM_SIZE :
			switch (wParam) {
				case SIZEFULLSCREEN:
					IntToProfile(psShow,SW_SHOWMAXIMIZED) ;
					break ;
				case SIZEICONIC:
					IntToProfile(psShow,SW_SHOWMINIMIZED) ;
					break ;
				case SIZENORMAL:
					IntToProfile(psShow,SW_SHOWNORMAL) ;
					break ;
			}
         deferstruct = BeginDeferWindowPos(3 + ((docking & DF_ERROR) ? 1 : 0) +
                  ((docking & DF_PROJECT) ? 1 : 0) +
                  ((docking & DF_WATCH) ? 1 : 0)) ;
                                                   
			rf.left = rf.top = 0 ;
			rf.right = LOWORD(lParam) ;
			rf.bottom = HIWORD(lParam) ;
			GetWindowRect(hwndStatus,&rs) ;
			rf.top = rf.bottom - rs.bottom + rs.top ;
         deferstruct = DeferWindowPos(deferstruct,hwndStatus,0,rf.left,rf.top,rf.right-rf.left,rf.bottom-rf.top, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER) ;
			parts[0] = rf.right - 180 ;
			parts[1] = rf.right - 100 ;
			parts[2] = rf.right - 20;
			SendMessage(hwndStatus,SB_SETPARTS,3,(LPARAM)&parts[0]) ;
			rf.bottom = rf.top ;
			GetClientRect(hwndToolBar,&rs) ;
			rs.right = rf.right ;
         deferstruct = DeferWindowPos(deferstruct,hwndToolBar,0,rs.left, rs.top,rs.right-rs.left,rs.bottom-rs.top, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER ) ;
			rf.top = rs.bottom ;

         if (hwndError && (docking & DF_ERROR)) {
            RECT re ;
            re = rf ;
            re.top = 4*re.bottom/5 ;
            deferstruct = DeferWindowPos(deferstruct,hwndError,0,re.left,re.top,re.right-re.left,re.bottom-re.top,SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER) ;
            if (!(docking & HF_ERROR))
               rf.bottom = re.top ;
         }

         if (hwndTab && (docking & DF_PROJECT)) {
            GetRelativeRect(hwndFrame,hwndTab,&rp) ;
            deferstruct = DeferWindowPos(deferstruct,hwndTab,0,rf.left, rf.top, rp.right-rp.left, rf.bottom-rf.top, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER) ;
            if (!(docking & HF_PROJECT))
               rf.left = rp.right ;
         }
         if (hwndTab && (docking & DF_WATCH)) {
            GetRelativeRect(hwndFrame,hwndWatch,&rp) ;
            GetFrameInternalRect(&rt) ;
            deferstruct = DeferWindowPos(deferstruct, hwndWatch,0,rf.right - rp.right+rp.left, rf.top, rp.right-rp.left, rf.bottom-rf.top, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER) ;
            if (!(docking & HF_WATCH))
               rf.right = rt.right - rp.right ;
         }
         deferstruct = DeferWindowPos(deferstruct, hwndClient,0, rf.left, rf.top,rf.right-rf.left,rf.bottom-rf.top, SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER ) ;
         EndDeferWindowPos(deferstruct) ;         
			return 0;
      case WM_REDOSIZING:
         GetFrameInternalRect(&rp) ;
         GetRelativeRect(hwndFrame, hwndTab, &rs) ;
         GetRelativeRect(hwndFrame, hwndError, &rf) ;
         GetRelativeRect(hwndFrame, hwndWatch, &rt) ;
         if (hwndError && (docking & DF_ERROR) && !(docking & HF_ERROR))
            rp.bottom = rf.top ;
         if (hwndTab && (docking & DF_PROJECT) && !(docking & HF_PROJECT))
            rp.left = rs.right ;
         if (hwndWatch && (docking & DF_WATCH) && !(docking & HF_WATCH))
            rp.right = rp.right - (rt.right -rt.left);
         newParent(hwndTab,docking & DF_PROJECT ) ;
         newParent(hwndError,docking & DF_ERROR) ;
         newParent(hwndWatch,docking & DF_WATCH) ;
         MoveWindow(hwndClient,rp.left, rp.top,rp.right-rp.left,rp.bottom-rp.top, TRUE ) ;
         return 0 ;
      case WM_TIMER:
         KillTimer(hwnd, timerid) ;
         if (uState != notDebugging) {
            timerid = SetTimer(hwnd,0,500,0) ;
            return 0 ;
         }
         PostMessage(hwnd,WM_CLOSE,0,0) ;
         break ;
		case WM_CLOSE:
         if (uState != notDebugging) {
            abortDebug() ;
            // It takes time for the debuggee to end, we can't close until
            // it is done unless we want to put the system into an abnormal
            // state.  We will keep trying with a timer until the debuggee
            // ends and then we will close out the window.
            timerid = SetTimer(hwnd,0,500,0) ;
            return 0 ;
         }
			if (AnyDrawChanged())
            if (DialogBoxParam(hInstance,"SAVEDLG",hwnd,(DLGPROC)YesNoProc,0))
					SaveDrawAll() ;
			MRUToProfile() ;
			if (hwndProject)
				DestroyWindow(hwndProject) ;			
			break ;
		default:
			if (iMessage == iFindMessage) {
					if (IsWindow(win = (HWND) SendMessage(hwndClient,WM_MDIGETACTIVE,0,0)))
						SendMessage(win,iMessage,wParam,lParam) ;
			}
			break ;
	}
   return DefFrameProc(hwnd, hwndClient, iMessage, wParam, lParam) ;
}
int PASCAL WinMain( HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpszCmdLine,
                    int nCmdShow )
{
	DWORD val ;
	MSG msg ;
	RECT r ;
   int argc ;
   char **argv;
	hInstance = hInst ;
	InitCommonControls() ;
   editLib = LoadLibrary("riched32.dll") ; /* Version 1.0 */
	if (!FindWindow(szFrameClassName,0)) {
		WNDCLASS wc ;
      wc.style = 0;
		wc.lpfnWndProc = &WndProc ;
		wc.cbClsExtra = 0;
		wc.cbWndExtra = 0 ;
		wc.hInstance = hInstance ;
		wc.hIcon = LoadIcon(hInstance,"XCCICON") ;
		wc.hCursor = LoadCursor(0,IDC_ARROW) ;
      wc.hbrBackground = 0 ; // COLOR_APPWORKSPACE + 1 ;
		wc.lpszMenuName = 0 ;
		wc.lpszClassName = szFrameClassName ;
		RegisterClass(&wc) ;

		RegisterDrawWindow() ;
		RegisterProjectWindow() ;
		RegisterXeditWindow() ;
		RegisterColorWindow() ;
		RegisterErrorWindow() ;
		RegisterASMWindow() ;
      RegisterStackWindow() ;
		RegisterRegisterWindow() ;
		RegisterDumpWindow() ;
      RegisterTabWindow() ;
      RegisterWatchWindow() ;
      RegisterControlWindow() ;
      RegisterextTreeWindow() ;
	}
   SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_LOWEST) ;
   restoreColors() ;
   strcpy(szInstallPath,(char *)ProfileToString("InstallPath","C:\\cc386")) ;

	hMenuMain = LoadMenu(hInstance,"MAINMENU") ;
	hAccel = LoadAccelerators(hInstance,"MAINACCELERATORS") ;

   hwndFrame = CreateWindowEx( 0 , szFrameClassName,"CCIDE Ver 1.0",
         WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
			CW_USEDEFAULT, 
			CW_USEDEFAULT, 
			CW_USEDEFAULT, 
			CW_USEDEFAULT, 
			0,hMenuMain,hInstance,0) ;
	ShowWindow(hwndFrame,ProfileToInt(psShow,SW_SHOWNORMAL)) ;
	UpdateWindow(hwndFrame) ;

	iFindMessage = RegisterWindowMessage("commdlg_FindReplace") ;
	ProfileToMRU() ;
	MRUToMenu() ;

   InitHelp();
   argv = CmdLineToC(&argc,lpszCmdLine) ;
	if (argv) {
      if (parse_args(&argc,argv,1)) {
         int i;
         for (i=1; i < argc; i++) {
            DWINFO info ;
            strcpy(info.dwTitle,argv[i]) ;
            strcpy(info.dwName,argv[i]) ;
            info.dwLineNo = 0 ;
            CreateDrawWindow(&info) ;
         }
                     
      }
   }
	while (GetMessage(&msg,0,0,0)) {
		if (!TranslateMDISysAccel(hwndClient,&msg))
			if (!hwndFind || !IsDialogMessage(hwndFind,&msg))
				if (!TranslateAccelerator(hwndFrame,hAccel,&msg))  {
					TranslateMessage(&msg) ;
					DispatchMessage(&msg) ;
				}
	}
   saveColors() ;
	unregxedit() ;
//   FreeLibrary(editLib) ;
   RundownHelp() ;
	return msg.wParam ;
}