fpmrun.inc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. {
  2. This file is part of the Free Pascal Integrated Development Environment
  3. Copyright (c) 1998 by Berczi Gabor
  4. Run menu entries
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$define MODIFIEDINDEBUG}
  12. function TIDEApp.CheckModifiedEditor:boolean;
  13. var
  14. PW,PPW : PSourceWindow;
  15. Checkmodified : boolean;
  16. begin
  17. Checkmodified:=false;
  18. PW:=FirstEditorWindow;
  19. PPW:=PW;
  20. while assigned(PW) do
  21. begin
  22. If PW^.HelpCtx=hcSourceWindow then
  23. begin
  24. if pw^.editor^.getmodified then
  25. if pw^.editor^.core^.getmodifytime > LastCompileTime then
  26. begin
  27. Checkmodified:=true;
  28. break;
  29. end;
  30. end;
  31. PW:=PSourceWindow(PW^.next);
  32. While assigned(PW) and (PW<>PPW) and (PW^.HelpCtx<>hcSourceWindow) do
  33. PW:=PSourceWindow(PW^.next);
  34. If PW=PPW then
  35. break;
  36. end;
  37. CheckModifiedEditor:=Checkmodified;
  38. end;
  39. function TIDEApp.AskRecompileIfModified:boolean;
  40. begin
  41. AskRecompileIfModified:=false;
  42. {$ifdef MODIFIEDINDEBUG}
  43. if not AskRecompileIfModifiedFlag then
  44. exit;
  45. if CheckModifiedEditor then
  46. begin
  47. if (MessageBox(#3+'You''ve edited a file, recompile the project?',nil,mfinformation+mfyesbutton+mfnobutton)=cmYes) then
  48. begin
  49. {$IFNDEF NODEBUG}
  50. if Assigned(Debugger) then
  51. begin
  52. if Debugger^.IsRunning then
  53. RestartingDebugger:=true;
  54. end;
  55. DoResetDebugger;
  56. {$ENDIF}
  57. DoRun;
  58. AskRecompileIfModified:=true;
  59. end
  60. else
  61. AskRecompileIfModifiedFlag:=false;
  62. end;
  63. {$endif MODIFIEDINDEBUG}
  64. end;
  65. procedure TIDEApp.DoStepOver;
  66. begin
  67. {$ifndef NODEBUG}
  68. if not assigned(Debugger) or Not Debugger^.HasExe then
  69. begin
  70. InitDebugger;
  71. if not assigned(Debugger) then
  72. begin
  73. NoDebugger;
  74. exit;
  75. end;
  76. end;
  77. if not Debugger^.IsRunning then
  78. Debugger^.StartTrace
  79. else
  80. begin
  81. if AskRecompileIfModified then
  82. exit;
  83. if InDisassemblyWindow then
  84. Debugger^.TraceNextI
  85. else
  86. Debugger^.TraceNext;
  87. end;
  88. {While (Debugger^.InvalidSourceLine and
  89. Debugger^.IsRunning and
  90. not Debugger^.error) do
  91. begin
  92. Inc(Debugger^.HiddenStepsCount);
  93. if InDisassemblyWindow then
  94. Debugger^.TraceNextI
  95. else
  96. Debugger^.TraceNext;
  97. end;}
  98. if Debugger^.IsRunning then
  99. Debugger^.AnnotateError;
  100. {$else NODEBUG}
  101. NoDebugger;
  102. {$endif NODEBUG}
  103. end;
  104. procedure TIDEApp.DoTraceInto;
  105. begin
  106. {$ifndef NODEBUG}
  107. if not assigned(Debugger) or Not Debugger^.HasExe then
  108. begin
  109. InitDebugger;
  110. if not assigned(Debugger) then
  111. begin
  112. NoDebugger;
  113. exit;
  114. end;
  115. end;
  116. if not debugger^.IsRunning then
  117. Debugger^.StartTrace
  118. else
  119. begin
  120. if AskRecompileIfModified then
  121. exit;
  122. if InDisassemblyWindow then
  123. Debugger^.TraceStepI
  124. else
  125. Debugger^.TraceStep;
  126. end;
  127. { I think we should not try to go deeper !
  128. if the source is not found PM }
  129. { in disassembly windows we should FK }
  130. if not(InDisassemblyWindow) then
  131. begin
  132. While (Debugger^.InvalidSourceLine and
  133. Debugger^.IsRunning and
  134. not Debugger^.error) do
  135. begin
  136. Inc(Debugger^.HiddenStepsCount);
  137. Debugger^.TraceNext;
  138. end;
  139. end;
  140. Debugger^.AnnotateError;
  141. {$else NODEBUG}
  142. NoDebugger;
  143. {$endif NODEBUG}
  144. end;
  145. procedure TIDEApp.DoContUntilReturn;
  146. begin
  147. {$ifndef NODEBUG}
  148. if not assigned(Debugger) or Not Debugger^.HasExe then
  149. begin
  150. InitDebugger;
  151. if not assigned(Debugger) then
  152. begin
  153. NoDebugger;
  154. exit;
  155. end;
  156. end;
  157. if not debugger^.IsRunning then
  158. Debugger^.Run
  159. else
  160. begin
  161. if AskRecompileIfModified then
  162. exit;
  163. Debugger^.UntilReturn;
  164. end;
  165. Debugger^.AnnotateError;
  166. {$else NODEBUG}
  167. NoDebugger;
  168. {$endif NODEBUG}
  169. end;
  170. procedure TIDEApp.DoRun;
  171. var
  172. RunDirect : boolean;
  173. oldcurrdir : string;
  174. s : shortstring;
  175. begin
  176. {$ifndef NODEBUG}
  177. if not assigned(Debugger) or not Debugger^.HasExe or not Debugger^.IsRunning then
  178. {$endif}
  179. begin
  180. if (not ExistsFile(ExeFile)) or (CompilationPhase<>cpDone) or
  181. NeedRecompile(cRun,false) or CheckModifiedEditor then
  182. begin
  183. DoCompile(cRun);
  184. if CompilationPhase<>cpDone then
  185. Exit;
  186. if not Status.IsExe then
  187. begin
  188. ErrorBox(msg_cannotrununit,nil);
  189. Exit;
  190. end;
  191. if IsLibrary then
  192. begin
  193. ErrorBox(msg_cannotrunlibrary,nil);
  194. Exit;
  195. end;
  196. end;
  197. if (EXEFile='') then
  198. begin
  199. ErrorBox(msg_nothingtorun,nil);
  200. Exit;
  201. end;
  202. s:=EXEFile;
  203. if not ExistsFile(ExeFile) then
  204. begin
  205. MsgParms[1].Ptr:=@s;
  206. ErrorBox(msg_invalidfilename,@MsgParms);
  207. Exit;
  208. end;
  209. RunDirect:=true;
  210. {$ifndef NODEBUG}
  211. { we use debugger if and only if there are active breakpoints
  212. AND the target is correct for debugging !! PM }
  213. if (ActiveBreakpoints or RestartingDebugger) and
  214. (target_info.shortname=source_info.shortname)
  215. then
  216. begin
  217. if not assigned(Debugger) or Not Debugger^.HasExe then
  218. InitDebugger;
  219. if assigned(Debugger) then
  220. begin
  221. if RestartingDebugger then
  222. begin
  223. RestartingDebugger:=false;
  224. Debugger^.StartTrace;
  225. end
  226. else
  227. Debugger^.Run;
  228. RunDirect:=false;
  229. {we are about to run debuger, AutoSave first}
  230. SaveCancelled:=false;
  231. AutoSave; {ignore result, ignore if canceled}
  232. end;
  233. end;
  234. {$endif ndef NODEBUG}
  235. if Not RunDirect then
  236. exit;
  237. {$I-}
  238. GetDir(0,oldcurrdir);
  239. chdir(GetRunDir);
  240. {$I+}
  241. EatIO;
  242. {$ifdef Unix}
  243. if (DebuggeeTTY<>'') then
  244. DoExecute(ExeFile,GetRunParameters,DebuggeeTTY,DebuggeeTTY,DebuggeeTTY,exNormal)
  245. else
  246. {$endif Unix}
  247. DoExecute(ExeFile,GetRunParameters,'','','',exNormal);
  248. {$I-}
  249. chdir(oldcurrdir);
  250. {$I+}
  251. EatIO;
  252. { In case we have something that the compiler touched }
  253. AskToReloadAllModifiedFiles;
  254. LastExitCode:=ExecuteResult;
  255. s:=EXEFile;
  256. If IOStatus<>0 then
  257. begin
  258. MsgParms[1].Ptr:=@s;
  259. MsgParms[2].long:=IOStatus;
  260. InformationBox(msg_programnotrundoserroris,@MsgParms);
  261. end
  262. else If LastExitCode<>0 then
  263. begin
  264. MsgParms[1].Ptr:=@s;
  265. MsgParms[2].long:=LastExitCode;
  266. InformationBox(msg_programfileexitedwithexitcode,@MsgParms);
  267. end;
  268. end
  269. {$ifndef NODEBUG}
  270. else
  271. begin
  272. if AskRecompileIfModified then
  273. exit;
  274. Debugger^.Continue;
  275. end;
  276. {$endif}
  277. ;
  278. end;
  279. procedure TIDEApp.UpdateRunMenu(DebuggeeRunning : boolean);
  280. var MenuItem : PMenuItem;
  281. begin
  282. MenuItem:=PAdvancedMenuBar(MenuBar)^.GetMenuItem(cmRun);
  283. if not assigned(MenuItem) then
  284. MenuItem:=PAdvancedMenuBar(MenuBar)^.GetMenuItem(cmContinue);
  285. if assigned(MenuItem) then
  286. begin
  287. If assigned(MenuItem^.Name) then
  288. DisposeStr(MenuItem^.Name);
  289. if DebuggeeRunning then
  290. begin
  291. MenuItem^.Name:=NewStr(menu_run_continue);
  292. MenuItem^.command:=cmContinue;
  293. end
  294. else
  295. begin
  296. MenuItem^.Name:=NewStr(menu_run_run);
  297. MenuItem^.command:=cmRun;
  298. end;
  299. end;
  300. MenuItem:=PAdvancedMenuBar(MenuBar)^.GetMenuItem(cmResetDebugger);
  301. if assigned(MenuItem) then
  302. MenuItem^.Disabled:=not DebuggeeRunning;
  303. MenuItem:=PAdvancedMenuBar(MenuBar)^.GetMenuItem(cmUntilReturn);
  304. if assigned(MenuItem) then
  305. MenuItem^.Disabled:=not DebuggeeRunning;
  306. end;
  307. procedure TIDEApp.RunDir;
  308. var
  309. S,Dir : DirStr;
  310. D : PFPChDirDialog;
  311. begin
  312. {$push}{$I-}
  313. GetDir(0,Dir);
  314. {$pop}
  315. S:=GetRunDir;
  316. S:=FExpand(S);
  317. New(D, Init(cdNormal, hidRunDir));
  318. if ExecuteDialog(D,@S)= cmOk then
  319. SetRunDir(S);
  320. {$push}{$I-}
  321. ChDir(Dir);
  322. {$pop}
  323. end;
  324. procedure TIDEApp.Parameters;
  325. var R,R2: TRect;
  326. D: PCenterDialog;
  327. IL: PEditorInputLine;
  328. begin
  329. R.Assign(0,0,round(ScreenWidth*54/80),4);
  330. New(D, Init(R, dialog_programparameters));
  331. with D^ do
  332. begin
  333. GetExtent(R); R.Grow(-2,-1); Inc(R.A.Y); R.B.Y:=R.A.Y+1;
  334. R2.Copy(R); R2.A.X:=16; Dec(R2.B.X,4);
  335. New(IL, Init(R2, 255));
  336. IL^.Data^:=GetRunParameters;
  337. Insert(IL);
  338. R2.Copy(R); R2.A.X:=R2.B.X-3; R2.B.X:=R2.A.X+3;
  339. Insert(New(PHistory, Init(R2, IL, hidRunParameters)));
  340. R2.Copy(R); R2.B.X:=16;
  341. Insert(New(PLabel, Init(R2, label_parameters_parameter, IL)));
  342. end;
  343. InsertButtons(D);
  344. IL^.Select;
  345. if Desktop^.ExecView(D)=cmOK then
  346. begin
  347. SetRunParameters(IL^.Data^);
  348. end;
  349. Dispose(D, Done);
  350. end;
  351. procedure TIDEApp.DoResetDebugger;
  352. begin
  353. {$ifndef NODEBUG}
  354. if assigned(Debugger) then
  355. DoneDebugger;
  356. UpdateScreen(true);
  357. {$else NODEBUG}
  358. NoDebugger;
  359. {$endif NODEBUG}
  360. end;
  361. procedure TIDEApp.DoContToCursor;
  362. {$ifndef NODEBUG}
  363. var
  364. W : PFPWindow;
  365. PDL : PDisasLine;
  366. S,FileName : string;
  367. P,CurY,LineNr : longint;
  368. {$endif}
  369. begin
  370. {$ifndef NODEBUG}
  371. if (DeskTop^.Current=nil) or
  372. ((TypeOf(DeskTop^.Current^)<>TypeOf(TSourceWindow)) and
  373. (TypeOf(DeskTop^.Current^)<>TypeOf(TDisassemblyWindow))) then
  374. Begin
  375. ErrorBox(msg_impossibletoreachcursor,nil);
  376. Exit;
  377. End;
  378. If not assigned(Debugger) or Not Debugger^.HasExe then
  379. begin
  380. InitDebugger;
  381. if not assigned(Debugger) then
  382. begin
  383. NoDebugger;
  384. exit;
  385. end;
  386. end;
  387. W:=PFPWindow(DeskTop^.Current);
  388. If assigned(W) then
  389. begin
  390. If TypeOf(W^)=TypeOf(TSourceWindow) then
  391. begin
  392. FileName:=PSourceWindow(W)^.Editor^.FileName;
  393. LineNr:=PSourceWindow(W)^.Editor^.CurPos.Y+1;
  394. Debugger^.SetTbreak(GDBFileName(NameAndExtOf(FileName))+':'+IntToStr(LineNr));
  395. Debugger^.Continue;
  396. end
  397. else
  398. begin
  399. CurY:=PDisassemblyWindow(W)^.Editor^.CurPos.Y;
  400. if CurY<PDisassemblyWindow(W)^.Editor^.GetLineCount then
  401. PDL:=PDisasLine(PDisassemblyWindow(W)^.Editor^.GetLine(CurY))
  402. else
  403. PDL:=nil;
  404. if assigned(PDL) then
  405. begin
  406. if PDL^.Address<>0 then
  407. begin
  408. Debugger^.SetTBreak('*0x'+HexStr(PDL^.Address,sizeof(pointer)*2));
  409. end
  410. else
  411. begin
  412. S:=PDisassemblyWindow(W)^.Editor^.GetDisplayText(PDisassemblyWindow(W)^.Editor^.CurPos.Y);
  413. p:=pos(':',S);
  414. FileName:=Copy(S,1,p-1);
  415. S:=Copy(S,p+1,high(S));
  416. p:=pos(' ',S);
  417. S:=Copy(S,1,p-1);
  418. LineNr:=StrToInt(S);
  419. Debugger^.SetTBreak(GDBFileName(NameAndExtOf(FileName))+':'+IntToStr(LineNr));
  420. end;
  421. Debugger^.Continue;
  422. end;
  423. end;
  424. end;
  425. {$else NODEBUG}
  426. NoDebugger;
  427. {$endif NODEBUG}
  428. end;
  429. procedure TIDEApp.DoOpenGDBWindow;
  430. begin
  431. {$ifndef NODEBUG}
  432. InitGDBWindow;
  433. if not assigned(Debugger) then
  434. begin
  435. new(Debugger,Init);
  436. if assigned(Debugger) then
  437. Debugger^.SetExe(ExeFile);
  438. end;
  439. If assigned(GDBWindow) then
  440. GDBWindow^.MakeFirst;
  441. {$else NODEBUG}
  442. NoDebugger;
  443. {$endif NODEBUG}
  444. end;
  445. procedure TIDEApp.DoToggleBreak;
  446. {$ifndef NODEBUG}
  447. var
  448. W : PSourceWindow;
  449. WD : PDisassemblyWindow;
  450. PDL : PDisasLine;
  451. PB : PBreakpoint;
  452. S,FileName : string;
  453. b : boolean;
  454. CurY,P,LineNr : longint;
  455. {$endif}
  456. begin
  457. {$ifndef NODEBUG}
  458. if (DeskTop^.Current=nil) or
  459. (TypeOf(DeskTop^.Current^)<>TypeOf(TSourceWindow)) and
  460. (TypeOf(DeskTop^.Current^)<>TypeOf(TDisassemblyWindow)) then
  461. Begin
  462. ErrorBox(msg_impossibletosetbreakpoint,nil);
  463. Exit;
  464. End;
  465. if assigned (DeskTop^.Current) and
  466. (TypeOf(DeskTop^.Current^)=TypeOf(TSourceWindow)) then
  467. begin
  468. W:=PSourceWindow(DeskTop^.Current);
  469. FileName:=W^.Editor^.FileName;
  470. If FileName='' then
  471. begin
  472. W^.Editor^.SaveAs;
  473. FileName:=W^.Editor^.FileName;
  474. If FileName='' then
  475. Begin
  476. ErrorBox(msg_impossibletosetbreakpoint,nil);
  477. Exit;
  478. End;
  479. end;
  480. LineNr:=W^.Editor^.CurPos.Y+1;
  481. BreakpointsCollection^.ToggleFileLine(FileName,LineNr);
  482. end
  483. else if assigned (DeskTop^.Current) and
  484. (TypeOf(DeskTop^.Current^)=TypeOf(TDisassemblyWindow)) then
  485. begin
  486. WD:=PDisassemblyWindow(DeskTop^.Current);
  487. CurY:=WD^.Editor^.CurPos.Y;
  488. if CurY<WD^.Editor^.GetLineCount then
  489. PDL:=PDisasLine(WD^.Editor^.GetLine(CurY))
  490. else
  491. PDL:=nil;
  492. if assigned(PDL) then
  493. begin
  494. if PDL^.Address<>0 then
  495. begin
  496. PB:=New(PBreakpoint,init_address(HexStr(PDL^.Address,sizeof(pointer)*2)));
  497. BreakpointsCollection^.Insert(PB);
  498. WD^.Editor^.SetLineFlagState(CurY,lfBreakpoint,true);
  499. end
  500. else
  501. begin
  502. S:=WD^.Editor^.GetDisplayText(WD^.Editor^.CurPos.Y);
  503. p:=pos(':',S);
  504. FileName:=Copy(S,1,p-1);
  505. S:=Copy(S,p+1,high(S));
  506. p:=pos(' ',S);
  507. S:=Copy(S,1,p-1);
  508. LineNr:=StrToInt(S);
  509. b:=BreakpointsCollection^.ToggleFileLine(FileName,LineNr);
  510. WD^.Editor^.SetLineFlagState(CurY,lfBreakpoint,b);
  511. end;
  512. end;
  513. end;
  514. {$else NODEBUG}
  515. NoDebugger;
  516. {$endif NODEBUG}
  517. end;