/* 
CCIDE
Copyright 2001-2011 David Lindauer.

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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

You may contact the author at:
	mailto::camille@bluegrass.net
 */
#define STRICT
#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#include <float.h>
#include "helpid.h"
#include "header.h"
#include <dir.h>
#include "wargs.h"
#include "splash.h"
#include "..\version.h"
#include <sys\stat.h>

/* timer identifiers
 *
 * note that the current timer implementation assumes only one timer
 * will run at a time
 */
#define IDT_STARTING 1
#define IDT_STOPPING 2
#define IDT_CLIENTCONTEXTMENU 3

extern char *findhist[MAX_COMBO_HISTORY];
extern HWND hwndASMBlank;
extern int restoredDocks;
extern HWND children[];
extern char szHelpPath[]; 
extern HANDLE projectSem;
extern int making;
extern int numberofdrawwindows;
extern HWND hwndFind, hwndProject, hwndASM, hwndThread;
extern HWND hwndRegister, hwndDump, hwndTab, hwndWatch, hwndStack;
extern HWND hwndBookmark;
extern DWINFO *mrulist[MAX_MRU],  *mruprojlist[MAX_MRU];
extern HANDLE BreakpointSem;
extern enum DebugStates uState;
extern char *lines[];
extern int curline;
extern THREAD *StoppedThread;
extern PROJLIST *projectList;
extern HFONT DumpFont;

extern int _argc;
extern char **_argv;

// the offset of the WINDOW menu
#define WINDOW_MENU_OFFSET 5

static char szFrameClassName[] = "ccideFrame";
HWND hwndTbFind;
HHOOK hCursHook;
HCURSOR hCursArrow, hCursHourglass;
HANDLE *winMenu[MAX_WINMENU];
char windowTexts[MAX_WINMENU][260];
int winMenuCount;
int WindowItemCount = 0;
char szInstallPath[1024];
HANDLE hMenuMain, hAccel, hwndFrame, hwndClient, hwndStatus;
HINSTANCE hInstance;
int iFindMessage;
HANDLE editLib;

int winShowCount;
int programBusy;

HWND hwndToolEdit, hwndToolDebug, hwndToolBuild;

DWORD threadMain;

char *watchhist[MAX_COMBO_HISTORY];

static int bCmdLineWS, bCmdLineProj;
static char szNewWS[256], szNewProj[256];
static char browseToText[256];
static LOGFONT fontdata = 
{
    15, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
        OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_DONTCARE, 
        "Arial"
};

void ProjSetup(char select, char *string);
void WorkspaceSetup(char select, char *string);
static LOGFONT toolbarFontData = 
{
    -13, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
        OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_MODERN |
        FF_DONTCARE,
		"Arial"
};
ARGLIST ArgList[] = 
{
    {
        'p', ARG_CONCATSTRING, ProjSetup
    }
    , 
    {
        'w', ARG_CONCATSTRING, WorkspaceSetup
    }
    , 
    {
        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] = 
{
    { // tabwnd
        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
        }
    }
    , 
    { //info wind
        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
        }
    }
    , 
    { // watch wind
        DOCK_BOTTOM, DOCK_BOTTOM, TRUE, 0, 0, 0, 1000 *500, 
        {
            0, 0, 500, 80
        }
        , 
        {
            0, 0, 500, 80
        }
        , 
        {
            0, 0, 500, 80
        }
        , 
        {
            0, 0, 0, 0
        }
    }
    , 
    { // edit tool
        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
        }
    }
    , 
    { // build tool
        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
        }
    }
    , 
    { // debug tool
        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
        }
    }
    , 
};
static char *edithints[] = 
{
    "New", "Open", "Save", "Save All", "Print", "", "Cut [Ctl+X]", "Copy [Ctl+C]", 
	"Paste [Ctl+V]", "Undo [Ctl+Z]", "Redo [Ctl+Y]", "",
         "Goto [Ctl+G]", "", "Find [Ctl+F]", "Find Next [F3]", "Replace [Ctl+H]", "Find In Files", "", 
        "To Upper Case", "To Lower Case", "Indent [TAB]", "Outdent [Shift+TAB]"
};

static char *makehints[] = 
{
    "Compile [Ctl+F7]", "Make [F7]", "Build Selected [Shift+F7]", "Build All",
};
static char *debughints[] = 
{
    "Start/Stop Debugging", "Run without debugger", "", "Breakpoint [F9]", "", "Stop", "", "Run [F5]", "Run to Cursor [Ctl+F5]", 
        "", "Step Into [F11]", "Step Over [F10]", "Step Out [Alt+F11]"
};
static TBBUTTON editButtons[] = 
{
    {
        0, IDM_NEWDRAW, TBSTATE_ENABLED, TBSTYLE_BUTTON
    }
    , 
    {
        1, IDM_OPEN, TBSTATE_ENABLED, TBSTYLE_BUTTON
    }
    , 
    {
        2, IDM_SAVE, 0 /* TBSTATE_ENABLED */, TBSTYLE_BUTTON
    }
    , 
    {
        18, IDM_SAVEALL, 0 /* TBSTATE_ENABLED */, TBSTYLE_BUTTON
    }
    , 
    {
        3, IDM_PRINT, 0 /* TBSTATE_ENABLED */, TBSTYLE_BUTTON
    }
    , 
    {
        0, 0, 0, TBSTYLE_SEP
    }
    , 
    {
        4, IDM_CUT, 0 /* TBSTATE_ENABLED */, TBSTYLE_BUTTON
    }
    , 
    {
        5, IDM_COPY, 0 /* TBSTATE_ENABLED */, TBSTYLE_BUTTON
    }
    , 
    {
        6, IDM_PASTE, 0 /* TBSTATE_ENABLED */, TBSTYLE_BUTTON
    }
    , 
    {
        7, IDM_UNDO, 0 /* TBSTATE_ENABLED */, TBSTYLE_BUTTON
    }
    , 
    {
        8, IDM_REDO, 0 /* TBSTATE_ENABLED */, TBSTYLE_BUTTON
    }
    , 
    {
        0, 0, 0, TBSTYLE_SEP
    }
    , 
    {
        12, IDM_GOTO, 0 /* TBSTATE_ENABLED */, TBSTYLE_BUTTON
    }
    , 
    {
        0, 0, 0, TBSTYLE_SEP
    }
    , 
    {
        9, IDM_FIND, 0 /* TBSTATE_ENABLED */, TBSTYLE_BUTTON
    }
    , 
    {
        10, IDM_FINDNEXT, 0 /* TBSTATE_ENABLED */, TBSTYLE_BUTTON
    }
    , 
    {
        11, IDM_REPLACE, 0 /* TBSTATE_ENABLED */, TBSTYLE_BUTTON
    }
    , 
    {
        13, IDM_FINDINFILES, TBSTATE_ENABLED, TBSTYLE_BUTTON
    }
    , 
    {
        130, 10000, TBSTATE_WRAP, TBSTYLE_SEP | TBSTYLE_FLAT, {0}, 0, -1
    }
    , 
    {
        14, IDM_TOUPPER, 0 /* TBSTATE_ENABLED */, TBSTYLE_BUTTON
    }
    , 
    {
        15, IDM_TOLOWER, 0 /* TBSTATE_ENABLED */, TBSTYLE_BUTTON
    }
    , 
    {
        16, IDM_INDENT, 0 /* TBSTATE_ENABLED */, TBSTYLE_BUTTON
    }
    , 
    {
        17, IDM_UNINDENT, 0 /* TBSTATE_ENABLED */, TBSTYLE_BUTTON
    }
    , 
    {
        0, 0, 0, 0
    }
    , 
};
static TBBUTTON makeButtons[] = 
{
    {
        0, IDM_COMPILEFILE, 0 /* TBSTATE_ENABLED */, TBSTYLE_BUTTON
    }
    , 
    {
        1, IDM_MAKE, 0 /* TBSTATE_ENABLED */, TBSTYLE_BUTTON
    }
    , 
    {
        2, IDM_BUILDSELECTED, 0 /* TBSTATE_ENABLED */, TBSTYLE_BUTTON
    }
    , 
    {
        3, IDM_BUILDALL, 0 /* TBSTATE_ENABLED */, TBSTYLE_BUTTON
    }
    , 
    {
        0, 0, 0, 0
    }
    , 
};

static TBBUTTON debugButtons[] = 
{
    {
        7, IDM_STARTSTOP, 0 /* TBSTATE_ENABLED */, TBSTYLE_CHECK
    }
    , 
    {
        8, IDM_RUNNODEBUG, 0 /* TBSTATE_ENABLED */, TBSTYLE_BUTTON
    }
    , 
    {
        0, 0, 0, TBSTYLE_SEP
    }
    , 
    {
        2, IDM_BREAKPOINT, 0, TBSTYLE_BUTTON
    }
    , 
    {
        0, 0, 0, TBSTYLE_SEP
    }
    , 
    {
        6, IDM_STOP, 0, TBSTYLE_BUTTON
    }
    , 
    {
        0, 0, 0, TBSTYLE_SEP
    }
    , 
    {
        0, IDM_RUN, 0, TBSTYLE_BUTTON
    }
    , 
    {
        1, IDM_RUNTO, 0, TBSTYLE_BUTTON
    }
    , 
    {
        0, 0, 0, TBSTYLE_SEP
    }
    , 
    {
        3, IDM_STEPIN, 0, TBSTYLE_BUTTON
    }
    , 
    {
        4, IDM_STEPOVER, 0, TBSTYLE_BUTTON
    }
    , 
    {
        5, IDM_STEPOUT, 0, TBSTYLE_BUTTON
    }
    , 
    {
        0, 0, 0, 0
    }
    , 
};
int MenuBitmapIDs[] = { ID_EDITTB, ID_BUILDTB , ID_DEBUGTB, ID_EXTRA};
struct menuBitmap {
	int id;
	int bitmapNum;
	int submapNum;
	HBITMAP bitmap;
} MenuBitmaps[] = 
{
    {
        IDM_NEWDRAW, 0, 0
    }
    , 
    {
        IDM_OPEN, 0, 1
    }
    , 
    {
        IDM_SAVE, 0, 2
    }
    , 
    {
		IDM_PRINT, 0, 3
    }
    , 
    {
		IDM_CUT, 0, 4
    }
    , 
    {
		IDM_COPY, 0, 5
    }
    , 
    {
		IDM_PASTE, 0, 6
    }
    , 
    {
		IDM_UNDO, 0, 7
    }
    , 
    {
		IDM_REDO, 0, 8
    }
    , 
    {
		IDM_FIND, 0, 9
    }
    , 
    {
		IDM_FINDNEXT, 0, 10
    }
    , 
    {
		IDM_REPLACE, 0, 11
    }
    , 
    {
		IDM_GOTO, 0, 12
    }
    , 
    {
		IDM_FINDINFILES, 0, 13
    }
    , 
	{
		IDM_TOUPPER, 0, 14
    }
    , 
    {
		IDM_TOLOWER, 0, 15
    }
    , 
    {
		IDM_INDENT, 0, 16
    }
    , 
    {
		IDM_UNINDENT,0, 17
    }
    , 
	{
		IDM_SAVEALL, 0, 18
    }
    ,     
    {
		IDM_COMPILEFILE, 1, 0
    }
    , 
    {
		IDM_COMPILEVIAPROJ, 1, 0
    }
    , 
    {
		IDM_MAKE, 1, 1
    }
    , 
    {
		IDM_BUILDSELECTED, 1, 2
    }
    , 
    {
		IDM_BUILDALL, 1, 3
    }
	,
    {
		IDM_RUN, 2, 0
    }
    , 
    {
		IDM_RUNTO, 2, 1
    }
    , 
    {
		IDM_BREAKPOINT, 2, 2
    }
	,
    {
		IDM_STEPIN, 2, 3
    }
    , 
    {
		IDM_STEPOVER, 2, 4
    }
    , 
    {
		IDM_STEPOUT, 2, 5
    }
    , 
    {
		IDM_STOP, 2, 6
    }
    , 
    {
		IDM_STARTSTOP, 2, 7
    }
	,
    {
		IDM_STARTDEBUGGING, 2, 7
    }
	,
	{
		IDM_RUNNODEBUG, 2, 8
	}
	,
	{
		IDM_CLOSE,	3, 0
	}
	,
	{
		IDM_TILEVERT, 3, 1
	}
	,
	{
		IDM_TILEHORIZ, 3, 2
	}
	,
	{
		IDM_CLOSEWINDOW, 3, 3
	}
	,
	{
		IDM_CASCADE, 3, 4
	}
	,
	{
		IDM_GENERALPROPERTIES, 3, 5
	}
	,
	{
		IDM_PROJECTPROPERTIES, 3, 5
	}
	,
//#ifdef XXXXX
	{
		IDM_NEWWINDOW, 3, 7
	}
	,
	{
		IDM_CCIDEHELP, 3, 8
	}
	,
	{
		IDM_LANGUAGEHELP, 3, 8
	}
	,
	{
		IDM_RTLHELP, 3, 8
	}
	,
	{
		IDM_TOOLSHELP, 3, 8
	}
	,
	{
		IDM_SPECIFIEDHELP, 3, 8
	}
	,
	{
		IDM_SAVEAS, 3, 9
	}
	,
	{
		IDM_PRINTPROPERTIES	,3,10
	}
	,
	{
		IDM_OPENWS,3,11
	}
//#endif
};
void SetStatusMessage(char *str, int highlight)
{
	static char buf[256];
	buf[0] = highlight + '0';
	strcpy(buf + 1, str);
	if (buf[1] == 0)
		strcpy(buf + 1, "    ");
    SendMessage(hwndStatus, SB_SETTEXT, 0 | SBT_NOBORDERS | SBT_OWNERDRAW, (LPARAM)
        buf);
}
static int readytodraw = FALSE;
void SetBusy(int state)
{
    if (state)
    {
        if (!programBusy)
            SetCursor(hCursHourglass);
        programBusy++;
    }
    else
    {
        programBusy--;
        if (programBusy <= 0)
        {
            SetCursor(hCursArrow);
            programBusy = 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, ...)
{
    int rv;
    HWND wnd;
    char string[512];
    va_list argptr;

    va_start(argptr, fmt);
    vsprintf(string, fmt, argptr);
    va_end(argptr);
    wnd = GetFocus();
    rv = MessageBox(0, string, title, flag);
    SetFocus(wnd);
    return rv;
}

//-------------------------------------------------------------------------

void projSetupThread(char *buf)
{
	ProjectInsertTarget(0, buf);
}

//-------------------------------------------------------------------------

void ProjSetup(char select, char *string)
{
	bCmdLineProj = TRUE ;
    strcpy(szNewProj, string);
    abspath(szNewProj, 0);
}

void WorkspaceSetup(char select, char *string)
{
    DWORD hand;
    bCmdLineWS = TRUE;
    strcpy(szNewWS, string);
    abspath(szNewWS, 0);
}

//-------------------------------------------------------------------------

int IsSpecialWindow(HWND hwnd)
{
    return (GetWindowLong(hwnd, 4) != EDITSIG);
}

//-------------------------------------------------------------------------

LRESULT CALLBACK _export BrowseToProc(HWND hwnd, UINT iMessage, WPARAM wParam,
    LPARAM lParam)
{
    char buf[3];
    switch (iMessage)
    {
        case WM_COMMAND:
            if (wParam == IDOK)
            {
                GetEditField(hwnd, IDC_BROWSETO, browseToText);
                EndDialog(hwnd, 1);
                break;
            }
            if (HIWORD(wParam) == EN_CHANGE)
            {
                DisableControl(hwnd, IDOK, !GetWindowText((HWND)lParam, buf, 2))
                    ;
                break;
            }
            if (wParam != IDCANCEL)
                break;
        case WM_CLOSE:
            EndDialog(hwnd, 0);
            break;
        case WM_INITDIALOG:
            browseToText[0] = 0;
            CenterWindow(hwnd);
            SetEditField(hwnd, IDC_BROWSETO, "");
            SendDlgItemMessage(hwnd, IDC_BROWSETO, EM_LIMITTEXT, 250, 0);
            DisableControl(hwnd, IDOK, 1);
            break;
    }
    return 0;
}

//-------------------------------------------------------------------------

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)
{
	HFONT xfont;
    hwndToolEdit = CreateToolBarWindow(DID_EDITTOOL, hwndFrame, hwndClient, 16,
        15, ID_EDITTB, 19, editButtons, edithints, 0, "Edit tools", IDH_EDIT_TOOLBAR);
    hwndToolBuild = CreateToolBarWindow(DID_BUILDTOOL, hwndFrame, hwndClient,
        16, 15, ID_BUILDTB, 4, makeButtons, makehints, 0, "Build tools", IDH_BUILD_TOOLBAR);
    hwndToolDebug = CreateToolBarWindow(DID_DEBUGTOOL, hwndFrame, hwndClient,
        16, 15, ID_DEBUGTB, 8, debugButtons, debughints, 0, "Debug tools", IDH_DEBUG_TOOLBAR);
    hwndTbFind = CreateWindowEx(0, "COMBOBOX", "", WS_CHILD + WS_BORDER +
        WS_VISIBLE + WS_TABSTOP + CBS_DROPDOWN + CBS_AUTOHSCROLL, 
                        0,0,100, 200, hwndFrame, (HMENU)ID_TBFIND, hInstance, 0);
	SendMessage(hwndToolEdit, LCF_ADDCONTROL, 0, (LPARAM)hwndTbFind);
    SubClassHistoryCombo(hwndTbFind);
    xfont = CreateFontIndirect(&toolbarFontData);
    SendMessage(hwndTbFind, WM_SETFONT, (WPARAM)xfont, 0);
}

//-------------------------------------------------------------------------

char *exceptval(int num)
{
    static char buf[256];
    switch (num)
    {
        case STATUS_ACCESS_VIOLATION:
            return "ACCESS VIOLATION";
        case STATUS_DATATYPE_MISALIGNMENT:
            return "DATATYPE MISALIGNMENT";
        case STATUS_ARRAY_BOUNDS_EXCEEDED:
            return "ARRAY BOUNDS EXCEEDED";
        case STATUS_FLOAT_DENORMAL_OPERAND:
            return "FLOAT DENORMAL OPERAND";
        case STATUS_FLOAT_DIVIDE_BY_ZERO:
            return "FLOAT DIVIDE BY ZERO";
        case STATUS_FLOAT_INEXACT_RESULT:
            return "FLOAT INEXACT RESULT";
        case STATUS_FLOAT_INVALID_OPERATION:
            return "FLOAT INVALID OPERATION";
        case STATUS_FLOAT_OVERFLOW:
            return "FLOAT OVERFLOW";
        case STATUS_FLOAT_STACK_CHECK:
            return "FLOAT STACK CHECK";
        case STATUS_FLOAT_UNDERFLOW:
            return "FLOAT UNDERFLOW";
        case STATUS_INTEGER_DIVIDE_BY_ZERO:
            return "INTEGER DIVIDE BY ZERO";
        case STATUS_INTEGER_OVERFLOW:
            return "INTEGER OVERFLOW";
        case STATUS_PRIVILEGED_INSTRUCTION:
            return "PRIVILEGED INSTRUCTION";
        case STATUS_IN_PAGE_ERROR:
            return "IN PAGE ERROR";
        case STATUS_ILLEGAL_INSTRUCTION:
            return "ILLEGALINSTRUCTION";
        case STATUS_NONCONTINUABLE_EXCEPTION:
            return "NONCONTINUABLE EXCEPTION";
        case STATUS_STACK_OVERFLOW:
            return "STACK OVERFLOW";
        case STATUS_INVALID_DISPOSITION:
            return "INVALID DISPOSITION";
        case STATUS_GUARD_PAGE_VIOLATION:
            return "GUARD PAGE VIOLATION";
        case STATUS_SEGMENT_NOTIFICATION:
            return "SEGMENT NOTIFICATION";
        case STATUS_INVALID_HANDLE:
            return "INVALID HANDLE";
        case STATUS_NO_MEMORY:
            return "NO MEMORY";
        case STATUS_CONTROL_C_EXIT:
            return "CONTROL C EXIT";
        case STATUS_FLOAT_MULTIPLE_FAULTS:
            return "FLOAT MULTIPLE FAULTS";
        case STATUS_FLOAT_MULTIPLE_TRAPS:
            return "FLOAT MULTIPLE TRAPS";
        case STATUS_ILLEGAL_VLM_REFERENCE:
            return "ILLEGAL VLM REFERENCE";
        case STATUS_REG_NAT_CONSUMPTION:
            return "REG NAT CONSUMPTION";

        default:
            sprintf(buf, "Unknown Exception(%08x)", num);
            return buf;
    }

}

//-------------------------------------------------------------------------

BOOL CALLBACK WindowChangeEnumProc(HWND window, LPARAM param)
{
    HWND hwndLV = (HWND)param;
    MENUITEMINFO mi;
    LV_ITEM item;
    char buf[256];
    int v;
    if (GetParent(window) != hwndClient)
        return TRUE;
    if (!IsWindowVisible(window))
        return TRUE;
    GetWindowText(window, buf, 256);
    item.iItem = winShowCount++;
    item.iSubItem = 0;
    item.mask = LVIF_PARAM | LVIF_TEXT;
    item.lParam = (LPARAM)window;
    item.pszText = buf;
    v = ListView_InsertItem(hwndLV, &item);
    ListView_SetCheckState(hwndLV, v, TRUE);
    return TRUE;
}

//-------------------------------------------------------------------------

static int CreateWindowData(HWND hwnd, int changed)
{
    RECT r;
    HWND hwndLV = GetDlgItem(hwnd, IDC_FILELIST);
    LV_COLUMN lvC;

    GetWindowRect(hwndLV, &r);
    lvC.mask = LVCF_WIDTH | LVCF_SUBITEM;
    lvC.cx = r.right - r.left;
    lvC.iSubItem = 0;
    ListView_InsertColumn(hwndLV, 0, &lvC);
    winShowCount = 0;
    EnumChildWindows(hwndClient, WindowChangeEnumProc, (LPARAM)hwndLV);
    return winShowCount;
}

//-------------------------------------------------------------------------

long APIENTRY WindowShowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM
    lParam)
{
    LV_ITEM item;
    static HFONT hfont;
    switch (message)
    {
        case WM_INITDIALOG:
            hfont = CreateFontIndirect(&fontdata);
            SendMessage(GetDlgItem(hwnd, IDC_FILELIST), WM_SETFONT, (WPARAM)
                hfont, 0);
            if (!CreateWindowData(hwnd, TRUE))
                EndDialog(hwnd, 1);
            else
                CenterWindow(hwnd);
            return 0;
        case WM_NOTIFY:
            if (wParam == IDC_FILELIST)
            {
                if (((LPNMHDR)lParam)->code == NM_DBLCLK)
                {
                    LPNMITEMACTIVATE plvdi = (LPNMITEMACTIVATE)lParam;
                    item.iItem = plvdi->iItem;
                    item.iSubItem = 0;
                    item.mask = LVIF_PARAM;
                    ListView_GetItem(GetDlgItem(hwnd, IDC_FILELIST), &item);
                    SendMessage(hwndClient, WM_MDIACTIVATE, (WPARAM)item.lParam,
                        0);
                    DeleteObject(hfont);
                    EndDialog(hwnd, IDOK);
                }
            }
            return 0;
        case WM_COMMAND:
            switch (wParam &0xffff)
            {
            case IDCANCEL:
                DeleteObject(hfont);
                EndDialog(hwnd, IDCANCEL);
                break;
            }
            break;
        case WM_CLOSE:
            PostMessage(hwnd, WM_COMMAND, IDCANCEL, 0);
            break;
    }
    return 0;
}

//-------------------------------------------------------------------------

void ShowWindowList(void)
{
    DialogBoxParam(hInstance, "DLG_MANYWINDOWS", 0, (DLGPROC)WindowShowProc, 0);
}

//-------------------------------------------------------------------------

BOOL CALLBACK winmenEnumProc(HWND window, LPARAM param)
{
    HANDLE hsub = (HANDLE)param;
    MENUITEMINFO mi;
    if (GetParent(window) != hwndClient)
        return TRUE;
    if (!IsWindowVisible(window))
        return TRUE;
    if (winMenuCount == 0)
    {
        memset(&mi, 0, sizeof(mi));
        mi.cbSize = sizeof(mi);
        mi.fMask = MIIM_TYPE;
        mi.fType = MFT_SEPARATOR;
        InsertMenuItem(hsub, WindowItemCount, TRUE, &mi);
    }
    memset(&mi, 0, sizeof(mi));
    mi.cbSize = sizeof(mi);
    mi.fMask = MIIM_ID | MIIM_TYPE | MIIM_DATA;
    mi.fType = MFT_STRING;
    if (winMenuCount == MAX_WINMENU)
    {
        mi.wID = IDM_WINDOW_MORE;
        mi.dwTypeData = "More Windows...";
        InsertMenuItem(hsub, 1+winMenuCount + WindowItemCount, TRUE, &mi);
        return FALSE;
    }
    else
    {
		sprintf(windowTexts[winMenuCount],"%2d: ",winMenuCount+1);
        GetWindowText(window, windowTexts[winMenuCount]+4, 60);
        mi.dwTypeData = &windowTexts[winMenuCount][0];
        mi.wID = ID_WINDOW_LIST + winMenuCount;
        InsertMenuItem(hsub, 1+winMenuCount + WindowItemCount, TRUE, &mi);
        winMenu[winMenuCount] = window;
        winMenuCount++;
        return TRUE;
    }

}

//-------------------------------------------------------------------------

void SetWindowMenu(void)
{
	int n = WINDOW_MENU_OFFSET;
    HANDLE hsub;
	DWORD maxed;
    int count, i;
	SendMessage(hwndClient, WM_MDIGETACTIVE, 0, (LPARAM)&maxed);
	if (maxed)
		n++;
	hsub = GetSubMenu(hMenuMain, n);
	count = GetMenuItemCount(hsub);
    for (i = WindowItemCount; i < count; i++)
        DeleteMenu(hsub, WindowItemCount, MF_BYPOSITION);
    winMenuCount = 0;
    EnumChildWindows(hwndClient, winmenEnumProc, (LPARAM)hsub);

}

//-------------------------------------------------------------------------

UINT GetMenuCheckedState(int Id)
{
    return !!(GetMenuState(hMenuMain, Id, MF_BYCOMMAND) &MF_CHECKED);
}

//-------------------------------------------------------------------------

void SetMenuCheckedState(int did, int id)
{
    MENUITEMINFO info;

    info.cbSize = sizeof(MENUITEMINFO);
    info.fMask = MIIM_STATE;
    GetMenuItemInfo(hMenuMain, id, MF_BYCOMMAND, &info);
    info.fState = (info.fState &~MFS_CHECKED) | (dmgrGetHiddenState(did) ? 0 :
        MFS_CHECKED);
    SetMenuItemInfo(hMenuMain, id, MF_BYCOMMAND, &info);
}
int GetHelpID(void )
{
	int helpID = HELP_CONTENTS;
	return helpID;
}
	
void LoadFirstWorkspace(void)
{
    int argc = _argc;
    char **argv = _argv;
    if (argv)
    {
        int todo = parse_args(&argc, argv, 1) && argc > 1 ;
        if (!bCmdLineWS)
		{
            LoadDefaultWorkspace();
			if (bCmdLineProj)
			{
				ProjectInsertTarget(0, szNewProj);
                dmgrHideWindow(DID_TABWND, FALSE);
			}
		}
		else
			OpenWorkspace(szNewWS);

        if (todo)
        {
            int i;
            char cwd[256];
            int munged = FALSE;
            StringToProfile("FILEDIR", getcwd(cwd, 256));
            for (i = 1; i < argc; i++)
            {
                DWINFO info;
                char *p = strrchr(argv[i], '\\');
                struct stat statbuf;
                if (p)
                    strcpy(info.dwTitle, p + 1);
                else
                    strcpy(info.dwTitle, argv[i]);
                strcpy(info.dwName, argv[i]);
                abspath(info.dwName, 0);
                info.dwLineNo =  - 1;
                info.logMRU = TRUE;
				info.newFile = FALSE;
                if (stat(info.dwName, &statbuf) !=  - 1)
                    CreateDrawWindow(&info, TRUE);
                else
					if (ExtendedMessageBox("File Error", 
						MB_SETFOREGROUND | MB_SYSTEMMODAL | MB_YESNO, 
						"File '%s' not found, would you like to create it?", 
						argv[i]) == IDYES)
					{
						info.newFile = TRUE;
						CreateDrawWindow(&info, FALSE);
					}
				
            }
//			for (i=1; i < numberofdrawwindows; i++)
//				ShowWindow(children[i], SW_SHOW);
        }
    } else
        LoadDefaultWorkspace();
}

void CreateMenuBitmaps(void)
{
	HBITMAP bitmaps[sizeof(MenuBitmapIDs)/sizeof(int)];
	HDC hDC = GetDC(hwndFrame);
	int i;
	for (i=0; i < sizeof(MenuBitmapIDs)/sizeof(int); i++)
		bitmaps[i] = LoadImage(hInstance, (LPTSTR)MenuBitmapIDs[i], 
			IMAGE_BITMAP, 0, 0, LR_LOADTRANSPARENT);


	for (i=0; i < sizeof(MenuBitmaps)/ sizeof(struct menuBitmap); i++)
	{
		HBITMAP thisBitmap ;
		MenuBitmaps[i].bitmap = CopyBitmap(hwndFrame, bitmaps[MenuBitmaps[i].bitmapNum],
					MenuBitmaps[i].submapNum * 16, 0 , 16, 15);		
	}
	
	for (i=0; i < sizeof(MenuBitmapIDs)/sizeof(int); i++)
		DeleteObject(bitmaps[i]);
	ReleaseDC(hwndFrame, hDC);
}

void InsertBitmapsInMenu(HMENU hMenu)
{
	int i;
    MENUITEMINFO mi;
	for (i=0; i < sizeof(MenuBitmaps)/ sizeof(struct menuBitmap); i++)
	{
		SetMenuItemBitmaps(hMenu, MenuBitmaps[i].id, MF_BYCOMMAND,
			MenuBitmaps[i].bitmap, MenuBitmaps[i].bitmap);
    }
}

//-------------------------------------------------------------------------

LRESULT CALLBACK _export WndProc(HWND hwnd, UINT iMessage, WPARAM wParam,
    LPARAM lParam)
{
    LRESULT rv;
    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;
	int colorfg, colorbg;
	DRAWITEMSTRUCT *di;
	HBRUSH hbr;
	int maxed;
    switch (iMessage)
    {
		case WM_DRAWITEM:
			/* for drawing the first section of the status window */
			di = (DRAWITEMSTRUCT *)lParam;
			if (*(char *)(di->itemData) == '1')
			{
				colorfg = SetTextColor(di->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
				colorbg = SetBkColor(di->hDC, GetSysColor(COLOR_HIGHLIGHT));
				hbr = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
			}
			else
			{
				colorfg = SetTextColor(di->hDC, 0);
				colorbg = SetBkColor(di->hDC, GetSysColor(COLOR_3DFACE));
				SetTextColor(di->hDC, colorfg);
				hbr = CreateSolidBrush(GetSysColor(COLOR_3DFACE));
			}				
			FillRect(di->hDC, &di->rcItem, hbr);
			TextOut(di->hDC, di->rcItem.left, di->rcItem.top, (char *)(di->itemData + 1), 
						strlen((char *)di->itemData + 1));
			SetTextColor(di->hDC, colorfg);
			SetBkColor(di->hDC, colorbg);
			DeleteObject(hbr);
			return TRUE;

        case WM_WINDOWPOSCHANGING:
            // Keeps it from drawing a smaller window prior to the initial
            // ShowWindow....
            if (!readytodraw)
            {
                ((LPWINDOWPOS)lParam)->flags |= SWP_NOREDRAW;
            }
            break;
        case WM_ACTIVATE:
            // check if edit windows changed
            if (LOWORD(wParam) != WA_INACTIVE)
                CheckEditWindowChanged();
            // first activation, init all the windows
            if (!initted)
            {
                DWORD hand;
                initted = TRUE;
			    MakeToolBar(hwnd);
			    CreateErrorWindow();
			    CreateTabWindow();
			    CreateWatchWindow();
			    CreateASMWindow();
			    CreateDumpWindow();
			    CreateStackWindow();
			    CreateThreadWindow();
			    CreateSourceTabWindow();
			    CreateRegisterWindow();
				CreateJumpListWindow();
//			    dmgrSetInfo(initialIDs, initialDocks, INITIAL_DOCK_COUNT);
				timerid = SetTimer(hwnd, IDT_STARTING, 100, 0);
            }
			return 0;
        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;
            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)
							dbe->u.Exception.ExceptionRecord.ExceptionAddress);
			SendErrorMessage(ERR_DEBUG_WINDOW, exceptval(dbe->u.Exception.ExceptionRecord.ExceptionCode));
			SendErrorMessage(ERR_DEBUG_WINDOW, "\r\n");
            ExtendedMessageBox("Exception", MB_SYSTEMMODAL, "%s", exceptval(dbe
                ->u.Exception.ExceptionRecord.ExceptionCode));
            break;
        case WM_PARENTNOTIFY:
			if (LOWORD(wParam) == WM_RBUTTONDOWN) {
				timerid = SetTimer(hwnd, IDT_CLIENTCONTEXTMENU, 100, 0);
			}
            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)
								dbe->u.Exception.ExceptionRecord.ExceptionAddress);
            }
            break;
        case WM_CREATE:
            if (IsDebuggerPresent())
                SetWindowText(hwnd, "CC386 IDE (DEBUGEE)");
            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 | MDIS_ALLCHILDSTYLES | WS_BORDER,
                rf.left, rf.top, rf.right - rf.left, rf.bottom - rf.top, hwnd,
                0, hInstance, &csx);
			SendMessage(hwndClient, WM_MDIGETACTIVE, 0, (LPARAM)&maxed);
            SendMessage(hwndClient, WM_MDISETMENU, (WPARAM)hMenuMain, (LPARAM)
                GetSubMenu(hMenuMain, ProjectsMenuItem + maxed));
            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 | SBT_OWNERDRAW, (LPARAM)
                "    ");
            dmgrInit(hInstance, hwnd, hwndClient, 20);
            dmgrAddStatusBar(hwndStatus);
            break;
        case WM_HELP:
            if (GetKeyState(VK_CONTROL) &0x80000000)
			{
                win = (HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0);
                if (numberofdrawwindows && IsWindow(win))
                    if (!IsSpecialWindow(win))
					{
						SendMessage(win, WM_COMMAND, IDM_SPECIFIEDHELP, 0);
						break;
					}
			}
			else if (GetKeyState(VK_SHIFT) & 0x80000000)
			{
                win = (HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0);
                if (numberofdrawwindows && IsWindow(win))
                    if (!IsSpecialWindow(win))
					{
						SendMessage(win, WM_COMMAND, IDM_RTLHELP, 0);
						break;
					}
			}
            else
                PostMessage(hwnd, WM_COMMAND, IDM_CCIDEHELP, 0);
            break;
        case WM_COMMAND:
            switch (wParam &0xffff)
            {
            case IDM_SPECIFIEDHELP:
               SpecifiedHelp(0);
               break;
			case IDM_RTLHELP:
				RTLHelp(0);
				break;
			case IDM_LANGUAGEHELP:
				LanguageHelp(0);
				break;
            case IDM_TOOLSHELP:
                strcpy(buf, szInstallPath);
                strcat(buf, "\\help\\tools.chm");
                GenericHelp(buf, -1);
                break;
            case IDM_CCIDEHELP:
                strcpy(buf, szInstallPath);
                strcat(buf, "\\help\\ccide.chm");
                GenericHelp(buf, GetHelpID());
                break;
            case IDM_ADDWATCH:
                if (uState != atBreakpoint && uState != atException)
                    break;
                name = DialogBoxParam(hInstance, "ADDWATCHDIALOG", hwnd, 
                    (DLGPROC)WatchAddProc, 0);
                if (name)
                    SendMessage(hwndWatch, WM_ADDWATCH, StoppedThread->regs.Eip,
                        (LPARAM)name);
                break;
            case IDM_ADDWATCHINDIRECT:
                if (uState != atBreakpoint && uState != atException)
                    break;
                if (IsWindow(win = (HWND)SendMessage(hwndClient,
                    WM_MDIGETACTIVE, 0, 0)) && !IsSpecialWindow(win))
                    SendMessage(hwndWatch, WM_ADDWATCHINDIRECT, (WPARAM)win, 0);
                break;
            case IDM_DELETEWATCH:
			case IDM_DELETEALLWATCH:
                if (uState != atBreakpoint && uState != atException)
                    break;
                SendMessage(hwndWatch, iMessage, wParam, lParam);
                break;
                #ifdef HBREAK
                case IDM_HBREAK:
                    hbpDialog();
                    break;
                #endif 
            case IDM_STARTSTOP:
                i = SendMessage(hwndToolDebug, TB_GETSTATE, IDM_STARTSTOP, 0);
                if (!(i &TBSTATE_CHECKED))
                {
                    abortDebug();
                    break;
                }
                // fall through 
            case IDM_STARTDEBUGGING:
                if (uState != notDebugging)
                    break;
                dbgRebuildMain(wParam);
                break;
            case IDM_STOPDEBUGGING:
                if (uState == notDebugging)
                    break;
                abortDebug();
                break;
            case IDM_STEPIN:
				if (uState == notDebugging)
	                dbgRebuildMain(wParam);
                else if (uState != notDebugging && uState != Running)
                {
                    StepIn(dbe);
                    if (hwndASM)
                        InvalidateRect(hwndASM, 0, 1);
                }
                break;
            case IDM_RUN:
            case IDM_RUNF5:
                if (uState != notDebugging && uState != Running)
                {
                    SaveRegisterContext();
                    ReleaseSemaphore(BreakpointSem, 1, 0);
                    if (hwndASM)
                        InvalidateRect(hwndASM, 0, 1);
                }
                else if (uState == notDebugging)
                {
                    PostMessage(hwnd, WM_COMMAND, IDM_STARTDEBUGGING, 0);
                }
				else
				{
					MessageBeep(MB_OK);
				}
                break;
            case IDM_STOP:
                if (uState != Running)
                    break;
                StopRunning(nullState);
                break;
            case IDM_STEPOVER:
				if (uState == notDebugging)
	                dbgRebuildMain(wParam);
                else if (uState != notDebugging && uState != Running)
                {
                    StepOver(dbe);
                    if (hwndASM)
                        InvalidateRect(hwndASM, 0, 1);
                }
                break;
            case IDM_STEPOUT:
				if (uState == notDebugging)
	                dbgRebuildMain(wParam);
                else 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:
				if (GetFocus() == hwndASMBlank)
				{
					SendMessage(hwndASMBlank, WM_COMMAND, IDM_BREAKPOINT, 0);
				}
				else
				{
		            SetBP(dbe);
				}
                break;
			case IDM_SCROLLTOBP:
	            if (!GetBreakpointLine((DWORD)StoppedThread->regs.Eip,
	                &module, &linenum))
	                dmgrHideWindow(DID_ASMWND, FALSE);
	            else
	                ApplyBreakAddress(module, linenum);
	            if (hwndASM)
	                SendMessage(hwndASM, WM_COMMAND, ID_SETADDRESS, StoppedThread->regs.Eip);
				break;
			case IDM_RUNNODEBUG:
				SendMessage(hwndProject, WM_COMMAND, IDM_RUNNODEBUG, 0);
				break;
            case IDM_VIEWBUILDBAR:
                x_state = GetMenuCheckedState(IDM_VIEWBUILDBAR);
                dmgrHideWindow(DID_BUILDTOOL, x_state);
				SetMenuCheckedState(DID_BUILDTOOL, IDM_VIEWBUILDBAR);
                break;
            case IDM_VIEWEDITBAR:
                x_state = GetMenuCheckedState(IDM_VIEWEDITBAR);
                dmgrHideWindow(DID_EDITTOOL, x_state);
				SetMenuCheckedState(DID_EDITTOOL, IDM_VIEWEDITBAR);
                break;
            case IDM_VIEWDEBUGBAR:
                x_state = GetMenuCheckedState(IDM_VIEWDEBUGBAR);
                dmgrHideWindow(DID_DEBUGTOOL, x_state);
				SetMenuCheckedState(DID_DEBUGTOOL, IDM_VIEWDEBUGBAR);
                break;
            case IDM_VIEWSTACK:
                x_state = GetMenuCheckedState(IDM_VIEWSTACK);
                dmgrHideWindow(DID_STACKWND, x_state);
				SetMenuCheckedState(DID_STACKWND, IDM_VIEWSTACK);
                break;
            case IDM_VIEWTHREAD:
                x_state = GetMenuCheckedState(IDM_VIEWTHREAD);
                dmgrHideWindow(DID_THREADWND, x_state);
				SetMenuCheckedState(DID_THREADWND, IDM_VIEWTHREAD);
                break;
            case IDM_VIEWASM:
                x_state = GetMenuCheckedState(IDM_VIEWASM);
                dmgrHideWindow(DID_ASMWND, x_state);
				SetMenuCheckedState(DID_ASMWND, IDM_VIEWASM);
                break;
            case IDM_VIEWDUMP:
                x_state = GetMenuCheckedState(IDM_VIEWDUMP);
                dmgrHideWindow(DID_MEMWND, x_state);
				SetMenuCheckedState(DID_MEMWND, IDM_VIEWDUMP);
                break;
            case IDM_VIEWREGISTER:
                x_state = GetMenuCheckedState(IDM_VIEWREGISTER);
                dmgrHideWindow(DID_REGWND, x_state);
				SetMenuCheckedState(DID_REGWND, IDM_VIEWREGISTER);
                break;
            case IDM_VIEWPROJECT:
                x_state = GetMenuCheckedState(IDM_VIEWPROJECT);
                dmgrHideWindow(DID_TABWND, x_state);
				SetMenuCheckedState(DID_TABWND, IDM_VIEWPROJECT);
                return 0;
            case IDM_VIEWWATCH:
                x_state = GetMenuCheckedState(IDM_VIEWWATCH);
                dmgrHideWindow(DID_WATCHWND, x_state);
				SetMenuCheckedState(DID_WATCHWND, IDM_VIEWWATCH);
                return 0;
            case IDM_VIEWERROR:
                x_state = GetMenuCheckedState(IDM_VIEWERROR);
                dmgrHideWindow(DID_ERRORWND, x_state);
				SetMenuCheckedState(DID_ERRORWND, IDM_VIEWERROR);
                return 0;
            case IDM_ABOUT:
                doAbout();
                //               DialogBoxParam(hInstance,"ABOUTDLG",hwnd,(DLGPROC)WaitingProc,0) ;
                return 0;
            case IDM_NEWDRAW:
                CreateDrawWindow((DWINFO*) - 1, TRUE);
                return 0;
            case IDM_OPEN:
                CreateDrawWindow(0, TRUE);
                return 0;
			case IDM_CLOSEWINDOW:
                win = (HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0);
                if (IsWindow(win))
				{
					if (SendMessage(win, WM_COMMAND, ID_QUERYSAVE, 0) != IDCANCEL)
						SendMessage(win, WM_CLOSE, 0, 0);
				}
 				return 0;
			case IDM_CLOSEALLWINDOWS:
				if (QuerySaveAll() != IDCANCEL)
					CloseAll();
				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_TILEHORIZ:
                SendMessage(hwndClient, WM_MDITILE, MDITILE_HORIZONTAL, 0);
                return 0;
            case IDM_TILEVERT:
                SendMessage(hwndClient, WM_MDITILE, MDITILE_VERTICAL, 0);
                return 0;
            case IDM_ARRANGE:
                SendMessage(hwndClient, WM_MDIICONARRANGE, 0, 0);
                return 0;
            case IDM_NEWPROJECT:
            case IDM_INSERTPROJECT:
            case IDM_NEWWS:
                dmgrHideWindow(DID_TABWND, FALSE);
            case IDM_OPENWS:
            case IDM_CLOSEWS:
            case IDM_SAVEWS:
				if (uState != notDebugging)
				{
				    if (ExtendedMessageBox("Workspace", MB_YESNO, 
				        "This action requires the debugger be stopped.\r\nStop the debugger now?") != IDYES)
				    {
						break ;
				    }
				    abortDebugThread();
				}
                SendMessage(hwndProject, iMessage, wParam, lParam);
                break;
            case IDM_GENERALPROPERTIES:
                DisplayProperties(hInstance, hwndClient, EDITPROP);
                break;
			case IDM_PRINTPROPERTIES:
				DisplayProperties(hInstance, hwndClient, PRINTFORMATPROP);
				break;
            case IDM_COMPILEFILE:
                win = (HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0);
                if (IsWindow(win) && !IsSpecialWindow(win))
                {
                    HTREEITEM item = FindItemByWind(win);
                    TREEDATA *data = getTreeData(item);
                    if (data) {
                        Compiler(data);
                        CheckEditWindowChanged();
                    }
                }
                break;
            case IDM_COMPILEVIAPROJ:
            case IDM_MAKE:
            case IDM_BUILDALL:
            case IDM_PROJECTPROPERTIES:
			case IDM_OPENFILES:
            case IDM_CALCDEPENDS:
			case IDM_ADDFILES:
			case IDM_REMOVEFILES:
            case IDM_GENMAKE:
			case IDM_BUILDSELECTED:
			case IDM_REMOVETARGET:
                if (making)
                    break;
            case IDM_STOPBUILD:
                if (!projectList)
                    break;
                if (hwndProject)
                {
                    PostMessage(hwndProject, WM_COMMAND, wParam, lParam);
                }
                return 0;
            case IDM_FINDINFILES:
                FindInFiles();
                break;
            case IDM_BOOKMARK:
                ToggleBookMark(-1);
                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))
                        while (!Print(win))
						{
							if (ExtendedMessageBox("Margin Error", MB_YESNO, "Incorrect margin settings\n"
											   "Do you want to reset the margins?") != IDYES)
								break;			
								DisplayProperties(hInstance, hwndClient, PRINTFORMATPROP);
						}
                break;
            case IDM_BROWSE:
                if (IsWindow(win = (HWND)SendMessage(hwndClient,
                    WM_MDIGETACTIVE, 0, 0)) && !IsSpecialWindow(win))
                {
                    BrowseTo(win, 0);
                }
                break;
            case IDM_BROWSETO:
                browseToText[0] = 0;
                if (DialogBoxParam(hInstance, "BROWSETODIALOG", hwnd, (DLGPROC)
                    BrowseToProc, 0))
                    BrowseTo(0, browseToText);
                break;
            case IDM_BROWSEBACK:
                BrowseBack();
                break;
            case IDM_REMOVEALLBREAKPOINTS:
                TagRemoveAll(TAG_BP);
                break;
            case IDM_REMOVEBOOKMARKS:
                TagRemoveAll(TAG_BOOKMARK);
                break;
            case IDM_SAVEALL:
                SaveDrawAll();
                break;
            case IDM_WINDOW_MORE:
                ShowWindowList();
                break;
			case IDM_DOSWINDOW:
				SendMessage(hwndProject, WM_COMMAND, IDM_DOSWINDOW, 0);
				break;
			case IDM_MAKEWINDOW:
				SendMessage(hwndProject, WM_COMMAND, IDM_MAKEWINDOW, 0);
				break;
			case IDM_EDITEXTERNALTOOLS:
				EditExternalTools();
				break;
            default:
                if (wParam >= ID_MRU_LIST && wParam < ID_MRU_LIST + MAX_MRU)
                {
                    mrulist[wParam - ID_MRU_LIST]->dwLineNo =  - 1;
                    mrulist[wParam - ID_MRU_LIST]->logMRU = FALSE;
                    CreateDrawWindow(mrulist[wParam - ID_MRU_LIST], TRUE);
                    return 0;
                }
				else if (wParam >= ID_EXTERNALTOOLS && wParam < ID_EXTERNALTOOLS + MAX_EXTERNALTOOLS)
				{
					RunExternalTool(wParam);
				}
                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 (wParam >= ID_WINDOW_LIST && wParam < ID_WINDOW_LIST +
                    MAX_WINMENU)
                {
                    SendMessage(hwndClient, WM_MDIACTIVATE, (WPARAM)
                        winMenu[wParam - ID_WINDOW_LIST], 0);
                }
				else if (LOWORD(wParam) == ID_TBFIND)
				{
					switch(HIWORD(wParam))
					{
						case CBN_KILLFOCUS:
						    SendMessage((HWND)lParam, WM_SAVEHISTORY, 0, (LPARAM)findhist);
							break;
					}
				}
				else if (LOWORD(wParam) == 4000 + VK_RETURN)
				{
					char buf[256];
					int n = GetWindowText(hwndTbFind, buf, 256);
					if (n > 0)
					{
						buf[n] = 0;
						FindStringFromToolbar(buf);
					}
				}
				else if (LOWORD(wParam) == 4000 + VK_ESCAPE)
				{
					HWND x = (HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0);
					SetFocus(x);
                }
                else if (IsWindow(win = GetFocus()))
                {
                    HWND win2 = GetParent(win);
					if (win2 == hwndTbFind)
						win2 = (HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0);
                    if (!IsSpecialWindow(win2))
                        PostMessage(win2, WM_COMMAND, wParam, lParam);
                    else
                    {
                        win2 = GetParent(win2);
						if (win2 != hwnd)
	                        PostMessage(win2, 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_SAVE, MAKELONG
                (mf_state, 0));
            SendMessage(hwndToolEdit, TB_ENABLEBUTTON, IDM_SAVEALL, MAKELONG
                (mf_state, 0));
            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_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_INDENT, MAKELONG
                (mf_state /*&& selstart != selend*/, 0));
            SendMessage(hwndToolEdit, TB_ENABLEBUTTON, IDM_UNINDENT, 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));
            SendMessage(hwndToolEdit, TB_ENABLEBUTTON, IDM_UNDO, MAKELONG
                (mf_state, 0));
            SendMessage(hwndToolEdit, TB_ENABLEBUTTON, IDM_REDO, MAKELONG
                (mf_state, 0));

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

            if (projectList)
            {
                mf_state = TRUE;
                SendMessage(hwndToolDebug, TB_ENABLEBUTTON, IDM_STARTSTOP,
                    MAKELONG(mf_state, 0));
                mf_state = uState != notDebugging;
                i = SendMessage(hwndToolDebug, TB_GETSTATE, IDM_STARTSTOP, 0);
                if (mf_state)
                    SendMessage(hwndToolDebug, TB_SETSTATE, IDM_STARTSTOP,
                        MAKELONG(TBSTATE_CHECKED | i, 0));
                else
                    SendMessage(hwndToolDebug, TB_SETSTATE, IDM_STARTSTOP,
                        MAKELONG(~TBSTATE_CHECKED &i, 0));
            }
            else
            {
                mf_state = FALSE;
                SendMessage(hwndToolDebug, TB_ENABLEBUTTON, IDM_STARTSTOP,
                    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 = uState == Running;
            SendMessage(hwndToolDebug, TB_ENABLEBUTTON, IDM_STOP, MAKELONG
                (mf_state, 0));

            mf_state = uState == notDebugging && projectList && !making;
            SendMessage(hwndToolDebug, TB_ENABLEBUTTON, IDM_RUNNODEBUG, MAKELONG
                (mf_state, 0));

            break;
        case WM_INITMENUPOPUP:
            SetWindowMenu();
            SetMenuCheckedState(DID_BUILDTOOL, IDM_VIEWBUILDBAR);
            SetMenuCheckedState(DID_EDITTOOL, IDM_VIEWEDITBAR);
            SetMenuCheckedState(DID_DEBUGTOOL, IDM_VIEWDEBUGBAR);
            SetMenuCheckedState(DID_TABWND, IDM_VIEWPROJECT);
            SetMenuCheckedState(DID_ERRORWND, IDM_VIEWERROR);
            SetMenuCheckedState(DID_STACKWND, IDM_VIEWSTACK);
            SetMenuCheckedState(DID_THREADWND, IDM_VIEWTHREAD);
            SetMenuCheckedState(DID_ASMWND, IDM_VIEWASM);
            SetMenuCheckedState(DID_MEMWND, IDM_VIEWDUMP);
            SetMenuCheckedState(DID_REGWND, IDM_VIEWREGISTER);
            SetMenuCheckedState(DID_WATCHWND, IDM_VIEWWATCH);

            mf_state = numberofdrawwindows ? MF_ENABLED : MF_GRAYED;
            EnableMenuItem(hMenuMain, IDM_SAVEALL, mf_state);
            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_CLOSEWINDOW, mf_state);
            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_INDENT, (mf_state == MF_ENABLED &&
                selstart != selend) ? MF_ENABLED : MF_GRAYED);
            EnableMenuItem(hMenuMain, IDM_UNINDENT, (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_BROWSETO,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 (!making && !IsSpecialWindow(win))
            {
                if (!FindItemByWind(win))
                    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 (numberofdrawwindows)
                mf_state = MF_ENABLED;
			EnableMenuItem(hMenuMain, IDM_CLOSEALLWINDOWS, mf_state);
            EnableMenuItem(hMenuMain, IDM_CASCADE, mf_state);
            EnableMenuItem(hMenuMain, IDM_TILEHORIZ, mf_state);
            EnableMenuItem(hMenuMain, IDM_TILEVERT, mf_state);
            EnableMenuItem(hMenuMain, IDM_ARRANGE, mf_state);
			EnableMenuItem(hMenuMain, IDM_NEWWINDOW, mf_state);
   	        EnableMenuItem(hMenuMain, IDM_SAVEALL, mf_state);
			
            EnableMenuItem(hMenuMain, IDM_NEWPROJECT, MF_ENABLED);
            EnableMenuItem(hMenuMain, IDM_VIEWPROJECT, MF_ENABLED);
            mf_state = MF_GRAYED;
            if (projectList)
                mf_state = MF_ENABLED;
            EnableMenuItem(hMenuMain, IDM_STARTDEBUGGING, mf_state);
            EnableMenuItem(hMenuMain, IDM_STOPDEBUGGING, mf_state);
            mf_state = MF_GRAYED;
			if (uState == notDebugging && projectList && !making)
                mf_state = MF_ENABLED;
            EnableMenuItem(hMenuMain, IDM_RUNNODEBUG, mf_state);
            if (making)
                mf_state = MF_GRAYED;
            EnableMenuItem(hMenuMain, IDM_CLOSEWS, mf_state);
            EnableMenuItem(hMenuMain, IDM_GENMAKE, mf_state);
            EnableMenuItem(hMenuMain, IDM_MAKE, mf_state);
            EnableMenuItem(hMenuMain, IDM_BUILDALL, mf_state);
            EnableMenuItem(hMenuMain, IDM_BUILDSELECTED, mf_state);
            if (projectList && making)
                mf_state = MF_ENABLED;
            else
                mf_state = MF_GRAYED;
            EnableMenuItem(hMenuMain, IDM_STOPBUILD, mf_state);

            if (IsWindow(win))
			{
                EnableMenuItem(hMenuMain, IDM_UNDO, SendMessage(win, EM_CANUNDO,
                    0, 0) ? MF_ENABLED : MF_GRAYED);
                EnableMenuItem(hMenuMain, IDM_REDO, SendMessage(win, EM_CANREDO,
                    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_RUNTO, mf_state);
            EnableMenuItem(hMenuMain, IDM_SCROLLTOBP, mf_state);
            EnableMenuItem(hMenuMain, IDM_VIEWASM, mf_state);
            EnableMenuItem(hMenuMain, IDM_VIEWDUMP, mf_state);
            EnableMenuItem(hMenuMain, IDM_VIEWREGISTER, mf_state);
            EnableMenuItem(hMenuMain, IDM_VIEWSTACK, mf_state);
            EnableMenuItem(hMenuMain, IDM_VIEWWATCH, mf_state);
            EnableMenuItem(hMenuMain, IDM_VIEWTHREAD, mf_state);
            mf_state = uState == Running ? MF_ENABLED : MF_GRAYED;
            EnableMenuItem(hMenuMain, IDM_STOP, mf_state);
            //         mf_state = uState == atBreakpoint || uState == atException ? MF_ENABLED : MF_GRAYED ;
            //         EnableMenuItem(hMenuMain,IDM_HBREAK, mf_state ) ;

            mf_state = szHelpPath[0] ? MF_ENABLED : MF_GRAYED;
            EnableMenuItem(hMenuMain, IDM_SPECIFIEDHELP, mf_state);
            return 0;

        case WM_SIZE:
            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 | SBT_OWNERDRAW, (LPARAM)
                "    ");

            rv = 0 ; //DefFrameProc(hwnd, hwndClient, iMessage, wParam, lParam);
            dmgrSizeFrame();
            return rv;
        case WM_TIMER:
			if (wParam == IDT_STARTING)
			{
				// i don't know if this one is necessary
	            KillTimer(hwnd, timerid);
				CreateMenuBitmaps();
				InsertBitmapsInMenu(hMenuMain);
				LoadFirstWorkspace();
				if (!restoredDocks)
				    dmgrSetInfo(initialIDs, initialDocks, INITIAL_DOCK_COUNT);
			} 
			else if (wParam == IDT_CLIENTCONTEXTMENU)
			{
				// this one is necessary because trying to do a trackpopupmenuex within
				// the WM_PARENTNOTIFY message didn't work out
	            HMENU menu = LoadMenu(hInstance, "WINDOWMENU");
	            HMENU popup = GetSubMenu(menu, 0);
				POINT pos;
				HWND win;
				if (!numberofdrawwindows)
				{
    	    	        EnableMenuItem(menu, IDM_CLOSEWINDOW, MF_GRAYED);
    	    	        EnableMenuItem(menu, IDM_CLOSEALLWINDOWS, MF_GRAYED);
    	    	        EnableMenuItem(menu, IDM_SAVEALL, MF_GRAYED);
    	    	        EnableMenuItem(menu, IDM_TILEHORIZ, MF_GRAYED);
    	    	        EnableMenuItem(menu, IDM_TILEVERT, MF_GRAYED);
    	    	        EnableMenuItem(menu, IDM_CASCADE, MF_GRAYED);
    	    	        EnableMenuItem(menu, IDM_ARRANGE, MF_GRAYED);
    	    	        EnableMenuItem(menu, IDM_WINDOW_MORE, MF_GRAYED);
    	    	        EnableMenuItem(menu, IDM_NEWWINDOW, MF_GRAYED);
					
				} 
				else
				{
		            win = (HWND)SendMessage(hwndClient, WM_MDIGETACTIVE, 0, 0);
	    	    	if (!IsWindow(win) || IsSpecialWindow(win))
    	    	        EnableMenuItem(menu, IDM_CLOSEWINDOW, MF_GRAYED);
				}
            	GetCursorPos(&pos);
	            KillTimer(hwnd, timerid);
				InsertBitmapsInMenu(popup);
	            TrackPopupMenuEx(popup, TPM_BOTTOMALIGN | TPM_LEFTBUTTON, pos.x,
	                pos.y, hwndFrame, NULL);
	            DestroyMenu(menu);
			}
			
			else if (wParam == IDT_STOPPING)
			{
				// This one is necessary to give the debugger time to stop
	            if (uState != notDebugging || making)
    	            return 0;
	            PostMessage(hwnd, WM_CLOSE, 0, 0);
	            KillTimer(hwnd, timerid);
			} else
				KillTimer(hwnd, timerid);
            break;
        case WM_CLOSE:
            if (uState != notDebugging)
            {
                if (ExtendedMessageBox("Debugger", MB_YESNO, 
                    "Closing the editor will end your debug session.\r\nDo you wish to continue?")
                    != 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, IDT_STOPPING, 500, 0);
                return 0;
            }
            if (making)
            {
                if (ExtendedMessageBox("Build", MB_YESNO, 
                    "Closing the editor will end your build.\r\nDo you wish to continue?") !=
                    IDYES)
                    return 0;
                SendMessage(hwnd, WM_COMMAND, IDM_STOPBUILD, 0);
                timerid = SetTimer(hwnd, IDT_STOPPING, 500, 0);
                return 0;
            }
            if (QuerySaveAll() == IDCANCEL)
                return 0;
            MRUToProfile(0);
            MRUToProfile(1);
            MRDToProfile();
			ExternalToolsToProfile();
            SaveDocksToRegistry();
            SaveCurrentWorkspace();
            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)
{
    static char buf[256];
    SPLASH splash;

    sprintf(buf, "Version %s", CCIDE_STRING_VERSION);
    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 = TRUE; /* Topmost flag                  */
    splash.bWait = FALSE; /* Wait-end flag                 */
    splash.bAbout = FALSE; /* About box */
    splash.iPosX = 0; /* X position                    */
    splash.iPosY = 0; /* Y position                    */
    splash.lpszVersion = buf;

    SplashScreen(&splash);
}

//-------------------------------------------------------------------------

void doAbout(void)
{
    static char buf[256];
    SPLASH splash;

    sprintf(buf, "Version %s", CCIDE_STRING_VERSION);
    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.bCentered = TRUE; /* Centered-on-screen flag       */
    splash.bTopmost = FALSE; /* Topmost flag                  */
    splash.bWait = FALSE; /* Wait-end flag                 */
    splash.bAbout = TRUE; /* About box */
    splash.iPosX = 0; /* X position                    */
    splash.iPosY = 0; /* Y position                    */
    splash.lpszVersion = buf;
    splash.lpszButtonTitle = "Close";
    splash.bPos.left = 120;
    splash.bPos.top = 180;
    splash.bPos.right = 220;
    splash.bPos.bottom = 210;

    SplashScreen(&splash);
}

//-------------------------------------------------------------------------

LRESULT CALLBACK CursorHookProc(int code, int wParam, int lParam)
{
    CWPRETSTRUCT *s = (CWPRETSTRUCT*)lParam;
    if (s->message == WM_SETCURSOR)
    {
        if (programBusy > 0)
            SetCursor(hCursHourglass);
    }
    return CallNextHookEx(hCursHook, code, wParam, lParam);
}

//-------------------------------------------------------------------------

int IsBusyMessage(MSG *msg)
{
    int rv = 0;
    if (programBusy <= 0)
        return 0;
    switch (msg->message)
    {
        case WM_LBUTTONDOWN:
        case WM_LBUTTONUP:
        case WM_MBUTTONDOWN:
        case WM_MBUTTONUP:
        case WM_RBUTTONDOWN:
        case WM_RBUTTONUP:
        case WM_LBUTTONDBLCLK:
        case WM_MBUTTONDBLCLK:
        case WM_RBUTTONDBLCLK:
        case WM_KEYUP:
        case WM_KEYDOWN:
        case WM_CHAR:
            rv = 1;
            break;
    }
    return rv;
}

void HandleMessage(MSG *msg)
{
    if (!IsBusyMessage(msg))
    {
        if (!TranslateMDISysAccel(hwndClient, msg))
        {
            if (!TranslateAccelerator(hwndFrame, hAccel, msg))
            {
                if (!IsWindow(hwndFind) || !IsDialogMessage(hwndFind, msg))
                {
                    if (!IsWindow(hwndBookmark) || !IsDialogMessage
                        (hwndBookmark, msg))
                    {
                        TranslateMessage(msg);
						switch(msg->message)
						{
							case WM_LBUTTONDOWN:
							case WM_RBUTTONDOWN:
							case WM_MBUTTONDOWN:
							case WM_KEYDOWN:
							    SendMessage(hwndStatus, SB_SETTEXT, 0 | SBT_NOBORDERS | SBT_OWNERDRAW, (LPARAM)"    ");
								break;
						}
                        DispatchMessage(msg);
                    }
                }
            }
        }
    }
}
void WaitTillReady(void)
{
	MSG msg;
	while (PeekMessage(&msg, NULL, 0,0, PM_REMOVE))
		   HandleMessage(&msg);
}
//-------------------------------------------------------------------------

int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpszCmdLine,
    int nCmdShow)
{
	char buf[260], buf2[260], *p;
    HANDLE hsub;
    DWORD val;
    MSG msg;
    RECT r;
	DWORD hand;
    WINDOWPLACEMENT wp;
	threadMain = GetCurrentThreadId();
    hInstance = hInst;
//    if (FindWindow(szFrameClassName,0)) {
//		return 0;
//	}
    _control87(MCW_EM, MCW_EM); 
        // so we don't get problems reading unused FP reg values
    InitCommonControls();
    editLib = LoadLibrary("riched32.dll"); /* Version 1.0 */
   alloc_init();
    hCursArrow = LoadCursor(0, IDC_ARROW);
    hCursHourglass = LoadCursor(0, IDC_WAIT);
    //   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();
		RegisterJumpListWindow();
    }
    //   SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_LOWEST) ;
    restoreColors();
	GetModuleFileName(0,buf, 260);
	p =strrchr(buf,'\\');
	if (p)
	{
		*p = 0;
	}
	strcpy(szInstallPath, buf);
	p =strrchr(szInstallPath,'\\');
	if (p)
	{
		*p = 0;
	}
	strcat(buf,"\\ccide.cfg");
	strcpy(buf2, szInstallPath);
    GetPrivateProfileString("Init", "InstallPath", buf2, szInstallPath, 260,
            buf);
	
    hMenuMain = LoadMenu(hInstance, "MAINMENU");
    hsub = GetSubMenu(hMenuMain, WINDOW_MENU_OFFSET);
    WindowItemCount = GetMenuItemCount(hsub);
    hAccel = LoadAccelerators(hInstance, "MAINACCELERATORS");

    projectSem = CreateSemaphore(0, 1, 1, 0);

    if (!RestorePlacementFromRegistry(&wp))
    {
        wp.rcNormalPosition.left = wp.rcNormalPosition.right = CW_USEDEFAULT;
        wp.rcNormalPosition.top = wp.rcNormalPosition.bottom = CW_USEDEFAULT;
    }
    else
    {
        wp.rcNormalPosition.right -= wp.rcNormalPosition.left;
        wp.rcNormalPosition.bottom -= wp.rcNormalPosition.top;
    }
    hwndFrame = CreateWindowEx(0, szFrameClassName, "CC386 IDE",
        WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
        wp.rcNormalPosition.left, wp.rcNormalPosition.top,
        wp.rcNormalPosition.right, wp.rcNormalPosition.bottom, 0, hMenuMain,
        hInstance, 0);
    InvalidateRect(hwndFrame, 0, 0);
    readytodraw = FALSE;
    ShowWindow(hwndFrame, SW_SHOWNORMAL);
    readytodraw = TRUE;
//    doSplash();

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

    InitHelp();
    #ifdef HBREAK
        hbpInit();
    #endif 
    hCursHook = SetWindowsHookEx(WH_CALLWNDPROCRET, (HOOKPROC)CursorHookProc, 0,
        GetCurrentThreadId());
    while (GetMessage(&msg, 0, 0, 0) > 0)
    {
		HandleMessage(&msg);
    }
    saveColors();
    FreeLibrary(editLib);
    RundownHelp();
    return msg.wParam;
}
