339 lines
7.1 KiB
C++
339 lines
7.1 KiB
C++
|
|
#include "mainframe.hpp"
|
|
#include "debuggerapp.hpp"
|
|
#include "prefs.hpp"
|
|
#include "resource.hpp"
|
|
#include "stdafx.hpp"
|
|
|
|
#define WM_IDLEUPDATECMDUI 0x0363 // wParam == bDisableIfNoHandler
|
|
|
|
enum { WM_STOP = WM_USER + 1, WM_RUN, WM_END };
|
|
|
|
enum { STARTING, RUNNING, STOPPED, ENDING };
|
|
|
|
IMPLEMENT_DYNAMIC(MainFrame, CFrameWnd)
|
|
BEGIN_MESSAGE_MAP(MainFrame, CFrameWnd)
|
|
ON_WM_CREATE()
|
|
ON_WM_SIZE()
|
|
ON_WM_CLOSE()
|
|
ON_WM_WINDOWPOSCHANGING()
|
|
|
|
ON_COMMAND(ID_STOP, cmdStop)
|
|
ON_COMMAND(ID_RUN, cmdRun)
|
|
ON_COMMAND(ID_STEPOVER, cmdStepOver)
|
|
ON_COMMAND(ID_STEPINTO, cmdStepInto)
|
|
ON_COMMAND(ID_STEPOUT, cmdStepOut)
|
|
ON_COMMAND(ID_END, cmdEnd)
|
|
|
|
ON_UPDATE_COMMAND_UI(ID_STOP, updateCmdUI)
|
|
ON_UPDATE_COMMAND_UI(ID_RUN, updateCmdUI)
|
|
ON_UPDATE_COMMAND_UI(ID_STEPOVER, updateCmdUI)
|
|
ON_UPDATE_COMMAND_UI(ID_STEPINTO, updateCmdUI)
|
|
ON_UPDATE_COMMAND_UI(ID_STEPOUT, updateCmdUI)
|
|
ON_UPDATE_COMMAND_UI(ID_END, updateCmdUI)
|
|
|
|
END_MESSAGE_MAP()
|
|
|
|
MainFrame::MainFrame() : state(STARTING), step_level(-1), cur_pos(0), cur_file(0) {}
|
|
|
|
MainFrame::~MainFrame()
|
|
{
|
|
map<const char*, SourceFile*>::iterator it;
|
|
for (it = files.begin(); it != files.end(); ++it)
|
|
delete it->second;
|
|
}
|
|
|
|
int MainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
|
|
{
|
|
CFrameWnd::OnCreate(lpCreateStruct);
|
|
|
|
prefs.open();
|
|
|
|
string tb = prefs.homeDir + "/cfg/dbg_toolbar.bmp";
|
|
|
|
//Toolbar
|
|
HBITMAP toolbmp = (HBITMAP)LoadImage(0, tb.c_str(), IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_LOADMAP3DCOLORS);
|
|
|
|
BITMAP bm;
|
|
GetObject(toolbmp, sizeof(bm), &bm);
|
|
|
|
int n = 0;
|
|
UINT toolbuts[] = {ID_STOP, ID_RUN, ID_STEPOVER, ID_STEPINTO, ID_STEPOUT, ID_END};
|
|
int toolcnt = sizeof(toolbuts) / sizeof(UINT);
|
|
for (int k = 0; k < toolcnt; ++k)
|
|
if (toolbuts[k] != ID_SEPARATOR)
|
|
++n;
|
|
|
|
SIZE imgsz, butsz;
|
|
imgsz.cx = bm.bmWidth / n;
|
|
imgsz.cy = bm.bmHeight;
|
|
butsz.cx = imgsz.cx + 7;
|
|
butsz.cy = imgsz.cy + 6;
|
|
|
|
toolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_TOOLTIPS);
|
|
toolBar.SetBitmap(toolbmp);
|
|
toolBar.SetSizes(butsz, imgsz);
|
|
toolBar.SetButtons(toolbuts, toolcnt);
|
|
|
|
//Tabber
|
|
tabber.Create(WS_VISIBLE | WS_CHILD | TCS_HOTTRACK, CRect(0, 0, 0, 0), this, 1);
|
|
tabber.SetFont(&prefs.tabsFont);
|
|
|
|
//Second tabber
|
|
tabber2.Create(WS_VISIBLE | WS_CHILD | TCS_HOTTRACK, CRect(0, 0, 0, 0), this, 2);
|
|
tabber2.SetFont(&prefs.tabsFont);
|
|
|
|
//Debug Log
|
|
debug_log.Create(WS_CHILD | WS_HSCROLL | WS_VSCROLL | ES_NOHIDESEL | ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL,
|
|
CRect(0, 0, 0, 0), &tabber, 1);
|
|
tabber.insert(0, &debug_log, "Debug log");
|
|
|
|
//Debug trees
|
|
locals_tree.Create(WS_VISIBLE | WS_CHILD | TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS, CRect(0, 0, 0, 0),
|
|
&tabber2, 3);
|
|
|
|
globals_tree.Create(WS_VISIBLE | WS_CHILD | TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS, CRect(0, 0, 0, 0),
|
|
&tabber2, 3);
|
|
|
|
consts_tree.Create(WS_VISIBLE | WS_CHILD | TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS, CRect(0, 0, 0, 0),
|
|
&tabber2, 3);
|
|
|
|
tabber2.insert(0, &locals_tree, "Locals");
|
|
tabber2.insert(1, &globals_tree, "Globals");
|
|
tabber2.insert(2, &consts_tree, "Consts");
|
|
tabber2.setCurrent(0);
|
|
|
|
setState(STARTING);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void MainFrame::setState(int n)
|
|
{
|
|
state = n;
|
|
SendMessageToDescendants(WM_IDLEUPDATECMDUI, (WPARAM)TRUE, 0, TRUE, TRUE);
|
|
if (shouldRun()) {
|
|
if (HWND app = ::FindWindow("Blitz Runtime Class", 0)) {
|
|
::SetActiveWindow(app);
|
|
}
|
|
} else {
|
|
SetActiveWindow();
|
|
}
|
|
}
|
|
|
|
void MainFrame::OnClose()
|
|
{
|
|
cmdEnd();
|
|
}
|
|
|
|
void MainFrame::OnSize(UINT type, int sw, int sh)
|
|
{
|
|
CFrameWnd::OnSize(type, sw, sh);
|
|
|
|
CRect r, t;
|
|
GetClientRect(&r);
|
|
int x = r.left, y = r.top, w = r.Width(), h = r.Height();
|
|
|
|
toolBar.GetWindowRect(&t);
|
|
y += t.Height();
|
|
h -= t.Height();
|
|
|
|
tabber.MoveWindow(x, y, w - 240, h);
|
|
|
|
tabber2.MoveWindow(x + w - 240, y, 240, h);
|
|
}
|
|
|
|
void MainFrame::setRuntime(void* mod, void* env)
|
|
{
|
|
consts_tree.reset((Environ*)env);
|
|
globals_tree.reset((Module*)mod, (Environ*)env);
|
|
locals_tree.reset((Environ*)env);
|
|
}
|
|
|
|
void MainFrame::showCurStmt()
|
|
{
|
|
if (!cur_file)
|
|
return;
|
|
|
|
SourceFile* t = sourceFile(cur_file);
|
|
|
|
int row = (cur_pos >> 16) & 0xffff, col = cur_pos & 0xffff;
|
|
t->highLight(row, col);
|
|
|
|
globals_tree.refresh();
|
|
locals_tree.refresh();
|
|
}
|
|
|
|
void MainFrame::debugRun()
|
|
{
|
|
setState(RUNNING);
|
|
}
|
|
|
|
void MainFrame::debugStop()
|
|
{
|
|
step_level = locals_tree.size();
|
|
setState(STOPPED);
|
|
showCurStmt();
|
|
}
|
|
|
|
void MainFrame::debugStmt(int pos, const char* file)
|
|
{
|
|
cur_pos = pos;
|
|
cur_file = file;
|
|
|
|
if (shouldRun())
|
|
return;
|
|
|
|
::PostMessage(0, WM_STOP, 0, 0);
|
|
}
|
|
|
|
void MainFrame::debugEnter(void* frame, void* env, const char* func)
|
|
{
|
|
locals_tree.pushFrame(frame, env, func);
|
|
|
|
if (locals_tree.size() > 1)
|
|
return;
|
|
|
|
globals_tree.refresh();
|
|
locals_tree.refresh();
|
|
|
|
setState(RUNNING);
|
|
}
|
|
|
|
void MainFrame::debugLeave()
|
|
{
|
|
locals_tree.popFrame();
|
|
}
|
|
|
|
void MainFrame::debugMsg(const char* msg, bool serious)
|
|
{
|
|
if (serious) {
|
|
::MessageBox(0, msg, "Runtime Error", MB_OK | MB_ICONWARNING | MB_TOPMOST | MB_SETFOREGROUND);
|
|
} else {
|
|
::MessageBox(0, msg, "Runtime Message", MB_OK | MB_ICONINFORMATION | MB_TOPMOST | MB_SETFOREGROUND);
|
|
}
|
|
}
|
|
|
|
void MainFrame::debugLog(const char* msg)
|
|
{
|
|
debug_log.ReplaceSel(msg);
|
|
debug_log.ReplaceSel("\n");
|
|
tabber.setCurrent(0);
|
|
setState(state);
|
|
}
|
|
|
|
void MainFrame::debugSys(void* m) {}
|
|
|
|
void MainFrame::cmdStop()
|
|
{
|
|
::PostMessage(0, WM_STOP, 0, 0);
|
|
}
|
|
|
|
void MainFrame::cmdRun()
|
|
{
|
|
step_level = -1;
|
|
::PostMessage(0, WM_RUN, 0, 0);
|
|
}
|
|
|
|
void MainFrame::cmdEnd()
|
|
{
|
|
::PostMessage(0, WM_END, 0, 0);
|
|
setState(ENDING);
|
|
}
|
|
|
|
void MainFrame::cmdStepOver()
|
|
{
|
|
::PostMessage(0, WM_RUN, 0, 0);
|
|
}
|
|
|
|
void MainFrame::cmdStepInto()
|
|
{
|
|
step_level = locals_tree.size() + 1;
|
|
::PostMessage(0, WM_RUN, 0, 0);
|
|
}
|
|
|
|
void MainFrame::cmdStepOut()
|
|
{
|
|
step_level = locals_tree.size() - 1;
|
|
::PostMessage(0, WM_RUN, 0, 0);
|
|
}
|
|
|
|
SourceFile* MainFrame::sourceFile(const char* file)
|
|
{
|
|
if (!file)
|
|
file = "<unknown>";
|
|
|
|
map<const char*, SourceFile*>::const_iterator it = files.find(file);
|
|
|
|
if (it != files.end()) {
|
|
tabber.setCurrent(file_tabs[file]);
|
|
return it->second;
|
|
}
|
|
|
|
//crete new source file
|
|
SourceFile* t = new SourceFile();
|
|
|
|
it = files.insert(make_pair(file, t)).first;
|
|
|
|
int tab = files.size();
|
|
|
|
t->Create(WS_CHILD | WS_HSCROLL | WS_VSCROLL | ES_NOHIDESEL | ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL,
|
|
CRect(0, 0, 0, 0), &tabber, 1);
|
|
|
|
if (FILE* f = fopen(file, "rb")) {
|
|
fseek(f, 0, SEEK_END);
|
|
int sz = ftell(f);
|
|
fseek(f, 0, SEEK_SET);
|
|
char* buf = new char[sz + 1];
|
|
fread(buf, sz, 1, f);
|
|
buf[sz] = 0;
|
|
t->ReplaceSel(buf);
|
|
delete[] buf;
|
|
fclose(f);
|
|
}
|
|
|
|
file_tabs.insert(make_pair(file, tab));
|
|
|
|
if (const char* p = strrchr(file, '/'))
|
|
file = p + 1;
|
|
if (const char* p = strrchr(file, '\\'))
|
|
file = p + 1;
|
|
tabber.insert(tab, t, file);
|
|
|
|
tabber.setCurrent(tab);
|
|
|
|
return t;
|
|
}
|
|
|
|
void MainFrame::updateCmdUI(CCmdUI* ui)
|
|
{
|
|
if (state != RUNNING && state != STOPPED) {
|
|
ui->Enable(false);
|
|
return;
|
|
}
|
|
switch (ui->m_nID) {
|
|
case ID_STOP:
|
|
ui->Enable(shouldRun());
|
|
break;
|
|
case ID_RUN:
|
|
case ID_STEPOVER:
|
|
case ID_STEPINTO:
|
|
case ID_STEPOUT:
|
|
ui->Enable(!shouldRun());
|
|
break;
|
|
case ID_END:
|
|
ui->Enable(true);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void MainFrame::OnWindowPosChanging(WINDOWPOS* pos)
|
|
{
|
|
RECT rect;
|
|
SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0);
|
|
|
|
pos->x = rect.left;
|
|
pos->cx = rect.right - pos->x;
|
|
pos->cy = rect.bottom - pos->y;
|
|
}
|