/* 
   Copyright 2001-2003 Free Software Foundation, Inc.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
   02111-1307, USA.  

   You may contact the author at:

   mailto::camille@bluegrass.net

   or by snail mail at:

   David Lindauer
   850 Washburn Ave Apt 99
   Louisville, KY 40222

**********************************************************************

This is the main program.  It sets everything up, handles global
resize issues, and the window procedure handles the main menu, sometimes
dispatching items to other windows as needed.

**********************************************************************

*/
#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include "header.h"
#include "dir.h"
#include "wargs.h"
#include "splash.h"
#include "sys\stat.h"

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

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

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

HWND hwndToolEdit, hwndToolDebug, hwndToolBuild ;

char *watchhist[MAX_COMBO_HISTORY] ;

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

int initialIDs[INITIAL_DOCK_COUNT] = { DID_TABWND, DID_ERRORWND, DID_WATCHWND, 
   DID_EDITTOOL, DID_BUILDTOOL, DID_DEBUGTOOL } ;
CCD_params initialDocks[INITIAL_DOCK_COUNT] = {
   { DOCK_LEFT, DOCK_LEFT, TRUE, 0, 0, 0, 1000*200, 
      { 0,0, 200, 200 }, { 0,0,200, 200}, {0,0,200, 200}, {0,0,0,0} } ,
   { DOCK_BOTTOM, DOCK_BOTTOM, FALSE, 0, 0,0, 1000*500, 
      { 0,0, 500, 110 }, { 0,0,500, 110}, {0,0,500, 110}, {0,0,0,0} } ,
   { DOCK_BOTTOM, DOCK_BOTTOM, TRUE, 0, 1,0, 1000*500, 
      { 0,0, 500, 80 }, { 0,0,500,80}, {0,0,500,80}, {0,0,0,0} } ,
   { DOCK_TOP, DOCK_TOP, FALSE, 0, 0,0, 0, 
      { 0,0, 200, 30 }, { 0,0,200, 30}, {0,0,200, 30}, {0,0,0,0} } ,
   { DOCK_TOP, DOCK_TOP, FALSE, 0, 1,0, 0, 
      { 0,0, 200, 30 }, { 0,0,200, 30}, {0,0,200, 30}, {0,0,0,0} } ,
   { DOCK_TOP, DOCK_TOP, FALSE, 0, 2,0, 0, 
      { 0,0, 200, 30 }, { 0,0,200, 30}, {0,0,200, 30}, {0,0,0,0} } ,
} ;
   static char *edithints[] = {
    "New","Open","Save","Print","","Cut","Copy","Paste","Undo","",
      "Find","Find Next", "Replace ", "Find In Files", "", "Goto",
      "", "To Upper Case", "To Lower Case" } ;
      
   static char *makehints[] = {
      "Compile","Make","Build"
   } ;
   static char *debughints[] = {
      "Start/Stop debugging","","Breakpoint","","Stop", "" ,"Run","Run to", "", "Step in", "Step over", "Step out"
   } ;
   static TBBUTTON editButtons[]  = {
    { 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},
      { 3, IDM_PRINT, 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},
      { 13, IDM_FINDINFILES, 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 },
      { 14, IDM_TOUPPER, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
      { 15, IDM_TOLOWER, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
      { 0, 0, 0, 0, 0, 0 },
} ;
   static TBBUTTON makeButtons[]  = {
      { 0, IDM_COMPILEFILE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
      { 1, IDM_MAKE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
      { 2, IDM_BUILDALL, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
      { 0, 0, 0, 0, 0, 0 },
   } ;

   static TBBUTTON debugButtons[] = {
      { 7, IDM_STARTSTOP, TBSTATE_ENABLED, TBSTYLE_CHECK, 0, 0 } ,
      { 0,0,0,TBSTYLE_SEP, 0, 0 },
      { 2, IDM_BREAKPOINT, 0, TBSTYLE_BUTTON, 0, 0},
		{ 0,0,0,TBSTYLE_SEP, 0, 0 },
      { 6, IDM_STOP, 0, TBSTYLE_BUTTON, 0, 0},
		{ 0,0,0,TBSTYLE_SEP, 0, 0 },
      { 0, IDM_RUN, 0, TBSTYLE_BUTTON, 0, 0},
      { 1, IDM_RUNTO, 0, TBSTYLE_BUTTON, 0, 0},
		{ 0,0,0,TBSTYLE_SEP, 0, 0 },
      { 3, IDM_STEPIN, 0, TBSTYLE_BUTTON, 0, 0},
      { 4, IDM_STEPOVER, 0, TBSTYLE_BUTTON, 0, 0},
      { 5, IDM_STEPOUT, 0, TBSTYLE_BUTTON, 0, 0},
      { 0, 0, 0, 0, 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)
{
   char buf[256] ;
   GetCurrentDirectory(256,buf) ;
   strcpy(szProjectName, buf);
   strcat(szProjectName, "\\hi.prj") ;
   strcpy(buf,string) ;
   abspath(buf) ;
   NewProject(buf) ;
}
int IsSpecialWindow(HWND hwnd)
{
   return hwnd == hwndFind || hwnd == hwndProject || hwnd == hwndError ||
         hwnd == hwndASM || hwnd == hwndRegister || hwnd == hwndDump || 
         hwnd == hwndTab || hwnd == hwndWatch || hwnd == hwndStack ||
         hwnd == hwndThread || hwnd == hwndToolEdit || hwnd == hwndToolBuild ||
         hwnd == hwndToolDebug ;
}
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 WatchAddProc (HWND hwnd, UINT iMessage, WPARAM wParam,
                                                        LPARAM lParam)
{
   static char buf[256] ;
   HWND editwnd ;
   switch (iMessage) {
      case WM_COMMAND:
         switch (LOWORD(wParam)) {
            case IDOK:
               editwnd = GetDlgItem(hwnd, IDC_EDWATCH) ;
               GetWindowText(editwnd,buf,256) ;
               SendMessage(editwnd,WM_SAVEHISTORY,0,0) ;
               EndDialog(hwnd, (int)buf) ;
               break ;
            case IDCANCEL:
               EndDialog(hwnd,0) ;
               break ;
           
         }
         switch (HIWORD(wParam)) {
            case CBN_SELCHANGE:
               EnableWindow(GetDlgItem(hwnd,IDOK),TRUE ) ;
               break ;
            case CBN_EDITCHANGE:
               EnableWindow(GetDlgItem(hwnd,IDOK),GetWindowText((HWND)lParam,buf,2)) ;
               break ;
         }  
         break ;
      case WM_CLOSE:
         PostMessage(hwnd,WM_COMMAND,IDCANCEL,0) ;
         break ;
      case WM_INITDIALOG:
         CenterWindow(hwnd) ;
         editwnd = GetDlgItem(hwnd, IDC_EDWATCH) ;
         SubClassHistoryCombo(editwnd) ;
         SendMessage(editwnd,WM_SETHISTORY,0,(LPARAM)watchhist) ;
         EnableWindow(GetDlgItem(hwnd,IDOK),FALSE ) ;
         SetFocus(GetDlgItem(hwnd,IDC_EDWATCH)) ;
         break ;
   }
   return 0 ;
}                                                        

void MakeToolBar(HWND hwnd)
{

   hwndToolEdit = CreateToolBarWindow(DID_EDITTOOL,hwndFrame,hwndClient,16,15,ID_EDITTB,16,editButtons,edithints,
         0,"Edit tools",210) ;
   hwndToolBuild = CreateToolBarWindow(DID_BUILDTOOL,hwndFrame,hwndClient,16,15,ID_BUILDTB,3,makeButtons,makehints,
         0,"Build tools",220) ;
   hwndToolDebug = CreateToolBarWindow(DID_DEBUGTOOL,hwndFrame,hwndClient,16,15,ID_DEBUGTB,8,debugButtons,debughints,
         0,"Debug tools",230) ;
}
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" ;
	}
}
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[4],i ;
	LPTOOLTIPTEXT lpt ;
	char *name ;
   PROJLIST *plist ;
   char module[256] ;
   int linenum ;
   HDWP deferstruct ;
   char buf[256] ;
   int selstart, selend ;
	switch(iMessage) {
      case WM_ACTIVATE:
         if (LOWORD(wParam) != WA_INACTIVE)
            CheckEditWindowChanged() ;
         if (!initted) {
            initted = TRUE ;
            MakeToolBar(hwnd) ; 
            CreateErrorWindow() ;
            CreateTabWindow() ;
            CreateWatchWindow() ;
            CreateASMWindow() ;
            CreateDumpWindow() ;
            CreateStackWindow() ;
            CreateThreadWindow() ;
            CreateSourceTabWindow() ;
            dmgrSetInfo(initialIDs,initialDocks,INITIAL_DOCK_COUNT) ;
            SendMessage(hwnd, WM_REDRAWTOOLBAR,0,0) ;
         }
         break ;
      case WM_SYSCOMMAND:
         if (wParam == SC_CLOSE) {
            PostMessage(hwnd,WM_COMMAND,IDM_EXIT,0) ;
            return 0 ;
         }
         break ;
		case WM_EXCEPTION:
         dmgrHideWindow(DID_ASMWND,FALSE) ;
			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_PARENTNOTIFY:
         break ;
		case WM_BREAKPOINT:
			dbe = (DEBUG_EVENT *) lParam ;
         if (uState != notDebugging) {
            if (!GetBreakpointLine((DWORD)dbe->u.Exception.ExceptionRecord.ExceptionAddress, &module, &linenum))
               dmgrHideWindow(DID_ASMWND,FALSE) ;
            else
               ApplyBreakAddress(module,linenum) ;
            if (hwndASM)
               SendMessage(hwndASM,WM_COMMAND, ID_SETADDRESS,lParam) ;
         }
			break ;
		case WM_CREATE :
			csx.hWindowMenu = hMenuMain ;
			csx.idFirstChild = IDM_FIRSTCHILD ;
			hwndStatus = CreateStatusWindow(WS_VISIBLE | WS_CHILD,"",hwnd,ID_STATUS_WINDOW) ;
			GetClientRect(hwnd,&rf) ;

			hwndClient = CreateWindowEx( 0, "MDICLIENT", 0,
            WS_CHILD + WS_CLIPCHILDREN + WS_VISIBLE + WS_CLIPSIBLINGS + MDIS_ALLCHILDSTYLES, 
            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 - 340 ;
         parts[1] = rf.right - 260 ;
         parts[2] = rf.right - 180 ;
         parts[3] = rf.right - 100 ;
         parts[4] = rf.right - 20 ;
         SendMessage(hwndStatus,SB_SETPARTS,5,(LPARAM)&parts[0]) ;
         SendMessage(hwndStatus,SB_SETTEXT,0 | SBT_NOBORDERS, (LPARAM)"    ") ;
         dmgrInit(hInstance,hwnd,hwndClient,20) ;
         dmgrAddStatusBar(hwndStatus) ;
         break ;
      case WM_HELP:
         if (GetKeyState(VK_CONTROL) & 0x80000000)
            PostMessage(hwnd,WM_COMMAND,IDM_CONTEXTHELP,0) ;
         else
            PostMessage(hwnd,WM_COMMAND,IDM_CCIDEHELP,0) ;
         break ;
		case WM_COMMAND:
         switch(wParam & 0xffff) {
            case IDM_WINHELP:
               ShowHelp(0) ;
               break ;
            case IDM_TOOLSHELP:
               strcpy(buf,szInstallPath) ;
               strcat(buf,"\\bin\\tools.hlp") ;
               WinHelp(hwnd,buf,HELP_CONTENTS,0) ;
               break ;
            case IDM_CCIDEHELP:
               strcpy(buf,szInstallPath) ;
               strcat(buf,"\\bin\\ccide.hlp") ;
               WinHelp(hwnd,buf,HELP_CONTENTS,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(hwndToolDebug, 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"))
							ExtendedMessageBox("Debug error",0,"Selected target is not an EXE file") ;
                  else {
                     initiateDebug(plist) ;
                     if ((wParam & 0xffff) != IDM_STARTSTOP) {
                        i = SendMessage(hwndToolDebug, TB_GETSTATE, IDM_STARTSTOP,0) ;
                        SendMessage(hwndToolDebug, TB_SETSTATE, IDM_STARTSTOP, MAKELONG(TBSTATE_CHECKED | i,0)) ;
                     }
                     break ;
                  }
					}
               i = SendMessage(hwndToolDebug, TB_GETSTATE, IDM_STARTSTOP,0) ;
               SendMessage(hwndToolDebug, TB_SETSTATE, IDM_STARTSTOP, MAKELONG(~TBSTATE_CHECKED & i,0)) ;
					break ;			
				case IDM_STOPDEBUGGING:
					abortDebug() ;
               i = SendMessage(hwndToolDebug, TB_GETSTATE, IDM_STARTSTOP,0) ;
               SendMessage(hwndToolDebug, 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_VIEWBUILDBAR:
               dmgrHideWindow(DID_BUILDTOOL,FALSE) ;
               break ;
            case IDM_VIEWEDITBAR:
               dmgrHideWindow(DID_EDITTOOL,FALSE) ;
               break ;
            case IDM_VIEWDEBUGBAR:
               dmgrHideWindow(DID_DEBUGTOOL,FALSE) ;
               break ;
            case IDM_VIEWSTACK:
               dmgrHideWindow(DID_STACKWND,FALSE) ;
               break  ;
            case IDM_VIEWTHREAD:
               dmgrHideWindow(DID_THREADWND,FALSE) ;
               break ;
				case IDM_VIEWASM:
               dmgrHideWindow(DID_ASMWND,FALSE) ;
					break ;
				case IDM_VIEWDUMP:
               dmgrHideWindow(DID_MEMWND,FALSE) ;
					break ;
				case IDM_VIEWPROJECT:
               dmgrHideWindow(DID_TABWND,FALSE) ;
					return 0;
            case IDM_VIEWWATCH:
               dmgrHideWindow(DID_WATCHWND,FALSE) ;
					return 0;
				case IDM_VIEWERROR:
               dmgrHideWindow(DID_ERRORWND,FALSE) ;
					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:
               dmgrHideWindow(DID_TABWND,FALSE) ;
               CreateProjectWindow(2,0) ;
					break ;
				case IDM_OPENPROJECT:
               dmgrHideWindow(DID_TABWND,FALSE) ;
               CreateProjectWindow(FALSE,0) ;
					break ;
				case IDM_CLOSEPROJECT:
               dmgrHideWindow(DID_TABWND,FALSE) ;
               ProjectSaveList(TRUE) ;
               ProjectFreeList() ;
               SendMessage(hwndTab,WM_CLOSE,0,0 ) ;
               SetWindowText(hwnd,"CC386 IDE") ;
					break ;
            case IDM_SAVEPROJECT:
               ProjectSaveList(FALSE) ;
               break ;
            case IDM_ADDTARGET:
               dmgrHideWindow(DID_TABWND,FALSE) ;
               SendMessage(hwndProject,iMessage,wParam,lParam) ;
               break ;
				case IDM_GENERALPROPERTIES:
					DisplayProperties(hInstance, hwndClient) ;
					break ;
				case IDM_COMPILEFILE:
               
               if (uState != notDebugging)
                  if  (ExtendedMessageBox("Debug mode",MB_YESNO,"You need to stop debugging to compile.\nDo you wish to stop debugging?") == IDNO)
                     break ;
                  else
                     abortDebug() ;
					win = (HWND) SendMessage(hwndClient,WM_MDIGETACTIVE,0,0) ;
               if (IsWindow(win) && !IsSpecialWindow(win)) {
                  FindItemByWind(win,&proj,&sel) ;
                  Compiler(proj,sel) ;
                  CheckEditWindowChanged() ;
               }
					break ;
            case IDM_COMPILEVIAPROJ:
				case IDM_MAKE:
				case IDM_BUILDALL:
				case IDM_PROJECTPROPERTIES:
				case IDM_CALCDEPENDS:
            case IDM_GENMAKE:
               if (uState != notDebugging)
                  if  (ExtendedMessageBox("Debug mode",MB_YESNO,"You need to stop debugging to Build the project.\nDo you wish to stop debugging?") == IDNO)
                     break ;
                  else
                     abortDebug() ;
					if (hwndProject) {
						PostMessage(hwndProject,WM_COMMAND,wParam,lParam) ;
					}
					break ;
            case IDM_FINDINFILES:
               FindInFiles() ;
               break ;
            case IDM_BOOKMARK:
               ToggleBookMark() ;
               break ;
            case IDM_NEXTBOOKMARK:
               NextBookMark() ;
               break ;
            case IDM_PREVBOOKMARK:
               PreviousBookMark() ;
               break ;
            case IDM_BOOKMARKWINDOW:
               ShowBookMarks() ;
               break ;
            case IDM_PRINT:
               win = (HWND)SendMessage(hwndClient,WM_MDIGETACTIVE,0,0) ;
               if (numberofdrawwindows && IsWindow(win)) 
                  if (!IsSpecialWindow(win))
                     Print(win) ;
               break ;
            case IDM_BROWSE:
               if (IsWindow(win = (HWND) SendMessage(hwndClient,WM_MDIGETACTIVE,0,0)) &&
                     !IsSpecialWindow(win)) {
                  BrowseTo(win) ;
               }
               break ;
            case IDM_BROWSEBACK:
               BrowseBack() ;
               break ;
            case IDM_REMOVEALLBREAKPOINTS:
               TagRemoveAll(TAG_BP) ;
               break ;
            case IDM_REMOVEBOOKMARKS:
               TagRemoveAll(TAG_BOOKMARK) ;
               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 ;
               } else if (wParam >= ID_MRU_PROJ_LIST && wParam < ID_MRU_PROJ_LIST + MAX_MRU) {
                  IndirectProjectWindow(mruprojlist[wParam-ID_MRU_PROJ_LIST]) ;
						return 0 ;
               } else if (IsWindow(win = GetFocus())) {
                  HWND win2 = GetParent(win) ;
                  if (IsWindow(win2))
                     win2 = GetParent(win2) ;
                  if (IsSpecialWindow(win2))
                     SendMessage(win2,WM_COMMAND,wParam,lParam) ;
                  else
                     SendMessage(GetParent(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(GetDlgItem(win,ID_EDITCHILD),EM_GETSEL,(WPARAM)&selstart,(LPARAM)&selend) ;
            }
         SendMessage(hwndToolEdit,TB_ENABLEBUTTON,IDM_PRINT,MAKELONG(mf_state,0)) ;
         SendMessage(hwndToolEdit,TB_ENABLEBUTTON,IDM_CUT,MAKELONG(mf_state,0)) ;
         SendMessage(hwndToolEdit,TB_ENABLEBUTTON,IDM_COPY,MAKELONG(mf_state,0)) ;
         SendMessage(hwndToolEdit,TB_ENABLEBUTTON,IDM_PASTE,MAKELONG(mf_state,0)) ;
         SendMessage(hwndToolEdit,TB_ENABLEBUTTON,IDM_UNDO,MAKELONG(mf_state,0)) ;
         SendMessage(hwndToolEdit,TB_ENABLEBUTTON,IDM_FIND,MAKELONG(mf_state,0)) ;
         SendMessage(hwndToolEdit,TB_ENABLEBUTTON,IDM_TOUPPER,MAKELONG(mf_state /*&& selstart != selend*/,0)) ;
         SendMessage(hwndToolEdit,TB_ENABLEBUTTON,IDM_TOLOWER,MAKELONG(mf_state /*&& selstart != selend*/,0)) ;
//         SendMessage(hwndToolEdit,TB_ENABLEBUTTON,IDM_FINDINFILES,MAKELONG(mf_state,0)) ;
         SendMessage(hwndToolEdit,TB_ENABLEBUTTON,IDM_FINDNEXT,MAKELONG(mf_state,0)) ;
         SendMessage(hwndToolEdit,TB_ENABLEBUTTON,IDM_REPLACE,MAKELONG(mf_state,0)) ;
         SendMessage(hwndToolEdit,TB_ENABLEBUTTON,IDM_GOTO,MAKELONG(mf_state || win == hwndASM || win == hwndDump,0)) ;
         SendMessage(hwndToolDebug, TB_ENABLEBUTTON, IDM_BREAKPOINT, MAKELONG(mf_state||win==hwndASM,0)) ;

         if (mf_state) {
				FindItemByWind(win,&proj,&sel) ;
				if (!proj)
					mf_state = FALSE ;
			}
         SendMessage(hwndToolBuild,TB_ENABLEBUTTON,IDM_COMPILEFILE,MAKELONG(mf_state,0)) ;
			mf_state = hwndProject ? TRUE : FALSE ;
         SendMessage(hwndToolBuild,TB_ENABLEBUTTON,IDM_MAKE,MAKELONG(mf_state,0)) ;
         SendMessage(hwndToolBuild,TB_ENABLEBUTTON,IDM_BUILDALL,MAKELONG(mf_state,0)) ;

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

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

//         SendMessage(hwndToolDebug, 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 ;
            SendMessage(GetDlgItem(win,ID_EDITCHILD),EM_GETSEL,(WPARAM)&selstart,(LPARAM)&selend) ;
         }
      EnableMenuItem(hMenuMain,IDM_CLOSE,mf_state) ;
      EnableMenuItem(hMenuMain,IDM_SAVEAS,mf_state) ;
      EnableMenuItem(hMenuMain,IDM_SAVE,mf_state) ;
      EnableMenuItem(hMenuMain,IDM_PRINT,mf_state) ;
      EnableMenuItem(hMenuMain,IDM_CUT,mf_state) ;
      EnableMenuItem(hMenuMain,IDM_COPY,mf_state) ;
      EnableMenuItem(hMenuMain,IDM_PASTE,mf_state) ;
      EnableMenuItem(hMenuMain,IDM_TOUPPER,(mf_state == MF_ENABLED && selstart != selend) ? MF_ENABLED : MF_GRAYED) ;
      EnableMenuItem(hMenuMain,IDM_TOLOWER,(mf_state == MF_ENABLED && selstart != selend) ? MF_ENABLED : MF_GRAYED) ;
      EnableMenuItem(hMenuMain,IDM_SELECTALL,mf_state) ;
      EnableMenuItem(hMenuMain,IDM_FIND,mf_state) ;
      EnableMenuItem(hMenuMain,IDM_BROWSE,mf_state) ;
      // EnableMenuItem(hMenuMain,IDM_BROWSEBACK,mf_state) ;
      EnableMenuItem(hMenuMain,IDM_BOOKMARK,mf_state) ;
      //EnableMenuItem(hMenuMain,IDM_NEXTBOOKMARK,mf_state) ;
      //EnableMenuItem(hMenuMain,IDM_PREVBOOKMARK,mf_state) ;
      EnableMenuItem(hMenuMain,IDM_FIND,mf_state) ;
//      EnableMenuItem(hMenuMain,IDM_FINDINFILES,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_GENMAKE,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_RUN, mf_state ) ;
         EnableMenuItem(hMenuMain,IDM_STOP, mf_state ) ;
			EnableMenuItem(hMenuMain,IDM_VIEWASM, mf_state ) ;
			EnableMenuItem(hMenuMain,IDM_VIEWDUMP, mf_state ) ;
         EnableMenuItem(hMenuMain,IDM_VIEWSTACK, mf_state ) ;
         EnableMenuItem(hMenuMain,IDM_VIEWWATCH, mf_state ) ;
         EnableMenuItem(hMenuMain,IDM_VIEWTHREAD, 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 ;
			}
			rf.left = rf.top = 0 ;
			rf.right = LOWORD(lParam) ;
			rf.bottom = HIWORD(lParam) ;
			GetWindowRect(hwndStatus,&rs) ;
			rf.top = rf.bottom - rs.bottom + rs.top ;
         MoveWindow(hwndStatus,rf.left,rf.top,rf.right-rf.left,rf.bottom-rf.top,1) ;
         parts[0] = rf.right - 340 ;
         parts[1] = rf.right - 260 ;
         parts[2] = rf.right - 180 ;
         parts[3] = rf.right - 100 ;
         parts[4] = rf.right - 20 ;
         SendMessage(hwndStatus,SB_SETPARTS,5,(LPARAM)&parts[0]) ;
         SendMessage(hwndStatus,SB_SETTEXT,0 | SBT_NOBORDERS, (LPARAM)"    ") ;
         dmgrSizeFrame() ;
         return 0 ;
      case WM_TIMER:
         if (uState != notDebugging)
            return 0 ;
         KillTimer(hwnd, timerid) ;       
         PostMessage(hwnd,WM_CLOSE,0,0) ;
         break ;
		case WM_CLOSE:
         if (uState != notDebugging) {
            if (ExtendedMessageBox("Exit Debugging",MB_YESNO,"This will abort your debug session.  Do you wish to exit?") != IDYES)
               return 0 ;
            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,2,500,0) ;
            return 0 ;
         }
         if (QuerySaveAll() == IDCANCEL)
            return 0 ;
         MRUToProfile(0) ;
         MRUToProfile(1) ;
         dmgrSetRundown() ;
         if (hwndProject) // MUST be after files are saved for tags to be updated
				DestroyWindow(hwndProject) ;			
			break ;
		default:
			if (iMessage == iFindMessage) {
               if (IsWindow(win = (HWND)SendMessage(hwndClient,WM_MDIGETACTIVE,0,0)))
                  SendMessage(win,iMessage,wParam,lParam) ;
               return 0 ;
			}
			break ;
	}
   return DefFrameProc(hwnd, hwndClient, iMessage, wParam, lParam) ;
}
void doSplash(void)
{
   SPLASH   splash;

   splash.hWndOwner    = NULL;               /* Window owner                  */
   splash.hInstance    = hInstance;          /* Instance of application       */
   splash.hInstanceRes = hInstance;          /* Instance of application (res) */
   splash.lpszResource = "BITMAP_SPLASH";    /* Bitmap resource               */
   splash.uTime        = 4000;               /* Timeout in milliseconds       */
   splash.bCentered    = TRUE;               /* Centered-on-screen flag       */
   splash.bTopmost     = FALSE;               /* Topmost flag                  */
   splash.bWait        = FALSE;               /* Wait-end flag                 */
   splash.iPosX        = 0;                  /* X position                    */
   splash.iPosY        = 0;                  /* Y position                    */

   SplashScreen (&splash);
}
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 ;
      memset(&wc,0,sizeof(wc)) ;
      wc.style = 0;
		wc.lpfnWndProc = &WndProc ;
		wc.cbClsExtra = 0;
		wc.cbWndExtra = 0 ;
		wc.hInstance = hInstance ;
      wc.hIcon = LoadIcon(hInstance,MAKEINTRESOURCE(1)) ;
		wc.hCursor = LoadCursor(0,IDC_ARROW) ;
      wc.hbrBackground = 0 ; // COLOR_APPWORKSPACE + 1 ;
		wc.lpszMenuName = 0 ;
		wc.lpszClassName = szFrameClassName ;
		RegisterClass(&wc) ;

		RegisterXeditWindow() ;
      RegisterextTreeWindow() ;
      RegisterControlWindow(hInstance) ;
      RegisterFrameWindow(hInstance );
      RegisterToolBarWindow(hInstance) ;
      RegisterGripWindow(hInstance) ;
      RegisterHistoryComboWindow() ;

      RegisterDrawWindow() ;
		RegisterProjectWindow() ;
		RegisterColorWindow() ;
		RegisterErrorWindow() ;
		RegisterASMWindow() ;
      RegisterStackWindow() ;
      RegisterThreadWindow() ;
		RegisterRegisterWindow() ;
		RegisterDumpWindow() ;
      RegisterTabWindow() ;
      RegisterWatchWindow() ;
      RegisterSourceTabWindow() ;
   }
//   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,"CC386 IDE",
         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) ;
   doSplash() ;

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

   InitHelp();
   argv = CmdLineToC(&argc,lpszCmdLine) ;
	if (argv) {
      if (parse_args(&argc,argv,1) && argc > 1) {
         int i;
         char cwd[256] ;
         StringToProfile("FILEDIR",getcwd(cwd,256)) ;
         for (i=1; i < argc; i++) {
            DWINFO info ;
            struct stat statbuf ;
            strcpy(info.dwTitle,argv[i]) ;
            strcpy(info.dwName,argv[i]) ;
            info.dwLineNo = -1 ;
            if ( stat(info.dwName,&statbuf) != -1)
               CreateDrawWindow(&info) ;
            else
               ExtendedMessageBox("File Open Error",MB_TASKMODAL,"File not found: %s",info.dwName) ;
         }
                     
      }
   }
	while (GetMessage(&msg,0,0,0)) {
		if (!TranslateMDISysAccel(hwndClient,&msg))
         if (!TranslateAccelerator(hwndFrame,hAccel,&msg))
            if (!IsWindow(hwndFind) || !IsDialogMessage(hwndFind,&msg)) {
					TranslateMessage(&msg) ;
					DispatchMessage(&msg) ;
				}
	}
   saveColors() ;
   FreeLibrary(editLib) ;
   RundownHelp() ;
	return msg.wParam ;
}