mainframe.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. #include "stdafx.h"
  2. #include "mainframe.h"
  3. #include "resource.h"
  4. #include "debuggerapp.h"
  5. #include "prefs.h"
  6. #define WM_IDLEUPDATECMDUI 0x0363 // wParam == bDisableIfNoHandler
  7. enum{
  8. WM_STOP=WM_USER+1,WM_RUN,WM_END
  9. };
  10. enum{
  11. STARTING,RUNNING,STOPPED,ENDING
  12. };
  13. IMPLEMENT_DYNAMIC( MainFrame,CFrameWnd )
  14. BEGIN_MESSAGE_MAP( MainFrame,CFrameWnd )
  15. ON_WM_CREATE()
  16. ON_WM_SIZE()
  17. ON_WM_CLOSE()
  18. ON_WM_WINDOWPOSCHANGING()
  19. ON_COMMAND( ID_STOP,cmdStop )
  20. ON_COMMAND( ID_RUN,cmdRun )
  21. ON_COMMAND( ID_STEPOVER,cmdStepOver )
  22. ON_COMMAND( ID_STEPINTO,cmdStepInto )
  23. ON_COMMAND( ID_STEPOUT,cmdStepOut )
  24. ON_COMMAND( ID_END,cmdEnd )
  25. ON_UPDATE_COMMAND_UI( ID_STOP,updateCmdUI )
  26. ON_UPDATE_COMMAND_UI( ID_RUN,updateCmdUI )
  27. ON_UPDATE_COMMAND_UI( ID_STEPOVER,updateCmdUI )
  28. ON_UPDATE_COMMAND_UI( ID_STEPINTO,updateCmdUI )
  29. ON_UPDATE_COMMAND_UI( ID_STEPOUT,updateCmdUI )
  30. ON_UPDATE_COMMAND_UI( ID_END,updateCmdUI )
  31. END_MESSAGE_MAP()
  32. MainFrame::MainFrame():state(STARTING),step_level(-1),cur_pos(0),cur_file(0){
  33. }
  34. MainFrame::~MainFrame(){
  35. map<const char*,SourceFile*>::iterator it;
  36. for( it=files.begin();it!=files.end();++it ) delete it->second;
  37. }
  38. int MainFrame::OnCreate( LPCREATESTRUCT lpCreateStruct ){
  39. CFrameWnd::OnCreate( lpCreateStruct );
  40. prefs.open();
  41. string tb=prefs.homeDir+"/cfg/dbg_toolbar.bmp";
  42. //Toolbar
  43. HBITMAP toolbmp=(HBITMAP)LoadImage(
  44. 0,tb.c_str(),IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_LOADMAP3DCOLORS );
  45. BITMAP bm;
  46. GetObject( toolbmp,sizeof(bm),&bm );
  47. int n=0;
  48. UINT toolbuts[]={ ID_STOP,ID_RUN,ID_STEPOVER,ID_STEPINTO,ID_STEPOUT,ID_END };
  49. int toolcnt=sizeof(toolbuts)/sizeof(UINT);
  50. for( int k=0;k<toolcnt;++k ) if( toolbuts[k]!=ID_SEPARATOR ) ++n;
  51. SIZE imgsz,butsz;
  52. imgsz.cx=bm.bmWidth/n;imgsz.cy=bm.bmHeight;
  53. butsz.cx=imgsz.cx+7;butsz.cy=imgsz.cy+6;
  54. toolBar.CreateEx( this,TBSTYLE_FLAT,WS_CHILD|WS_VISIBLE|CBRS_TOP|CBRS_TOOLTIPS );
  55. toolBar.SetBitmap( toolbmp );
  56. toolBar.SetSizes( butsz,imgsz );
  57. toolBar.SetButtons( toolbuts,toolcnt );
  58. //Tabber
  59. tabber.Create(
  60. WS_VISIBLE|WS_CHILD|
  61. TCS_HOTTRACK,
  62. CRect( 0,0,0,0 ),this,1 );
  63. tabber.SetFont( &prefs.tabsFont );
  64. //Second tabber
  65. tabber2.Create(
  66. WS_VISIBLE|WS_CHILD|
  67. TCS_HOTTRACK,
  68. CRect( 0,0,0,0 ),this,2 );
  69. tabber2.SetFont( &prefs.tabsFont );
  70. //Debug Log
  71. debug_log.Create(
  72. WS_CHILD|WS_HSCROLL|WS_VSCROLL|
  73. ES_NOHIDESEL|ES_MULTILINE|ES_AUTOHSCROLL|ES_AUTOVSCROLL,
  74. CRect( 0,0,0,0 ),&tabber,1 );
  75. tabber.insert( 0,&debug_log,"Debug log" );
  76. //Debug trees
  77. locals_tree.Create(
  78. WS_VISIBLE|WS_CHILD|
  79. TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS,
  80. CRect( 0,0,0,0 ),&tabber2,3 );
  81. globals_tree.Create(
  82. WS_VISIBLE|WS_CHILD|
  83. TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS,
  84. CRect( 0,0,0,0 ),&tabber2,3 );
  85. consts_tree.Create(
  86. WS_VISIBLE|WS_CHILD|
  87. TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS,
  88. CRect( 0,0,0,0 ),&tabber2,3 );
  89. tabber2.insert( 0,&locals_tree,"Locals" );
  90. tabber2.insert( 1,&globals_tree,"Globals" );
  91. tabber2.insert( 2,&consts_tree,"Consts" );
  92. tabber2.setCurrent(0);
  93. setState( STARTING );
  94. return 0;
  95. }
  96. void MainFrame::setState( int n ){
  97. state=n;
  98. SendMessageToDescendants( WM_IDLEUPDATECMDUI,(WPARAM)TRUE,0,TRUE,TRUE );
  99. if( shouldRun() ){
  100. if( HWND app=::FindWindow( "Blitz Runtime Class",0 ) ){
  101. ::SetActiveWindow( app );
  102. }
  103. }else{
  104. SetActiveWindow();
  105. }
  106. }
  107. void MainFrame::OnClose(){
  108. cmdEnd();
  109. }
  110. void MainFrame::OnSize( UINT type,int sw,int sh ){
  111. CFrameWnd::OnSize( type,sw,sh );
  112. CRect r,t;GetClientRect( &r );
  113. int x=r.left,y=r.top,w=r.Width(),h=r.Height();
  114. toolBar.GetWindowRect( &t );y+=t.Height();h-=t.Height();
  115. tabber.MoveWindow( x,y,w-240,h );
  116. tabber2.MoveWindow( x+w-240,y,240,h );
  117. }
  118. void MainFrame::setRuntime( void *mod,void *env ){
  119. consts_tree.reset( (Environ*)env );
  120. globals_tree.reset( (Module*)mod,(Environ*)env );
  121. locals_tree.reset( (Environ*)env );
  122. }
  123. void MainFrame::showCurStmt(){
  124. if( !cur_file ) return;
  125. SourceFile *t=sourceFile(cur_file);
  126. int row=(cur_pos>>16)&0xffff,col=cur_pos&0xffff;
  127. t->highLight( row,col );
  128. globals_tree.refresh();
  129. locals_tree.refresh();
  130. }
  131. void MainFrame::debugRun(){
  132. setState( RUNNING );
  133. }
  134. void MainFrame::debugStop(){
  135. step_level=locals_tree.size();
  136. setState( STOPPED );
  137. showCurStmt();
  138. }
  139. void MainFrame::debugStmt( int pos,const char *file ){
  140. cur_pos=pos;
  141. cur_file=file;
  142. if( shouldRun() ) return;
  143. ::PostMessage( 0,WM_STOP,0,0 );
  144. }
  145. void MainFrame::debugEnter( void *frame,void *env,const char *func ){
  146. locals_tree.pushFrame( frame,env,func );
  147. if( locals_tree.size()>1 ) return;
  148. globals_tree.refresh();
  149. locals_tree.refresh();
  150. setState( RUNNING );
  151. }
  152. void MainFrame::debugLeave(){
  153. locals_tree.popFrame();
  154. }
  155. void MainFrame::debugMsg( const char *msg,bool serious ){
  156. if( serious ){
  157. ::MessageBox( 0,msg,"Runtime Error",MB_OK|MB_ICONWARNING|MB_TOPMOST|MB_SETFOREGROUND );
  158. }else{
  159. ::MessageBox( 0,msg,"Runtime Message",MB_OK|MB_ICONINFORMATION|MB_TOPMOST|MB_SETFOREGROUND );
  160. }
  161. }
  162. void MainFrame::debugLog( const char *msg ){
  163. debug_log.ReplaceSel( msg );
  164. debug_log.ReplaceSel( "\n" );
  165. tabber.setCurrent( 0 );
  166. setState( state );
  167. }
  168. void MainFrame::debugSys( void *m ){
  169. }
  170. void MainFrame::cmdStop(){
  171. ::PostMessage( 0,WM_STOP,0,0 );
  172. }
  173. void MainFrame::cmdRun(){
  174. step_level=-1;
  175. ::PostMessage( 0,WM_RUN,0,0 );
  176. }
  177. void MainFrame::cmdEnd(){
  178. ::PostMessage( 0,WM_END,0,0 );
  179. setState( ENDING );
  180. }
  181. void MainFrame::cmdStepOver(){
  182. ::PostMessage( 0,WM_RUN,0,0 );
  183. }
  184. void MainFrame::cmdStepInto(){
  185. step_level=locals_tree.size()+1;
  186. ::PostMessage( 0,WM_RUN,0,0 );
  187. }
  188. void MainFrame::cmdStepOut(){
  189. step_level=locals_tree.size()-1;
  190. ::PostMessage( 0,WM_RUN,0,0 );
  191. }
  192. SourceFile *MainFrame::sourceFile(const char *file){
  193. if( !file ) file="<unknown>";
  194. map<const char*,SourceFile*>::const_iterator it=files.find( file );
  195. if( it!=files.end() ){
  196. tabber.setCurrent( file_tabs[file] );
  197. return it->second;
  198. }
  199. //crete new source file
  200. SourceFile *t=new SourceFile();
  201. it=files.insert( make_pair(file,t) ).first;
  202. int tab=files.size();
  203. t->Create(
  204. WS_CHILD|WS_HSCROLL|WS_VSCROLL|
  205. ES_NOHIDESEL|ES_MULTILINE|ES_AUTOHSCROLL|ES_AUTOVSCROLL,
  206. CRect( 0,0,0,0 ),&tabber,1 );
  207. if( FILE *f=fopen( file,"rb" ) ){
  208. fseek( f,0,SEEK_END );
  209. int sz=ftell( f );
  210. fseek( f,0,SEEK_SET );
  211. char *buf=new char[sz+1];
  212. fread( buf,sz,1,f );
  213. buf[sz]=0;
  214. t->ReplaceSel( buf );
  215. delete[] buf;
  216. fclose(f);
  217. }
  218. file_tabs.insert( make_pair(file,tab) );
  219. if( char *p=strrchr(file,'/') ) file=p+1;
  220. if( char *p=strrchr(file,'\\') ) file=p+1;
  221. tabber.insert( tab,t,file );
  222. tabber.setCurrent( tab );
  223. return t;
  224. }
  225. void MainFrame::updateCmdUI( CCmdUI *ui ){
  226. if( state!=RUNNING && state!=STOPPED ){
  227. ui->Enable( false );
  228. return;
  229. }
  230. switch( ui->m_nID ){
  231. case ID_STOP:
  232. ui->Enable( shouldRun() );
  233. break;
  234. case ID_RUN:
  235. case ID_STEPOVER:
  236. case ID_STEPINTO:
  237. case ID_STEPOUT:
  238. ui->Enable( !shouldRun() );
  239. break;
  240. case ID_END:
  241. ui->Enable( true );
  242. break;
  243. }
  244. }
  245. void MainFrame::OnWindowPosChanging( WINDOWPOS *pos ){
  246. RECT rect;
  247. SystemParametersInfo( SPI_GETWORKAREA,0,&rect,0 );
  248. pos->x=rect.left;
  249. pos->cx=rect.right-pos->x;
  250. pos->cy=rect.bottom-pos->y;
  251. }