blitz3d/debugger/mainframe.cpp

326 lines
6.9 KiB
C++

#include "stdafx.h"
#include "mainframe.h"
#include "resource.h"
#include "debuggerapp.h"
#include "prefs.h"
#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( char *p=strrchr(file,'/') ) file=p+1;
if( 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;
}