Files
Michael Fabian 'Xaymar' Dirks f713369a01 debugger: Formatting;
2019-01-18 17:04:34 +01:00

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;
}