fpdebug.pas 67 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481
  1. {
  2. $Id$
  3. This file is part of the Free Pascal Integrated Development Environment
  4. Copyright (c) 1998 by Berczi Gabor
  5. Debugger call routines for the IDE
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit FPDebug;
  13. interface
  14. uses
  15. Objects,Dialogs,Drivers,Views,
  16. GDBCon,GDBInt,Menus,
  17. WViews,
  18. FPViews;
  19. type
  20. PDebugController=^TDebugController;
  21. TDebugController=object(TGDBController)
  22. InvalidSourceLine : boolean;
  23. LastFileName : string;
  24. LastSource : PView; {PsourceWindow !! }
  25. HiddenStepsCount : longint;
  26. constructor Init(const exefn:string);
  27. destructor Done;
  28. procedure DoSelectSourceline(const fn:string;line:longint);virtual;
  29. { procedure DoStartSession;virtual;
  30. procedure DoBreakSession;virtual;}
  31. procedure DoEndSession(code:longint);virtual;
  32. procedure AnnotateError;
  33. procedure InsertBreakpoints;
  34. procedure RemoveBreakpoints;
  35. procedure ReadWatches;
  36. procedure ResetBreakpointsValues;
  37. procedure DoDebuggerScreen;virtual;
  38. procedure DoUserScreen;virtual;
  39. procedure Reset;virtual;
  40. procedure Run;virtual;
  41. procedure Continue;virtual;
  42. procedure UntilReturn;virtual;
  43. procedure CommandBegin(const s:string);virtual;
  44. procedure CommandEnd(const s:string);virtual;
  45. function AllowQuit : boolean;virtual;
  46. end;
  47. BreakpointType = (bt_function,bt_file_line,bt_watch,bt_awatch,bt_rwatch,bt_invalid);
  48. BreakpointState = (bs_enabled,bs_disabled,bs_deleted);
  49. PBreakpointCollection=^TBreakpointCollection;
  50. PBreakpoint=^TBreakpoint;
  51. TBreakpoint=object(TObject)
  52. typ : BreakpointType;
  53. state : BreakpointState;
  54. owner : PBreakpointCollection;
  55. Name : PString; { either function name or expr to watch }
  56. FileName : PString;
  57. OldValue,CurrentValue : Pstring;
  58. Line : Longint; { only used for bt_file_line type }
  59. Conditions : PString; { conditions relative to that breakpoint }
  60. IgnoreCount : Longint; { how many counts should be ignored }
  61. Commands : pchar; { commands that should be executed on breakpoint }
  62. GDBIndex : longint;
  63. GDBState : BreakpointState;
  64. constructor Init_function(Const AFunc : String);
  65. constructor Init_Empty;
  66. constructor Init_file_line(AFile : String; ALine : longint);
  67. constructor Init_type(atyp : BreakpointType;Const AnExpr : String);
  68. procedure Insert;
  69. procedure Remove;
  70. procedure Enable;
  71. procedure Disable;
  72. procedure ResetValues;
  73. destructor Done;virtual;
  74. end;
  75. TBreakpointCollection=object(TCollection)
  76. function At(Index: Integer): PBreakpoint;
  77. function GetGDB(index : longint) : PBreakpoint;
  78. function GetType(typ : BreakpointType;Const s : String) : PBreakpoint;
  79. function ToggleFileLine(Const FileName: String;LineNr : Longint) : boolean;
  80. procedure Update;
  81. procedure ShowBreakpoints(W : PSourceWindow);
  82. end;
  83. PBreakpointItem = ^TBreakpointItem;
  84. TBreakpointItem = object(TObject)
  85. Breakpoint : PBreakpoint;
  86. constructor Init(ABreakpoint : PBreakpoint);
  87. function GetText(MaxLen: Sw_integer): string; virtual;
  88. procedure Selected; virtual;
  89. function GetModuleName: string; virtual;
  90. end;
  91. PBreakpointsListBox = ^TBreakpointsListBox;
  92. TBreakpointsListBox = object(THSListBox)
  93. Transparent : boolean;
  94. NoSelection : boolean;
  95. MaxWidth : Sw_integer;
  96. (* ModuleNames : PStoreCollection; *)
  97. constructor Init(var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar);
  98. procedure AddBreakpoint(P: PBreakpointItem); virtual;
  99. function GetText(Item,MaxLen: Sw_Integer): String; virtual;
  100. function GetLocalMenu: PMenu;virtual;
  101. procedure Clear; virtual;
  102. procedure TrackSource; virtual;
  103. procedure EditNew; virtual;
  104. procedure EditCurrent; virtual;
  105. procedure DeleteCurrent; virtual;
  106. procedure ToggleCurrent;
  107. procedure Draw; virtual;
  108. procedure HandleEvent(var Event: TEvent); virtual;
  109. constructor Load(var S: TStream);
  110. procedure Store(var S: TStream);
  111. destructor Done; virtual;
  112. end;
  113. PBreakpointsWindow = ^TBreakpointsWindow;
  114. TBreakpointsWindow = object(TDlgWindow)
  115. BreakLB : PBreakpointsListBox;
  116. constructor Init;
  117. procedure AddBreakpoint(ABreakpoint : PBreakpoint);
  118. procedure ClearBreakpoints;
  119. procedure ReloadBreakpoints;
  120. procedure Close; virtual;
  121. procedure SizeLimits(var Min, Max: TPoint);virtual;
  122. procedure HandleEvent(var Event: TEvent); virtual;
  123. procedure Update; virtual;
  124. constructor Load(var S: TStream);
  125. procedure Store(var S: TStream);
  126. destructor Done; virtual;
  127. end;
  128. PBreakpointItemDialog = ^TBreakpointItemDialog;
  129. TBreakpointItemDialog = object(TCenterDialog)
  130. constructor Init(ABreakpoint: PBreakpoint);
  131. function Execute: Word; virtual;
  132. private
  133. Breakpoint : PBreakpoint;
  134. TypeRB : PRadioButtons;
  135. NameIL : PInputLine;
  136. ConditionsIL: PInputLine;
  137. LineIL : PInputLine;
  138. IgnoreIL : PInputLine;
  139. end;
  140. PWatch = ^TWatch;
  141. TWatch = Object(TObject)
  142. constructor Init(s : string);
  143. procedure rename(s : string);
  144. procedure Get_new_value;
  145. destructor done;virtual;
  146. private
  147. expr : pstring;
  148. last_value,current_value : pchar;
  149. end;
  150. PWatchesCollection = ^TWatchesCollection;
  151. TWatchesCollection = Object(TCollection)
  152. constructor Init;
  153. procedure Insert(Item: Pointer); virtual;
  154. function At(Index: Integer): PWatch;
  155. procedure Update;
  156. private
  157. MaxW : integer;
  158. end;
  159. PWatchesListBox = ^TWatchesListBox;
  160. TWatchesListBox = object(THSListBox)
  161. Transparent : boolean;
  162. MaxWidth : Sw_integer;
  163. constructor Init(var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar);
  164. (* procedure AddWatch(P: PWatch); virtual; *)
  165. procedure Update(AMaxWidth : integer);
  166. function GetIndentedText(Item,Indent,MaxLen: Sw_Integer): String; virtual;
  167. function GetLocalMenu: PMenu;virtual;
  168. (* procedure Clear; virtual;
  169. procedure TrackSource; virtual;*)
  170. procedure EditNew; virtual;
  171. procedure EditCurrent; virtual;
  172. procedure DeleteCurrent; virtual;
  173. (*procedure ToggleCurrent; *)
  174. procedure Draw; virtual;
  175. procedure HandleEvent(var Event: TEvent); virtual;
  176. constructor Load(var S: TStream);
  177. procedure Store(var S: TStream);
  178. destructor Done; virtual;
  179. end;
  180. PWatchItemDialog = ^TWatchItemDialog;
  181. TWatchItemDialog = object(TCenterDialog)
  182. constructor Init(AWatch: PWatch);
  183. function Execute: Word; virtual;
  184. private
  185. Watch : PWatch;
  186. NameIL : PInputLine;
  187. TextST : PAdvancedStaticText;
  188. end;
  189. PWatchesWindow = ^TWatchesWindow;
  190. TWatchesWindow = Object(TDlgWindow)
  191. WLB : PWatchesListBox;
  192. Constructor Init;
  193. constructor Load(var S: TStream);
  194. procedure Store(var S: TStream);
  195. procedure Update; virtual;
  196. destructor Done; virtual;
  197. end;
  198. PFramesListBox = ^TFramesListBox;
  199. TFramesListBox = object(TMessageListBox)
  200. constructor Init(var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar);
  201. procedure Update;
  202. function GetLocalMenu: PMenu;virtual;
  203. procedure GotoSource; virtual;
  204. procedure HandleEvent(var Event: TEvent); virtual;
  205. destructor Done; virtual;
  206. end;
  207. PStackWindow = ^TStackWindow;
  208. TStackWindow = Object(TDlgWindow)
  209. FLB : PFramesListBox;
  210. Constructor Init;
  211. constructor Load(var S: TStream);
  212. procedure Store(var S: TStream);
  213. procedure Update; virtual;
  214. destructor Done; virtual;
  215. end;
  216. const
  217. StackWindow : PStackWindow = nil;
  218. procedure InitStackWindow;
  219. procedure DoneStackWindow;
  220. const
  221. BreakpointTypeStr : Array[BreakpointType] of String[9]
  222. = ( 'function','file-line','watch','awatch','rwatch','invalid' );
  223. BreakpointStateStr : Array[BreakpointState] of String[8]
  224. = ( 'enabled','disabled','invalid' );
  225. var
  226. Debugger : PDebugController;
  227. BreakpointCollection : PBreakpointCollection;
  228. WatchesCollection : PwatchesCollection;
  229. procedure InitDebugger;
  230. procedure DoneDebugger;
  231. procedure InitGDBWindow;
  232. procedure DoneGDBWindow;
  233. procedure InitBreakpoints;
  234. procedure DoneBreakpoints;
  235. procedure InitWatches;
  236. procedure DoneWatches;
  237. procedure RegisterFPDebugViews;
  238. implementation
  239. uses
  240. Dos,Mouse,Video,
  241. App,Commands,Strings,
  242. FPVars,FPUtils,FPConst,
  243. FPIntf,FPCompile,FPIde,
  244. Validate,WEditor,WUtils;
  245. const
  246. RBreakpointsWindow: TStreamRec = (
  247. ObjType: 1701;
  248. VmtLink: Ofs(TypeOf(TBreakpointsWindow)^);
  249. Load: @TBreakpointsWindow.Load;
  250. Store: @TBreakpointsWindow.Store
  251. );
  252. RBreakpointsListBox : TStreamRec = (
  253. ObjType: 1702;
  254. VmtLink: Ofs(TypeOf(TBreakpointsListBox)^);
  255. Load: @TBreakpointsListBox.Load;
  256. Store: @TBreakpointsListBox.Store
  257. );
  258. RWatchesWindow: TStreamRec = (
  259. ObjType: 1703;
  260. VmtLink: Ofs(TypeOf(TWatchesWindow)^);
  261. Load: @TWatchesWindow.Load;
  262. Store: @TWatchesWindow.Store
  263. );
  264. RWatchesListBox: TStreamRec = (
  265. ObjType: 1704;
  266. VmtLink: Ofs(TypeOf(TWatchesListBox)^);
  267. Load: @TWatchesListBox.Load;
  268. Store: @TWatchesListBox.Store
  269. );
  270. RStackWindow: TStreamRec = (
  271. ObjType: 1705;
  272. VmtLink: Ofs(TypeOf(TStackWindow)^);
  273. Load: @TStackWindow.Load;
  274. Store: @TStackWindow.Store
  275. );
  276. RFramesListBox: TStreamRec = (
  277. ObjType: 1706;
  278. VmtLink: Ofs(TypeOf(TFramesListBox)^);
  279. Load: @TFramesListBox.Load;
  280. Store: @TFramesListBox.Store
  281. );
  282. {****************************************************************************
  283. TDebugController
  284. ****************************************************************************}
  285. constructor TDebugController.Init(const exefn:string);
  286. var f: string;
  287. begin
  288. inherited Init;
  289. f := exefn;
  290. LoadFile(f);
  291. SetArgs(GetRunParameters);
  292. Debugger:=@self;
  293. switch_to_user:=true;
  294. InsertBreakpoints;
  295. ReadWatches;
  296. end;
  297. procedure TDebugController.InsertBreakpoints;
  298. procedure DoInsert(PB : PBreakpoint);
  299. begin
  300. PB^.Insert;
  301. end;
  302. begin
  303. BreakpointCollection^.ForEach(@DoInsert);
  304. end;
  305. procedure TDebugController.ReadWatches;
  306. procedure DoRead(PB : PWatch);
  307. begin
  308. PB^.Get_new_value;
  309. end;
  310. begin
  311. WatchesCollection^.ForEach(@DoRead);
  312. If Assigned(WatchesWindow) then
  313. WatchesWindow^.Update;
  314. end;
  315. procedure TDebugController.RemoveBreakpoints;
  316. procedure DoDelete(PB : PBreakpoint);
  317. begin
  318. PB^.Remove;
  319. end;
  320. begin
  321. BreakpointCollection^.ForEach(@DoDelete);
  322. end;
  323. procedure TDebugController.ResetBreakpointsValues;
  324. procedure DoResetVal(PB : PBreakpoint);
  325. begin
  326. PB^.ResetValues;
  327. end;
  328. begin
  329. BreakpointCollection^.ForEach(@DoResetVal);
  330. end;
  331. destructor TDebugController.Done;
  332. begin
  333. { kill the program if running }
  334. Reset;
  335. RemoveBreakpoints;
  336. inherited Done;
  337. end;
  338. procedure TDebugController.Run;
  339. begin
  340. ResetBreakpointsValues;
  341. inherited Run;
  342. MyApp.SetCmdState([cmResetDebugger,cmUntilReturn],true);
  343. If assigned(StackWindow) then
  344. StackWindow^.Update;
  345. end;
  346. procedure TDebugController.Continue;
  347. begin
  348. {$ifdef NODEBUG}
  349. NoDebugger;
  350. {$else}
  351. if not debuggee_started then
  352. Run
  353. else
  354. inherited Continue;
  355. If assigned(StackWindow) then
  356. StackWindow^.Update;
  357. {$endif NODEBUG}
  358. end;
  359. procedure TDebugController.UntilReturn;
  360. begin
  361. Command('finish');
  362. If assigned(StackWindow) then
  363. StackWindow^.Update;
  364. { We could try to get the return value !
  365. Not done yet }
  366. end;
  367. procedure TDebugController.CommandBegin(const s:string);
  368. begin
  369. if assigned(GDBWindow) and (in_command>1) then
  370. begin
  371. { We should do something special for errors !! }
  372. If StrLen(GetError)>0 then
  373. GDBWindow^.WriteErrorText(GetError);
  374. GDBWindow^.WriteOutputText(GetOutput);
  375. end;
  376. if assigned(GDBWindow) then
  377. GDBWindow^.WriteString(S);
  378. end;
  379. procedure TDebugController.CommandEnd(const s:string);
  380. begin
  381. if assigned(GDBWindow) and (in_command=0) then
  382. begin
  383. { We should do something special for errors !! }
  384. If StrLen(GetError)>0 then
  385. GDBWindow^.WriteErrorText(GetError);
  386. GDBWindow^.WriteOutputText(GetOutput);
  387. GDBWindow^.Editor^.TextEnd;
  388. end;
  389. end;
  390. function TDebugController.AllowQuit : boolean;
  391. begin
  392. if ConfirmBox('Really quit editor ?',nil,true)=cmOK then
  393. begin
  394. Message(@MyApp,evCommand,cmQuit,nil);
  395. end
  396. else
  397. AllowQuit:=false;
  398. end;
  399. procedure TDebugController.Reset;
  400. var
  401. W : PSourceWindow;
  402. procedure ResetDebugerRow(P: PView); {$ifndef FPC}far;{$endif}
  403. begin
  404. if assigned(P) and
  405. (TypeOf(P^)=TypeOf(TSourceWindow)) then
  406. Message(P,evCommand,cmResetDebuggerRow,nil);
  407. end;
  408. begin
  409. inherited Reset;
  410. MyApp.SetCmdState([cmResetDebugger,cmUntilReturn],false);
  411. W:=PSourceWindow(LastSource);
  412. if assigned(W) then
  413. W^.Editor^.SetDebuggerRow(-1);
  414. Desktop^.ForEach(@ResetDebugerRow);
  415. end;
  416. procedure TDebugController.AnnotateError;
  417. var errornb : longint;
  418. begin
  419. if error then
  420. begin
  421. errornb:=error_num;
  422. ReadWatches;
  423. If assigned(StackWindow) then
  424. StackWindow^.Update;
  425. ErrorBox(#3'Error within GDB'#13#3'Error code = %d',@errornb);
  426. end;
  427. end;
  428. procedure TDebugController.DoSelectSourceLine(const fn:string;line:longint);
  429. var
  430. W: PSourceWindow;
  431. Found : boolean;
  432. PB : PBreakpoint;
  433. S : String;
  434. BreakIndex : longint;
  435. begin
  436. BreakIndex:=stop_breakpoint_number;
  437. Desktop^.Lock;
  438. { 0 based line count in Editor }
  439. if Line>0 then
  440. dec(Line);
  441. if (fn=LastFileName) then
  442. begin
  443. W:=PSourceWindow(LastSource);
  444. if assigned(W) then
  445. begin
  446. W^.Editor^.SetCurPtr(0,Line);
  447. W^.Editor^.TrackCursor(true);
  448. W^.Editor^.SetDebuggerRow(Line);
  449. ReadWatches;
  450. If assigned(StackWindow) then
  451. StackWindow^.Update;
  452. if Not assigned(GDBWindow) or not GDBWindow^.GetState(sfActive) then
  453. W^.Select;
  454. InvalidSourceLine:=false;
  455. end
  456. else
  457. InvalidSourceLine:=true;
  458. end
  459. else
  460. begin
  461. W:=TryToOpenFile(nil,fn,0,Line,false);
  462. if assigned(W) then
  463. begin
  464. W^.Editor^.SetDebuggerRow(Line);
  465. W^.Editor^.TrackCursor(true);
  466. If assigned(StackWindow) then
  467. StackWindow^.Update;
  468. ReadWatches;
  469. if Not assigned(GDBWindow) or not GDBWindow^.GetState(sfActive) then
  470. W^.Select;
  471. LastSource:=W;
  472. InvalidSourceLine:=false;
  473. end
  474. { only search a file once }
  475. else
  476. begin
  477. Desktop^.UnLock;
  478. Found:=MyApp.OpenSearch(fn);
  479. Desktop^.Lock;
  480. if not Found then
  481. begin
  482. InvalidSourceLine:=true;
  483. LastSource:=Nil;
  484. end
  485. else
  486. begin
  487. { should now be open }
  488. W:=TryToOpenFile(nil,fn,0,Line,true);
  489. W^.Editor^.SetDebuggerRow(Line);
  490. W^.Editor^.TrackCursor(true);
  491. ReadWatches;
  492. If assigned(StackWindow) then
  493. StackWindow^.Update;
  494. if Not assigned(GDBWindow) or not GDBWindow^.GetState(sfActive) then
  495. W^.Select;
  496. LastSource:=W;
  497. InvalidSourceLine:=false;
  498. end;
  499. end;
  500. end;
  501. LastFileName:=fn;
  502. Desktop^.UnLock;
  503. if BreakIndex>0 then
  504. begin
  505. PB:=BreakpointCollection^.GetGDB(BreakIndex);
  506. { For watch we should get old and new value !! }
  507. if (Not assigned(GDBWindow) or not GDBWindow^.GetState(sfActive)) and
  508. (PB^.typ<>bt_file_line) and (PB^.typ<>bt_function) then
  509. begin
  510. Command('p '+GetStr(PB^.Name));
  511. S:=StrPas(GetOutput);
  512. got_error:=false;
  513. If Pos('=',S)>0 then
  514. S:=Copy(S,Pos('=',S)+1,255);
  515. If S[Length(S)]=#10 then
  516. Delete(S,Length(S),1);
  517. if Assigned(PB^.OldValue) then
  518. DisposeStr(PB^.OldValue);
  519. PB^.OldValue:=PB^.CurrentValue;
  520. PB^.CurrentValue:=NewStr(S);
  521. If PB^.typ=bt_function then
  522. WarningBox(#3'GDB stopped due to'#13+
  523. #3+BreakpointTypeStr[PB^.typ]+' '+GetStr(PB^.Name),nil)
  524. else if (GetStr(PB^.OldValue)<>S) then
  525. WarningBox(#3'GDB stopped due to'#13+
  526. #3+BreakpointTypeStr[PB^.typ]+' '+GetStr(PB^.Name)+#13+
  527. #3+'Old value = '+GetStr(PB^.OldValue)+#13+
  528. #3+'New value = '+GetStr(PB^.CurrentValue),nil)
  529. else
  530. WarningBox(#3'GDB stopped due to'#13+
  531. #3+BreakpointTypeStr[PB^.typ]+' '+GetStr(PB^.Name)+#13+
  532. #3+' value = '+GetStr(PB^.CurrentValue),nil);
  533. end;
  534. end;
  535. end;
  536. procedure TDebugController.DoEndSession(code:longint);
  537. var P :Array[1..2] of longint;
  538. W : PSourceWindow;
  539. begin
  540. MyApp.SetCmdState([cmResetDebugger],false);
  541. W:=PSourceWindow(LastSource);
  542. if assigned(W) then
  543. W^.Editor^.SetDebuggerRow(-1);
  544. If HiddenStepsCount=0 then
  545. InformationBox(#3'Program exited with '#13#3'exitcode = %d',@code)
  546. else
  547. begin
  548. P[1]:=code;
  549. P[2]:=HiddenStepsCount;
  550. WarningBox(#3'Program exited with '#13+
  551. #3'exitcode = %d'#13+
  552. #3'hidden steps = %d',@P);
  553. end;
  554. end;
  555. procedure TDebugController.DoDebuggerScreen;
  556. begin
  557. MyApp.ShowIDEScreen;
  558. end;
  559. procedure TDebugController.DoUserScreen;
  560. begin
  561. MyApp.ShowUserScreen;
  562. end;
  563. {****************************************************************************
  564. TBreakpoint
  565. ****************************************************************************}
  566. constructor TBreakpoint.Init_function(Const AFunc : String);
  567. begin
  568. typ:=bt_function;
  569. state:=bs_enabled;
  570. GDBState:=bs_deleted;
  571. Name:=NewStr(AFunc);
  572. FileName:=nil;
  573. Line:=0;
  574. IgnoreCount:=0;
  575. Commands:=nil;
  576. Conditions:=nil;
  577. OldValue:=nil;
  578. CurrentValue:=nil;
  579. end;
  580. constructor TBreakpoint.Init_Empty;
  581. begin
  582. typ:=bt_function;
  583. state:=bs_enabled;
  584. GDBState:=bs_deleted;
  585. Name:=Nil;
  586. FileName:=nil;
  587. Line:=0;
  588. IgnoreCount:=0;
  589. Commands:=nil;
  590. Conditions:=nil;
  591. OldValue:=nil;
  592. CurrentValue:=nil;
  593. end;
  594. constructor TBreakpoint.Init_type(atyp : BreakpointType;Const AnExpr : String);
  595. begin
  596. typ:=atyp;
  597. state:=bs_enabled;
  598. GDBState:=bs_deleted;
  599. Name:=NewStr(AnExpr);
  600. IgnoreCount:=0;
  601. Commands:=nil;
  602. Conditions:=nil;
  603. OldValue:=nil;
  604. CurrentValue:=nil;
  605. end;
  606. constructor TBreakpoint.Init_file_line(AFile : String; ALine : longint);
  607. begin
  608. typ:=bt_file_line;
  609. state:=bs_enabled;
  610. GDBState:=bs_deleted;
  611. { d:test.pas:12 does not work !! }
  612. { I do not know how to solve this if
  613. if (Length(AFile)>1) and (AFile[2]=':') then
  614. AFile:=Copy(AFile,3,255);
  615. Only use base name for now !! PM }
  616. FileName:=NewStr(AFile);
  617. Name:=nil;
  618. Line:=ALine;
  619. IgnoreCount:=0;
  620. Commands:=nil;
  621. Conditions:=nil;
  622. OldValue:=nil;
  623. CurrentValue:=nil;
  624. end;
  625. procedure TBreakpoint.Insert;
  626. begin
  627. If not assigned(Debugger) then Exit;
  628. Remove;
  629. Debugger^.last_breakpoint_number:=0;
  630. if (GDBState=bs_deleted) and (state=bs_enabled) then
  631. begin
  632. if (typ=bt_file_line) and assigned(FileName) then
  633. Debugger^.Command('break '+NameAndExtOf(FileName^)+':'+IntToStr(Line))
  634. else if (typ=bt_function) and assigned(name) then
  635. Debugger^.Command('break '+name^)
  636. else if (typ=bt_watch) and assigned(name) then
  637. Debugger^.Command('watch '+name^)
  638. else if (typ=bt_awatch) and assigned(name) then
  639. Debugger^.Command('awatch '+name^)
  640. else if (typ=bt_rwatch) and assigned(name) then
  641. Debugger^.Command('rwatch '+name^);
  642. if Debugger^.last_breakpoint_number<>0 then
  643. begin
  644. GDBIndex:=Debugger^.last_breakpoint_number;
  645. GDBState:=bs_enabled;
  646. Debugger^.Command('cond '+IntToStr(GDBIndex)+' '+GetStr(Conditions));
  647. Debugger^.Command('ignore '+IntToStr(GDBIndex)+' '+IntToStr(IgnoreCount));
  648. If Assigned(Commands) then
  649. begin
  650. {Commands are not handled yet }
  651. end;
  652. end
  653. else
  654. { Here there was a problem !! }
  655. begin
  656. GDBIndex:=0;
  657. ErrorBox(#3'Could not set Breakpoint'#13+
  658. #3+BreakpointTypeStr[typ]+' '+Name^,nil);
  659. state:=bs_disabled;
  660. end;
  661. end
  662. else if (GDBState=bs_disabled) and (state=bs_enabled) then
  663. Enable
  664. else if (GDBState=bs_enabled) and (state=bs_disabled) then
  665. Disable;
  666. end;
  667. procedure TBreakpoint.Remove;
  668. begin
  669. If not assigned(Debugger) then Exit;
  670. if GDBIndex>0 then
  671. Debugger^.Command('delete '+IntToStr(GDBIndex));
  672. GDBIndex:=0;
  673. GDBState:=bs_deleted;
  674. end;
  675. procedure TBreakpoint.Enable;
  676. begin
  677. If not assigned(Debugger) then Exit;
  678. if GDBIndex>0 then
  679. Debugger^.Command('enable '+IntToStr(GDBIndex))
  680. else
  681. Insert;
  682. GDBState:=bs_enabled;
  683. end;
  684. procedure TBreakpoint.Disable;
  685. begin
  686. If not assigned(Debugger) then Exit;
  687. if GDBIndex>0 then
  688. Debugger^.Command('disable '+IntToStr(GDBIndex));
  689. GDBState:=bs_disabled;
  690. end;
  691. procedure TBreakpoint.ResetValues;
  692. begin
  693. if assigned(OldValue) then
  694. DisposeStr(OldValue);
  695. OldValue:=nil;
  696. if assigned(CurrentValue) then
  697. DisposeStr(CurrentValue);
  698. CurrentValue:=nil;
  699. end;
  700. destructor TBreakpoint.Done;
  701. begin
  702. Remove;
  703. ResetValues;
  704. if assigned(Name) then
  705. DisposeStr(Name);
  706. if assigned(FileName) then
  707. DisposeStr(FileName);
  708. if assigned(Conditions) then
  709. DisposeStr(Conditions);
  710. if assigned(Commands) then
  711. StrDispose(Commands);
  712. inherited Done;
  713. end;
  714. {****************************************************************************
  715. TBreakpointCollection
  716. ****************************************************************************}
  717. function TBreakpointCollection.At(Index: Integer): PBreakpoint;
  718. begin
  719. At:=inherited At(Index);
  720. end;
  721. procedure TBreakpointCollection.Update;
  722. begin
  723. if assigned(Debugger) then
  724. begin
  725. Debugger^.RemoveBreakpoints;
  726. Debugger^.InsertBreakpoints;
  727. end;
  728. if assigned(BreakpointsWindow) then
  729. BreakpointsWindow^.Update;
  730. end;
  731. function TBreakpointCollection.GetGDB(index : longint) : PBreakpoint;
  732. function IsNum(P : PBreakpoint) : boolean;{$ifndef FPC}far;{$endif}
  733. begin
  734. IsNum:=P^.GDBIndex=index;
  735. end;
  736. begin
  737. if index=0 then
  738. GetGDB:=nil
  739. else
  740. GetGDB:=FirstThat(@IsNum);
  741. end;
  742. procedure TBreakpointCollection.ShowBreakpoints(W : PSourceWindow);
  743. procedure SetInSource(P : PBreakpoint);{$ifndef FPC}far;{$endif}
  744. begin
  745. If assigned(P^.FileName) and (P^.FileName^=W^.Editor^.FileName) then
  746. W^.Editor^.SetLineBreakState(P^.Line,P^.state=bs_enabled);
  747. end;
  748. begin
  749. ForEach(@SetInSource);
  750. end;
  751. function TBreakpointCollection.GetType(typ : BreakpointType;Const s : String) : PBreakpoint;
  752. function IsThis(P : PBreakpoint) : boolean;{$ifndef FPC}far;{$endif}
  753. begin
  754. IsThis:=(P^.typ=typ) and (P^.Name^=S);
  755. end;
  756. begin
  757. GetType:=FirstThat(@IsThis);
  758. end;
  759. function TBreakpointCollection.ToggleFileLine(Const FileName: String;LineNr : Longint) : boolean;
  760. var PB : PBreakpoint;
  761. function IsThere(P : PBreakpoint) : boolean;{$ifndef FPC}far;{$endif}
  762. begin
  763. IsThere:=(P^.typ=bt_file_line) and (P^.FileName^=FileName) and (P^.Line=LineNr);
  764. end;
  765. begin
  766. PB:=FirstThat(@IsThere);
  767. ToggleFileLine:=false;
  768. If Assigned(PB) then
  769. if PB^.state=bs_disabled then
  770. begin
  771. PB^.state:=bs_enabled;
  772. ToggleFileLine:=true;
  773. end
  774. else if PB^.state=bs_enabled then
  775. PB^.state:=bs_disabled;
  776. If not assigned(PB) then
  777. begin
  778. PB:= New(PBreakpoint,Init_file_line(FileName,LineNr));
  779. if assigned(PB) then
  780. Begin
  781. Insert(PB);
  782. ToggleFileLine:=true;
  783. End;
  784. end;
  785. Update;
  786. end;
  787. {****************************************************************************
  788. TBreakpointItem
  789. ****************************************************************************}
  790. constructor TBreakpointItem.Init(ABreakpoint : PBreakpoint);
  791. begin
  792. inherited Init;
  793. Breakpoint:=ABreakpoint;
  794. end;
  795. function TBreakpointItem.GetText(MaxLen: Sw_integer): string;
  796. var S: string;
  797. begin
  798. with Breakpoint^ do
  799. begin
  800. S:=BreakpointTypeStr[typ];
  801. While Length(S)<10 do
  802. S:=S+' ';
  803. S:=S+'|';
  804. S:=S+BreakpointStateStr[state]+' ';
  805. While Length(S)<20 do
  806. S:=S+' ';
  807. S:=S+'|';
  808. if (typ=bt_file_line) then
  809. S:=S+NameAndExtOf(GetStr(FileName))+':'+IntToStr(Line)
  810. else
  811. S:=S+GetStr(name);
  812. While Length(S)<40 do
  813. S:=S+' ';
  814. S:=S+'|';
  815. if IgnoreCount>0 then
  816. S:=S+IntToStr(IgnoreCount);
  817. While Length(S)<49 do
  818. S:=S+' ';
  819. S:=S+'|';
  820. if assigned(Conditions) then
  821. S:=S+' '+GetStr(Conditions);
  822. if length(S)>MaxLen then S:=copy(S,1,MaxLen-2)+'..';
  823. GetText:=S;
  824. end;
  825. end;
  826. procedure TBreakpointItem.Selected;
  827. begin
  828. end;
  829. function TBreakpointItem.GetModuleName: string;
  830. begin
  831. if breakpoint^.typ=bt_file_line then
  832. GetModuleName:=GetStr(breakpoint^.FileName)
  833. else
  834. GetModuleName:='';
  835. end;
  836. {****************************************************************************
  837. TBreakpointsListBox
  838. ****************************************************************************}
  839. constructor TBreakpointsListBox.Init(var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar);
  840. begin
  841. inherited Init(Bounds,1,AHScrollBar, AVScrollBar);
  842. GrowMode:=gfGrowLoX+gfGrowHiX+gfGrowHiY;
  843. NoSelection:=true;
  844. end;
  845. function TBreakpointsListBox.GetLocalMenu: PMenu;
  846. var M: PMenu;
  847. begin
  848. if (Owner<>nil) and (Owner^.GetState(sfModal)) then M:=nil else
  849. M:=NewMenu(
  850. NewItem('~G~oto source','',kbNoKey,cmMsgGotoSource,hcMsgGotoSource,
  851. NewItem('~E~dit breakpoint','',kbNoKey,cmEditBreakpoint,hcEditBreakpoint,
  852. NewItem('~N~ew breakpoint','',kbNoKey,cmNewBreakpoint,hcNewBreakpoint,
  853. NewItem('~D~elete breakpoint','',kbNoKey,cmDeleteBreakpoint,hcDeleteBreakpoint,
  854. NewItem('~T~oggle state','',kbNoKey,cmToggleBreakpoint,hcToggleBreakpoint,
  855. nil))))));
  856. GetLocalMenu:=M;
  857. end;
  858. procedure TBreakpointsListBox.HandleEvent(var Event: TEvent);
  859. var DontClear: boolean;
  860. begin
  861. case Event.What of
  862. evKeyDown :
  863. begin
  864. DontClear:=false;
  865. case Event.KeyCode of
  866. kbEnter :
  867. Message(@Self,evCommand,cmMsgGotoSource,nil);
  868. else
  869. DontClear:=true;
  870. end;
  871. if not DontClear then
  872. ClearEvent(Event);
  873. end;
  874. evBroadcast :
  875. case Event.Command of
  876. cmListItemSelected :
  877. if Event.InfoPtr=@Self then
  878. Message(@Self,evCommand,cmEditBreakpoint,nil);
  879. end;
  880. evCommand :
  881. begin
  882. DontClear:=false;
  883. case Event.Command of
  884. cmMsgTrackSource :
  885. if Range>0 then
  886. TrackSource;
  887. cmEditBreakpoint :
  888. EditCurrent;
  889. cmToggleBreakpoint :
  890. ToggleCurrent;
  891. cmDeleteBreakpoint :
  892. DeleteCurrent;
  893. cmNewBreakpoint :
  894. EditNew;
  895. cmMsgClear :
  896. Clear;
  897. else
  898. DontClear:=true;
  899. end;
  900. if not DontClear then
  901. ClearEvent(Event);
  902. end;
  903. end;
  904. inherited HandleEvent(Event);
  905. end;
  906. procedure TBreakpointsListBox.AddBreakpoint(P: PBreakpointItem);
  907. var W : integer;
  908. begin
  909. if List=nil then New(List, Init(20,20));
  910. W:=length(P^.GetText(255));
  911. if W>MaxWidth then
  912. begin
  913. MaxWidth:=W;
  914. if HScrollBar<>nil then
  915. HScrollBar^.SetRange(0,MaxWidth);
  916. end;
  917. List^.Insert(P);
  918. SetRange(List^.Count);
  919. if Focused=List^.Count-1-1 then
  920. FocusItem(List^.Count-1);
  921. DrawView;
  922. end;
  923. (* function TBreakpointsListBox.AddModuleName(const Name: string): PString;
  924. var P: PString;
  925. begin
  926. if ModuleNames<>nil then
  927. P:=ModuleNames^.Add(Name)
  928. else
  929. P:=nil;
  930. AddModuleName:=P;
  931. end; *)
  932. function TBreakpointsListBox.GetText(Item,MaxLen: Sw_Integer): String;
  933. var P: PBreakpointItem;
  934. S: string;
  935. begin
  936. P:=List^.At(Item);
  937. S:=P^.GetText(MaxLen);
  938. GetText:=copy(S,1,MaxLen);
  939. end;
  940. procedure TBreakpointsListBox.Clear;
  941. begin
  942. if assigned(List) then
  943. Dispose(List, Done);
  944. List:=nil;
  945. MaxWidth:=0;
  946. (* if assigned(ModuleNames) then
  947. ModuleNames^.FreeAll; *)
  948. SetRange(0); DrawView;
  949. Message(Application,evBroadcast,cmClearLineHighlights,@Self);
  950. end;
  951. procedure TBreakpointsListBox.TrackSource;
  952. var W: PSourceWindow;
  953. P: PBreakpointItem;
  954. R: TRect;
  955. (* Row,Col: sw_integer; *)
  956. begin
  957. (*Message(Application,evBroadcast,cmClearLineHighlights,@Self);
  958. if Range=0 then Exit;*)
  959. P:=List^.At(Focused);
  960. if P^.GetModuleName='' then Exit;
  961. Desktop^.Lock;
  962. GetNextEditorBounds(R);
  963. R.B.Y:=Owner^.Origin.Y;
  964. W:=EditorWindowFile(P^.GetModuleName);
  965. if assigned(W) then
  966. begin
  967. W^.GetExtent(R);
  968. R.B.Y:=Owner^.Origin.Y;
  969. W^.ChangeBounds(R);
  970. W^.Editor^.SetCurPtr(1,P^.Breakpoint^.Line);
  971. end
  972. else
  973. W:=TryToOpenFile(@R,P^.GetModuleName,1,P^.Breakpoint^.Line,true);
  974. if W<>nil then
  975. begin
  976. W^.Select;
  977. W^.Editor^.TrackCursor(true);
  978. W^.Editor^.SetHighlightRow(P^.Breakpoint^.Line);
  979. end;
  980. if Assigned(Owner) then
  981. Owner^.Select;
  982. Desktop^.UnLock;
  983. end;
  984. procedure TBreakpointsListBox.ToggleCurrent;
  985. var W: PSourceWindow;
  986. P: PBreakpointItem;
  987. b : boolean;
  988. (* Row,Col: sw_integer; *)
  989. begin
  990. if Range=0 then Exit;
  991. P:=List^.At(Focused);
  992. if P=nil then Exit;
  993. if P^.Breakpoint^.state=bs_enabled then
  994. P^.Breakpoint^.state:=bs_disabled
  995. else if P^.Breakpoint^.state=bs_disabled then
  996. P^.Breakpoint^.state:=bs_enabled;
  997. BreakpointCollection^.Update;
  998. if P^.Breakpoint^.typ=bt_file_line then
  999. begin
  1000. W:=TryToOpenFile(nil,GetStr(P^.Breakpoint^.FileName),1,P^.Breakpoint^.Line,false);
  1001. If assigned(W) then
  1002. begin
  1003. if P^.Breakpoint^.state=bs_enabled then
  1004. b:=true
  1005. else
  1006. b:=false;
  1007. W^.Editor^.SetLineBreakState(P^.Breakpoint^.Line,b);
  1008. end;
  1009. end;
  1010. end;
  1011. procedure TBreakpointsListBox.EditCurrent;
  1012. var
  1013. P: PBreakpointItem;
  1014. begin
  1015. if Range=0 then Exit;
  1016. P:=List^.At(Focused);
  1017. if P=nil then Exit;
  1018. Application^.ExecuteDialog(New(PBreakpointItemDialog,Init(P^.Breakpoint)),nil);
  1019. BreakpointCollection^.Update;
  1020. end;
  1021. procedure TBreakpointsListBox.DeleteCurrent;
  1022. var
  1023. P: PBreakpointItem;
  1024. begin
  1025. if Range=0 then Exit;
  1026. P:=List^.At(Focused);
  1027. if P=nil then Exit;
  1028. BreakpointCollection^.free(P^.Breakpoint);
  1029. List^.free(P);
  1030. BreakpointCollection^.Update;
  1031. end;
  1032. procedure TBreakpointsListBox.EditNew;
  1033. var
  1034. P: PBreakpoint;
  1035. begin
  1036. P:=New(PBreakpoint,Init_Empty);
  1037. if Application^.ExecuteDialog(New(PBreakpointItemDialog,Init(P)),nil)<>cmCancel then
  1038. begin
  1039. BreakpointCollection^.Insert(P);
  1040. BreakpointCollection^.Update;
  1041. end
  1042. else
  1043. dispose(P,Done);
  1044. end;
  1045. procedure TBreakpointsListBox.Draw;
  1046. var
  1047. I, J, Item: Sw_Integer;
  1048. NormalColor, SelectedColor, FocusedColor, Color: Word;
  1049. ColWidth, CurCol, Indent: Integer;
  1050. B: TDrawBuffer;
  1051. Text: String;
  1052. SCOff: Byte;
  1053. TC: byte;
  1054. procedure MT(var C: word); begin if TC<>0 then C:=(C and $ff0f) or (TC and $f0); end;
  1055. begin
  1056. if (Owner<>nil) then TC:=ord(Owner^.GetColor(6)) else TC:=0;
  1057. if State and (sfSelected + sfActive) = (sfSelected + sfActive) then
  1058. begin
  1059. NormalColor := GetColor(1);
  1060. FocusedColor := GetColor(3);
  1061. SelectedColor := GetColor(4);
  1062. end else
  1063. begin
  1064. NormalColor := GetColor(2);
  1065. SelectedColor := GetColor(4);
  1066. end;
  1067. if Transparent then
  1068. begin MT(NormalColor); MT(SelectedColor); end;
  1069. if NoSelection then
  1070. SelectedColor:=NormalColor;
  1071. if HScrollBar <> nil then Indent := HScrollBar^.Value
  1072. else Indent := 0;
  1073. ColWidth := Size.X div NumCols + 1;
  1074. for I := 0 to Size.Y - 1 do
  1075. begin
  1076. for J := 0 to NumCols-1 do
  1077. begin
  1078. Item := J*Size.Y + I + TopItem;
  1079. CurCol := J*ColWidth;
  1080. if (State and (sfSelected + sfActive) = (sfSelected + sfActive)) and
  1081. (Focused = Item) and (Range > 0) then
  1082. begin
  1083. Color := FocusedColor;
  1084. SetCursor(CurCol+1,I);
  1085. SCOff := 0;
  1086. end
  1087. else if (Item < Range) and IsSelected(Item) then
  1088. begin
  1089. Color := SelectedColor;
  1090. SCOff := 2;
  1091. end
  1092. else
  1093. begin
  1094. Color := NormalColor;
  1095. SCOff := 4;
  1096. end;
  1097. MoveChar(B[CurCol], ' ', Color, ColWidth);
  1098. if Item < Range then
  1099. begin
  1100. Text := GetText(Item, ColWidth + Indent);
  1101. Text := Copy(Text,Indent,ColWidth);
  1102. MoveStr(B[CurCol+1], Text, Color);
  1103. if ShowMarkers then
  1104. begin
  1105. WordRec(B[CurCol]).Lo := Byte(SpecialChars[SCOff]);
  1106. WordRec(B[CurCol+ColWidth-2]).Lo := Byte(SpecialChars[SCOff+1]);
  1107. end;
  1108. end;
  1109. MoveChar(B[CurCol+ColWidth-1], #179, GetColor(5), 1);
  1110. end;
  1111. WriteLine(0, I, Size.X, 1, B);
  1112. end;
  1113. end;
  1114. constructor TBreakpointsListBox.Load(var S: TStream);
  1115. begin
  1116. inherited Load(S);
  1117. end;
  1118. procedure TBreakpointsListBox.Store(var S: TStream);
  1119. var OL: PCollection;
  1120. OldR : integer;
  1121. begin
  1122. OL:=List;
  1123. OldR:=Range;
  1124. Range:=0;
  1125. New(List, Init(1,1));
  1126. inherited Store(S);
  1127. Dispose(List, Done);
  1128. Range:=OldR;
  1129. List:=OL;
  1130. { ^^^ nasty trick - has anyone a better idea how to avoid storing the
  1131. collection? Pasting here a modified version of TListBox.Store+
  1132. TAdvancedListBox.Store isn't a better solution, since by eventually
  1133. changing the obj-hierarchy you'll always have to modify this, too - BG }
  1134. end;
  1135. destructor TBreakpointsListBox.Done;
  1136. begin
  1137. inherited Done;
  1138. if List<>nil then Dispose(List, Done);
  1139. (* if ModuleNames<>nil then Dispose(ModuleNames, Done);*)
  1140. end;
  1141. {****************************************************************************
  1142. TBreakpointsWindow
  1143. ****************************************************************************}
  1144. constructor TBreakpointsWindow.Init;
  1145. var R,R2: TRect;
  1146. HSB,VSB: PScrollBar;
  1147. ST: PStaticText;
  1148. S: String;
  1149. X,X1 : Sw_integer;
  1150. const White = 15;
  1151. begin
  1152. Desktop^.GetExtent(R); R.A.Y:=R.B.Y-18;
  1153. inherited Init(R, 'Breakpoint list', wnNoNumber);
  1154. HelpCtx:=hcBreakpointListWindow;
  1155. GetExtent(R); R.Grow(-1,-1); R.B.Y:=R.A.Y+1;
  1156. S:=' Type | State | Position | Ignore | Conditions ';
  1157. New(ST, Init(R,S));
  1158. ST^.GrowMode:=gfGrowHiX;
  1159. Insert(ST);
  1160. GetExtent(R); R.Grow(-1,-1); Inc(R.A.Y,1); R.B.Y:=R.A.Y+1;
  1161. New(ST, Init(R, CharStr('Ä', MaxViewWidth)));
  1162. ST^.GrowMode:=gfGrowHiX;
  1163. Insert(ST);
  1164. GetExtent(R); R.Grow(-1,-1); Inc(R.A.Y,2);Dec(R.B.Y,5);
  1165. R2.Copy(R); Inc(R2.B.Y); R2.A.Y:=R2.B.Y-1;
  1166. New(HSB, Init(R2)); HSB^.GrowMode:=gfGrowLoY+gfGrowHiY+gfGrowHiX; Insert(HSB);
  1167. R2.Copy(R); Inc(R2.B.X); R2.A.X:=R2.B.X-1;
  1168. New(VSB, Init(R2)); VSB^.GrowMode:=gfGrowLoX+gfGrowHiX+gfGrowHiY; Insert(VSB);
  1169. New(BreakLB, Init(R,HSB,VSB));
  1170. BreakLB^.GrowMode:=gfGrowHiX+gfGrowHiY;
  1171. BreakLB^.Transparent:=true;
  1172. Insert(BreakLB);
  1173. GetExtent(R);R.Grow(-1,-1);
  1174. Dec(R.B.Y);
  1175. R.A.Y:=R.B.Y-2;
  1176. X:=(R.B.X-R.A.X) div 4;
  1177. X1:=R.A.X+(X div 2);
  1178. R.A.X:=X1-3;R.B.X:=X1+7;
  1179. Insert(New(PButton, Init(R, '~C~lose', cmClose, bfDefault)));
  1180. X1:=X1+X;
  1181. R.A.X:=X1-3;R.B.X:=X1+7;
  1182. Insert(New(PButton, Init(R, '~N~ew', cmNewBreakpoint, bfNormal)));
  1183. X1:=X1+X;
  1184. R.A.X:=X1-3;R.B.X:=X1+7;
  1185. Insert(New(PButton, Init(R, '~E~dit', cmEditBreakpoint, bfNormal)));
  1186. X1:=X1+X;
  1187. R.A.X:=X1-3;R.B.X:=X1+7;
  1188. Insert(New(PButton, Init(R, '~D~elete', cmDeleteBreakpoint, bfNormal)));
  1189. BreakLB^.Select;
  1190. Update;
  1191. BreakpointsWindow:=@self;
  1192. end;
  1193. constructor TBreakpointsWindow.Load(var S: TStream);
  1194. begin
  1195. inherited Load(S);
  1196. GetSubViewPtr(S,BreakLB);
  1197. end;
  1198. procedure TBreakpointsWindow.Store(var S: TStream);
  1199. begin
  1200. inherited Store(S);
  1201. PutSubViewPtr(S,BreakLB);
  1202. end;
  1203. procedure TBreakpointsWindow.AddBreakpoint(ABreakpoint : PBreakpoint);
  1204. begin
  1205. BreakLB^.AddBreakpoint(New(PBreakpointItem, Init(ABreakpoint)));
  1206. end;
  1207. procedure TBreakpointsWindow.ClearBreakpoints;
  1208. begin
  1209. BreakLB^.Clear;
  1210. ReDraw;
  1211. end;
  1212. procedure TBreakpointsWindow.ReloadBreakpoints;
  1213. procedure InsertInBreakLB(P : PBreakpoint);
  1214. begin
  1215. BreakLB^.AddBreakpoint(New(PBreakpointItem, Init(P)));
  1216. end;
  1217. begin
  1218. If not assigned(BreakpointCollection) then
  1219. exit;
  1220. BreakpointCollection^.ForEach(@InsertInBreakLB);
  1221. ReDraw;
  1222. end;
  1223. procedure TBreakpointsWindow.SizeLimits(var Min, Max: TPoint);
  1224. begin
  1225. inherited SizeLimits(Min,Max);
  1226. Min.X:=40; Min.Y:=18;
  1227. end;
  1228. procedure TBreakpointsWindow.Close;
  1229. begin
  1230. Hide;
  1231. end;
  1232. procedure TBreakpointsWindow.HandleEvent(var Event: TEvent);
  1233. var DontClear : boolean;
  1234. begin
  1235. case Event.What of
  1236. evKeyDown :
  1237. begin
  1238. if (Event.KeyCode=kbEnter) or (Event.KeyCode=kbEsc) then
  1239. begin
  1240. ClearEvent(Event);
  1241. Hide;
  1242. end;
  1243. end;
  1244. evCommand :
  1245. begin
  1246. DontClear:=False;
  1247. case Event.Command of
  1248. cmNewBreakpoint :
  1249. BreakLB^.EditNew;
  1250. cmEditBreakpoint :
  1251. BreakLB^.EditCurrent;
  1252. cmDeleteBreakpoint :
  1253. BreakLB^.DeleteCurrent;
  1254. cmClose :
  1255. Hide;
  1256. else
  1257. DontClear:=true;
  1258. end;
  1259. if not DontClear then
  1260. ClearEvent(Event);
  1261. end;
  1262. evBroadcast :
  1263. case Event.Command of
  1264. cmUpdate :
  1265. Update;
  1266. end;
  1267. end;
  1268. inherited HandleEvent(Event);
  1269. end;
  1270. procedure TBreakpointsWindow.Update;
  1271. begin
  1272. ClearBreakpoints;
  1273. ReloadBreakpoints;
  1274. end;
  1275. destructor TBreakpointsWindow.Done;
  1276. begin
  1277. inherited Done;
  1278. BreakpointsWindow:=nil;
  1279. end;
  1280. {****************************************************************************
  1281. TBreakpointItemDialog
  1282. ****************************************************************************}
  1283. constructor TBreakpointItemDialog.Init(ABreakpoint: PBreakpoint);
  1284. var R,R2,R3: TRect;
  1285. Items: PSItem;
  1286. I : BreakpointType;
  1287. KeyCount: sw_integer;
  1288. begin
  1289. KeyCount:=longint(high(BreakpointType));
  1290. R.Assign(0,0,60,Max(3+KeyCount,18));
  1291. inherited Init(R,'Modify/New Breakpoint');
  1292. Breakpoint:=ABreakpoint;
  1293. GetExtent(R); R.Grow(-3,-2); R3.Copy(R);
  1294. Inc(R.A.Y); R.B.Y:=R.A.Y+1; R.B.X:=R.A.X+36;
  1295. New(NameIL, Init(R, 128)); Insert(NameIL);
  1296. R2.Copy(R); R2.Move(-1,-1); Insert(New(PLabel, Init(R2, '~N~ame', NameIL)));
  1297. R.Move(0,3);
  1298. New(LineIL, Init(R, 128)); Insert(LineIL);
  1299. LineIL^.SetValidator(New(PRangeValidator, Init(0,MaxInt)));
  1300. R2.Copy(R); R2.Move(-1,-1); Insert(New(PLabel, Init(R2, '~L~ine', LineIL)));
  1301. R.Move(0,3);
  1302. New(ConditionsIL, Init(R, 128)); Insert(ConditionsIL);
  1303. R2.Copy(R); R2.Move(-1,-1); Insert(New(PLabel, Init(R2, 'Conditions', ConditionsIL)));
  1304. R.Move(0,3);
  1305. New(IgnoreIL, Init(R, 128)); Insert(IgnoreIL);
  1306. IgnoreIL^.SetValidator(New(PRangeValidator, Init(0,MaxInt)));
  1307. R2.Copy(R); R2.Move(-1,-1); Insert(New(PLabel, Init(R2, '~I~gnore count', IgnoreIL)));
  1308. R.Copy(R3); Inc(R.A.X,38); R.B.Y:=R.A.Y+KeyCount;
  1309. Items:=nil;
  1310. for I:=high(BreakpointType) downto low(BreakpointType) do
  1311. Items:=NewSItem(BreakpointTypeStr[I], Items);
  1312. New(TypeRB, Init(R, Items));
  1313. Insert(TypeRB);
  1314. InsertButtons(@Self);
  1315. NameIL^.Select;
  1316. end;
  1317. function TBreakpointItemDialog.Execute: Word;
  1318. var R: word;
  1319. S1: string;
  1320. err: word;
  1321. L: longint;
  1322. begin
  1323. R:=longint(Breakpoint^.typ);
  1324. TypeRB^.SetData(R);
  1325. If Breakpoint^.typ=bt_file_line then
  1326. S1:=GetStr(Breakpoint^.FileName)
  1327. else
  1328. S1:=GetStr(Breakpoint^.name);
  1329. NameIL^.SetData(S1);
  1330. If Breakpoint^.typ=bt_file_line then
  1331. S1:=IntToStr(Breakpoint^.Line)
  1332. else
  1333. S1:='0';
  1334. LineIL^.SetData(S1);
  1335. S1:=IntToStr(Breakpoint^.IgnoreCount);
  1336. IgnoreIL^.SetData(S1);
  1337. S1:=GetStr(Breakpoint^.Conditions);
  1338. ConditionsIL^.SetData(S1);
  1339. R:=inherited Execute;
  1340. if R=cmOK then
  1341. begin
  1342. TypeRB^.GetData(R);
  1343. L:=R;
  1344. Breakpoint^.typ:=BreakpointType(L);
  1345. NameIL^.GetData(S1);
  1346. If Breakpoint^.typ=bt_file_line then
  1347. begin
  1348. If assigned(Breakpoint^.FileName) then
  1349. DisposeStr(Breakpoint^.FileName);
  1350. Breakpoint^.FileName:=NewStr(S1);
  1351. end
  1352. else
  1353. begin
  1354. If assigned(Breakpoint^.Name) then
  1355. DisposeStr(Breakpoint^.Name);
  1356. Breakpoint^.name:=NewStr(S1);
  1357. end;
  1358. If Breakpoint^.typ=bt_file_line then
  1359. begin
  1360. LineIL^.GetData(S1);
  1361. Val(S1,L,err);
  1362. Breakpoint^.Line:=L;
  1363. end;
  1364. IgnoreIL^.GetData(S1);
  1365. Val(S1,L,err);
  1366. Breakpoint^.IgnoreCount:=L;
  1367. ConditionsIL^.GetData(S1);
  1368. If assigned(Breakpoint^.Conditions) then
  1369. DisposeStr(Breakpoint^.Conditions);
  1370. Breakpoint^.Conditions:=NewStr(S1);
  1371. end;
  1372. Execute:=R;
  1373. end;
  1374. {****************************************************************************
  1375. TWatch
  1376. ****************************************************************************}
  1377. constructor TWatch.Init(s : string);
  1378. begin
  1379. expr:=NewStr(s);
  1380. last_value:=nil;
  1381. current_value:=nil;
  1382. Get_new_value;
  1383. end;
  1384. procedure TWatch.rename(s : string);
  1385. begin
  1386. if assigned(expr) then
  1387. begin
  1388. if GetStr(expr)=S then
  1389. exit;
  1390. DisposeStr(expr);
  1391. end;
  1392. expr:=NewStr(s);
  1393. if assigned(last_value) then
  1394. StrDispose(last_value);
  1395. last_value:=nil;
  1396. if assigned(current_value) then
  1397. StrDispose(current_value);
  1398. current_value:=nil;
  1399. Get_new_value;
  1400. end;
  1401. procedure TWatch.Get_new_value;
  1402. var p,q : pchar;
  1403. i : longint;
  1404. last_removed : boolean;
  1405. begin
  1406. If not assigned(Debugger) then
  1407. exit;
  1408. if assigned(last_value) then
  1409. strdispose(last_value);
  1410. last_value:=current_value;
  1411. Debugger^.Command('p '+GetStr(expr));
  1412. if Debugger^.Error then
  1413. p:=StrNew(Debugger^.GetError)
  1414. else
  1415. p:=StrNew(Debugger^.GetOutput);
  1416. { do not open a messagebox for such errors }
  1417. Debugger^.got_error:=false;
  1418. q:=nil;
  1419. if assigned(p) and (p[0]='$') then
  1420. q:=StrPos(p,'=');
  1421. if not assigned(q) then
  1422. q:=p;
  1423. if assigned(q) then
  1424. i:=strlen(q)
  1425. else
  1426. i:=0;
  1427. if (i>0) and (q[i-1]=#10) then
  1428. begin
  1429. q[i-1]:=#0;
  1430. last_removed:=true;
  1431. end
  1432. else
  1433. last_removed:=false;
  1434. if assigned(q) then
  1435. current_value:=strnew(q)
  1436. else
  1437. current_value:=strnew('');
  1438. if last_removed then
  1439. q[i-1]:=#10;
  1440. strdispose(p);
  1441. end;
  1442. destructor TWatch.Done;
  1443. begin
  1444. if assigned(expr) then
  1445. disposestr(expr);
  1446. if assigned(last_value) then
  1447. strdispose(last_value);
  1448. if assigned(current_value) then
  1449. strdispose(current_value);
  1450. inherited done;
  1451. end;
  1452. {****************************************************************************
  1453. TWatchesCollection
  1454. ****************************************************************************}
  1455. constructor TWatchesCollection.Init;
  1456. begin
  1457. inherited Init(10,10);
  1458. end;
  1459. procedure TWatchesCollection.Insert(Item: Pointer);
  1460. begin
  1461. PWatch(Item)^.Get_new_value;
  1462. Inherited Insert(Item);
  1463. Update;
  1464. end;
  1465. procedure TWatchesCollection.Update;
  1466. var
  1467. W,W1 : integer;
  1468. procedure GetMax(P : PWatch);
  1469. begin
  1470. if assigned(P^.Current_value) then
  1471. begin
  1472. W1:=StrLen(P^.Current_value)+2+Length(GetStr(P^.expr));
  1473. if W1>W then
  1474. W:=W1;
  1475. end;
  1476. end;
  1477. begin
  1478. W:=0;
  1479. ForEach(@GetMax);
  1480. MaxW:=W;
  1481. If assigned(WatchesWindow) then
  1482. WatchesWindow^.WLB^.Update(MaxW);
  1483. end;
  1484. function TWatchesCollection.At(Index: Integer): PWatch;
  1485. begin
  1486. At:=Inherited At(Index);
  1487. end;
  1488. {****************************************************************************
  1489. TWatchesListBox
  1490. ****************************************************************************}
  1491. (* PWatchesListBox = ^TWatchesListBox;
  1492. TWatchesListBox = object(THSListBox)
  1493. MaxWidth : Sw_integer; *)
  1494. constructor TWatchesListBox.Init(var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar);
  1495. begin
  1496. inherited Init(Bounds,1,AHScrollBar,AVScrollBar);
  1497. If assigned(List) then
  1498. dispose(list,done);
  1499. List:=WatchesCollection;
  1500. end;
  1501. procedure TWatchesListBox.Update(AMaxWidth : integer);
  1502. var R : TRect;
  1503. begin
  1504. GetExtent(R);
  1505. MaxWidth:=AMaxWidth;
  1506. if HScrollBar<>nil then
  1507. HScrollBar^.SetRange(0,MaxWidth);
  1508. if R.B.X-R.A.X>MaxWidth then
  1509. HScrollBar^.Hide
  1510. else
  1511. HScrollBar^.Show;
  1512. SetRange(List^.Count);
  1513. if R.B.Y-R.A.Y>Range then
  1514. VScrollBar^.Hide
  1515. else
  1516. VScrollBar^.Show;
  1517. if Focused=List^.Count-1-1 then
  1518. FocusItem(List^.Count-1);
  1519. DrawView;
  1520. end;
  1521. function TWatchesListBox.GetIndentedText(Item,Indent,MaxLen: Sw_Integer): String;
  1522. var
  1523. PW : PWatch;
  1524. ValOffset : Sw_integer;
  1525. S : String;
  1526. begin
  1527. PW:=WatchesCollection^.At(Item);
  1528. ValOffset:=Length(GetStr(PW^.Expr))+2;
  1529. if Indent<ValOffset then
  1530. begin
  1531. if not assigned(PW^.current_value) then
  1532. S:=' '+GetStr(PW^.Expr)+' <Unknown value>'
  1533. else if not assigned(PW^.last_value) or
  1534. (strcomp(PW^.Last_value,PW^.Current_value)=0) then
  1535. S:=' '+GetStr(PW^.Expr)+' '+StrPas(PW^.Current_value)
  1536. else
  1537. S:='!'+GetStr(PW^.Expr)+'!'+StrPas(PW^.Current_value);
  1538. GetIndentedText:=Copy(S,Indent,MaxLen);
  1539. end
  1540. else
  1541. begin
  1542. if not assigned(PW^.Current_value) or
  1543. (StrLen(PW^.Current_value)<Indent-Valoffset) then
  1544. S:=''
  1545. else
  1546. S:=StrPas(@(PW^.Current_Value[Indent-Valoffset]));
  1547. GetIndentedText:=Copy(S,1,MaxLen);
  1548. end;
  1549. end;
  1550. (* function TWatchesListBox.GetLocalMenu: PMenu;virtual;
  1551. procedure TWatchesListBox.Clear; virtual;
  1552. procedure TWatchesListBox.TrackSource; virtual;
  1553. procedure TWatchesListBox.EditNew; virtual;
  1554. procedure TWatchesListBox.EditCurrent; virtual;
  1555. procedure TWatchesListBox.DeleteCurrent; virtual;
  1556. procedure TWatchesListBox.ToggleCurrent; *)
  1557. procedure TWatchesListBox.EditCurrent;
  1558. var
  1559. P: PWatch;
  1560. begin
  1561. if Range=0 then Exit;
  1562. P:=WatchesCollection^.At(Focused);
  1563. if P=nil then Exit;
  1564. Application^.ExecuteDialog(New(PWatchItemDialog,Init(P)),nil);
  1565. WatchesCollection^.Update;
  1566. end;
  1567. procedure TWatchesListBox.DeleteCurrent;
  1568. var
  1569. P: PWatch;
  1570. begin
  1571. if Range=0 then Exit;
  1572. P:=WatchesCollection^.At(Focused);
  1573. if P=nil then Exit;
  1574. WatchesCollection^.free(P);
  1575. WatchesCollection^.Update;
  1576. end;
  1577. procedure TWatchesListBox.EditNew;
  1578. var
  1579. P: PWatch;
  1580. begin
  1581. P:=New(PWatch,Init(''));
  1582. if Application^.ExecuteDialog(New(PWatchItemDialog,Init(P)),nil)<>cmCancel then
  1583. begin
  1584. WatchesCollection^.Insert(P);
  1585. WatchesCollection^.Update;
  1586. end
  1587. else
  1588. dispose(P,Done);
  1589. end;
  1590. procedure TWatchesListBox.Draw;
  1591. var
  1592. I, J, Item: Sw_Integer;
  1593. NormalColor, SelectedColor, FocusedColor, Color: Word;
  1594. ColWidth, CurCol, Indent: Integer;
  1595. B: TDrawBuffer;
  1596. Text: String;
  1597. SCOff: Byte;
  1598. TC: byte;
  1599. procedure MT(var C: word); begin if TC<>0 then C:=(C and $ff0f) or (TC and $f0); end;
  1600. begin
  1601. if (Owner<>nil) then TC:=ord(Owner^.GetColor(6)) else TC:=0;
  1602. if State and (sfSelected + sfActive) = (sfSelected + sfActive) then
  1603. begin
  1604. NormalColor := GetColor(1);
  1605. FocusedColor := GetColor(3);
  1606. SelectedColor := GetColor(4);
  1607. end else
  1608. begin
  1609. NormalColor := GetColor(2);
  1610. SelectedColor := GetColor(4);
  1611. end;
  1612. if Transparent then
  1613. begin MT(NormalColor); MT(SelectedColor); end;
  1614. (* if NoSelection then
  1615. SelectedColor:=NormalColor;*)
  1616. if HScrollBar <> nil then Indent := HScrollBar^.Value
  1617. else Indent := 0;
  1618. ColWidth := Size.X div NumCols + 1;
  1619. for I := 0 to Size.Y - 1 do
  1620. begin
  1621. for J := 0 to NumCols-1 do
  1622. begin
  1623. Item := J*Size.Y + I + TopItem;
  1624. CurCol := J*ColWidth;
  1625. if (State and (sfSelected + sfActive) = (sfSelected + sfActive)) and
  1626. (Focused = Item) and (Range > 0) then
  1627. begin
  1628. Color := FocusedColor;
  1629. SetCursor(CurCol+1,I);
  1630. SCOff := 0;
  1631. end
  1632. else if (Item < Range) and IsSelected(Item) then
  1633. begin
  1634. Color := SelectedColor;
  1635. SCOff := 2;
  1636. end
  1637. else
  1638. begin
  1639. Color := NormalColor;
  1640. SCOff := 4;
  1641. end;
  1642. MoveChar(B[CurCol], ' ', Color, ColWidth);
  1643. if Item < Range then
  1644. begin
  1645. (* Text := GetText(Item, ColWidth + Indent);
  1646. Text := Copy(Text,Indent,ColWidth); *)
  1647. Text:=GetIndentedText(Item,Indent,ColWidth);
  1648. MoveStr(B[CurCol+1], Text, Color);
  1649. if ShowMarkers then
  1650. begin
  1651. WordRec(B[CurCol]).Lo := Byte(SpecialChars[SCOff]);
  1652. WordRec(B[CurCol+ColWidth-2]).Lo := Byte(SpecialChars[SCOff+1]);
  1653. end;
  1654. end;
  1655. MoveChar(B[CurCol+ColWidth-1], #179, GetColor(5), 1);
  1656. end;
  1657. WriteLine(0, I, Size.X, 1, B);
  1658. end;
  1659. end;
  1660. function TWatchesListBox.GetLocalMenu: PMenu;
  1661. var M: PMenu;
  1662. begin
  1663. if (Owner<>nil) and (Owner^.GetState(sfModal)) then M:=nil else
  1664. M:=NewMenu(
  1665. NewItem('~E~dit watch','',kbNoKey,cmEdit,hcNoContext,
  1666. NewItem('~N~ew watch','',kbNoKey,cmNew,hcNoContext,
  1667. NewItem('~D~elete watch','',kbNoKey,cmDelete,hcNoContext,
  1668. nil))));
  1669. GetLocalMenu:=M;
  1670. end;
  1671. procedure TWatchesListBox.HandleEvent(var Event: TEvent);
  1672. var DontClear: boolean;
  1673. begin
  1674. case Event.What of
  1675. evKeyDown :
  1676. begin
  1677. DontClear:=false;
  1678. case Event.KeyCode of
  1679. kbEnter :
  1680. Message(@Self,evCommand,cmEdit,nil);
  1681. kbIns :
  1682. Message(@Self,evCommand,cmNew,nil);
  1683. kbDel :
  1684. Message(@Self,evCommand,cmDelete,nil);
  1685. else
  1686. DontClear:=true;
  1687. end;
  1688. if not DontClear then
  1689. ClearEvent(Event);
  1690. end;
  1691. evBroadcast :
  1692. case Event.Command of
  1693. cmListItemSelected :
  1694. if Event.InfoPtr=@Self then
  1695. Message(@Self,evCommand,cmEdit,nil);
  1696. end;
  1697. evCommand :
  1698. begin
  1699. DontClear:=false;
  1700. case Event.Command of
  1701. cmEdit :
  1702. EditCurrent;
  1703. cmDelete :
  1704. DeleteCurrent;
  1705. cmNew :
  1706. EditNew;
  1707. else
  1708. DontClear:=true;
  1709. end;
  1710. if not DontClear then
  1711. ClearEvent(Event);
  1712. end;
  1713. end;
  1714. inherited HandleEvent(Event);
  1715. end;
  1716. constructor TWatchesListBox.Load(var S: TStream);
  1717. begin
  1718. inherited Load(S);
  1719. If assigned(List) then
  1720. dispose(list,done);
  1721. List:=WatchesCollection;
  1722. { we must set Range PM }
  1723. SetRange(List^.count);
  1724. end;
  1725. procedure TWatchesListBox.Store(var S: TStream);
  1726. var OL: PCollection;
  1727. OldRange : Sw_integer;
  1728. begin
  1729. OL:=List;
  1730. OldRange:=Range;
  1731. Range:=0;
  1732. New(List, Init(1,1));
  1733. inherited Store(S);
  1734. Dispose(List, Done);
  1735. List:=OL;
  1736. { ^^^ nasty trick - has anyone a better idea how to avoid storing the
  1737. collection? Pasting here a modified version of TListBox.Store+
  1738. TAdvancedListBox.Store isn't a better solution, since by eventually
  1739. changing the obj-hierarchy you'll always have to modify this, too - BG }
  1740. SetRange(OldRange);
  1741. end;
  1742. destructor TWatchesListBox.Done;
  1743. begin
  1744. List:=nil;
  1745. inherited Done;
  1746. end;
  1747. {****************************************************************************
  1748. TWatchesWindow
  1749. ****************************************************************************}
  1750. Constructor TWatchesWindow.Init;
  1751. var
  1752. HSB,VSB: PScrollBar;
  1753. R,R2 : trect;
  1754. begin
  1755. Desktop^.GetExtent(R);
  1756. R.A.Y:=R.B.Y-5;
  1757. inherited Init(R, 'Watches', wnNoNumber);
  1758. GetExtent(R);
  1759. HelpCtx:=hcWatches;
  1760. R.Grow(-1,-1);
  1761. R2.Copy(R);
  1762. Inc(R2.B.Y);
  1763. R2.A.Y:=R2.B.Y-1;
  1764. New(HSB, Init(R2));
  1765. HSB^.GrowMode:=gfGrowLoY+gfGrowHiY+gfGrowHiX;
  1766. Insert(HSB);
  1767. R2.Copy(R);
  1768. Inc(R2.B.X);
  1769. R2.A.X:=R2.B.X-1;
  1770. New(VSB, Init(R2));
  1771. VSB^.GrowMode:=gfGrowLoX+gfGrowHiX+gfGrowHiY;
  1772. Insert(VSB);
  1773. New(WLB,Init(R,HSB,VSB));
  1774. WLB^.GrowMode:=gfGrowHiX+gfGrowHiY;
  1775. WLB^.Transparent:=true;
  1776. Insert(WLB);
  1777. If assigned(WatchesWindow) then
  1778. dispose(WatchesWindow,done);
  1779. WatchesWindow:=@Self;
  1780. Update;
  1781. end;
  1782. procedure TWatchesWindow.Update;
  1783. begin
  1784. WatchesCollection^.Update;
  1785. Draw;
  1786. end;
  1787. constructor TWatchesWindow.Load(var S: TStream);
  1788. begin
  1789. inherited Load(S);
  1790. GetSubViewPtr(S,WLB);
  1791. end;
  1792. procedure TWatchesWindow.Store(var S: TStream);
  1793. begin
  1794. inherited Store(S);
  1795. PutSubViewPtr(S,WLB);
  1796. end;
  1797. Destructor TWatchesWindow.Done;
  1798. begin
  1799. WatchesWindow:=nil;
  1800. Dispose(WLB,done);
  1801. inherited done;
  1802. end;
  1803. {****************************************************************************
  1804. TWatchItemDialog
  1805. ****************************************************************************}
  1806. (* TWatchItemDialog = object(TCenterDialog)
  1807. constructor Init(AWatch: PWatch);
  1808. function Execute: Word; virtual;
  1809. private
  1810. Watch : PWatch;
  1811. NameIL : PInputLine;
  1812. TextST : PAdvancedStaticText;
  1813. CurrentIL: PLabel;
  1814. LastIL : PLabel;
  1815. end; *)
  1816. constructor TWatchItemDialog.Init(AWatch: PWatch);
  1817. var R,R2: TRect;
  1818. begin
  1819. R.Assign(0,0,50,10);
  1820. inherited Init(R,'Edit Watch');
  1821. Watch:=AWatch;
  1822. GetExtent(R); R.Grow(-3,-2);
  1823. Inc(R.A.Y); R.B.Y:=R.A.Y+1; R.B.X:=R.A.X+36;
  1824. New(NameIL, Init(R, 255)); Insert(NameIL);
  1825. R2.Copy(R); R2.Move(-1,-1);
  1826. Insert(New(PLabel, Init(R2, '~E~xpression to watch', NameIL)));
  1827. GetExtent(R);
  1828. R.Grow(-1,-1);
  1829. R.A.Y:=R.A.Y+3;
  1830. R.B.X:=R.A.X+36;
  1831. TextST:=New(PAdvancedStaticText, Init(R, 'Watch values'));
  1832. Insert(TextST);
  1833. InsertButtons(@Self);
  1834. NameIL^.Select;
  1835. end;
  1836. function TWatchItemDialog.Execute: Word;
  1837. var R: word;
  1838. S1,S2: string;
  1839. begin
  1840. S1:=GetStr(Watch^.expr);
  1841. NameIL^.SetData(S1);
  1842. if assigned(Watch^.Current_value) then
  1843. S1:=StrPas(Watch^.Current_value)
  1844. else
  1845. S1:='';
  1846. if assigned(Watch^.Last_value) then
  1847. S2:=StrPas(Watch^.Last_value)
  1848. else
  1849. S2:='';
  1850. if assigned(Watch^.Last_value) and
  1851. assigned(Watch^.Current_value) and
  1852. (strcomp(Watch^.Last_value,Watch^.Current_value)=0) then
  1853. S1:='Current value: '+#13+S1
  1854. else
  1855. S1:='Current value: '+#13+S1+#13+
  1856. 'Previous value: '+#13+S2;
  1857. TextST^.SetText(S1);
  1858. R:=inherited Execute;
  1859. if R=cmOK then
  1860. begin
  1861. NameIL^.GetData(S1);
  1862. Watch^.Rename(S1);
  1863. If assigned(Debugger) then
  1864. Debugger^.ReadWatches;
  1865. end;
  1866. Execute:=R;
  1867. end;
  1868. {****************************************************************************
  1869. TStackWindow
  1870. ****************************************************************************}
  1871. constructor TFramesListBox.Init(var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar);
  1872. begin
  1873. Inherited Init(Bounds,AHScrollBar,AVScrollBar);
  1874. end;
  1875. procedure TFramesListBox.Update;
  1876. var i : longint;
  1877. begin
  1878. { call backtrace command }
  1879. If not assigned(Debugger) then
  1880. exit;
  1881. Clear;
  1882. { forget all old frames }
  1883. Debugger^.clear_frames;
  1884. Debugger^.Command('backtrace');
  1885. { generate list }
  1886. { all is in tframeentry }
  1887. for i:=0 to Debugger^.frame_count-1 do
  1888. begin
  1889. with Debugger^.frames[i]^ do
  1890. begin
  1891. AddItem(new(PMessageItem,init(0,StrPas(function_name)+StrPas(args),
  1892. AddModuleName(StrPas(file_name)),line_number,1)));
  1893. end;
  1894. end;
  1895. if List^.Count > 0 then
  1896. FocusItem(0);
  1897. end;
  1898. function TFramesListBox.GetLocalMenu: PMenu;
  1899. begin
  1900. GetLocalMenu:=Inherited GetLocalMenu;
  1901. end;
  1902. procedure TFramesListBox.GotoSource;
  1903. begin
  1904. { select frame for watches }
  1905. If not assigned(Debugger) then
  1906. exit;
  1907. Debugger^.Command('f '+IntToStr(Focused));
  1908. { for local vars }
  1909. Debugger^.ReadWatches;
  1910. { goto source }
  1911. inherited GotoSource;
  1912. end;
  1913. procedure TFramesListBox.HandleEvent(var Event: TEvent);
  1914. begin
  1915. inherited HandleEvent(Event);
  1916. end;
  1917. destructor TFramesListBox.Done;
  1918. begin
  1919. Inherited Done;
  1920. end;
  1921. Constructor TStackWindow.Init;
  1922. var
  1923. HSB,VSB: PScrollBar;
  1924. R,R2 : trect;
  1925. begin
  1926. Desktop^.GetExtent(R);
  1927. R.A.Y:=R.B.Y-5;
  1928. inherited Init(R, 'Call Stack', wnNoNumber);
  1929. GetExtent(R);
  1930. HelpCtx:=hcStack;
  1931. R.Grow(-1,-1);
  1932. R2.Copy(R);
  1933. Inc(R2.B.Y);
  1934. R2.A.Y:=R2.B.Y-1;
  1935. New(HSB, Init(R2));
  1936. HSB^.GrowMode:=gfGrowLoY+gfGrowHiY+gfGrowHiX;
  1937. Insert(HSB);
  1938. R2.Copy(R);
  1939. Inc(R2.B.X);
  1940. R2.A.X:=R2.B.X-1;
  1941. New(VSB, Init(R2));
  1942. VSB^.GrowMode:=gfGrowLoX+gfGrowHiX+gfGrowHiY;
  1943. Insert(VSB);
  1944. New(FLB,Init(R,HSB,VSB));
  1945. FLB^.GrowMode:=gfGrowHiX+gfGrowHiY;
  1946. Insert(FLB);
  1947. If assigned(StackWindow) then
  1948. dispose(StackWindow,done);
  1949. StackWindow:=@Self;
  1950. Update;
  1951. end;
  1952. procedure TStackWindow.Update;
  1953. begin
  1954. FLB^.Update;
  1955. DrawView;
  1956. end;
  1957. constructor TStackWindow.Load(var S: TStream);
  1958. begin
  1959. inherited Load(S);
  1960. GetSubViewPtr(S,FLB);
  1961. end;
  1962. procedure TStackWindow.Store(var S: TStream);
  1963. begin
  1964. inherited Store(S);
  1965. PutSubViewPtr(S,FLB);
  1966. end;
  1967. Destructor TStackWindow.Done;
  1968. begin
  1969. StackWindow:=nil;
  1970. Dispose(FLB,done);
  1971. inherited done;
  1972. end;
  1973. {****************************************************************************
  1974. Init/Final
  1975. ****************************************************************************}
  1976. procedure InitDebugger;
  1977. begin
  1978. {$ifdef DEBUG}
  1979. Assign(gdb_file,GDBOutFileName);
  1980. Rewrite(gdb_file);
  1981. Use_gdb_file:=true;
  1982. {$endif}
  1983. if (not ExistsFile(ExeFile)) or (CompilationPhase<>cpDone) then
  1984. DoCompile(cRun);
  1985. if CompilationPhase<>cpDone then
  1986. Exit;
  1987. if (EXEFile='') then
  1988. begin
  1989. ErrorBox('Oooops, nothing to debug.',nil);
  1990. Exit;
  1991. end;
  1992. { init debugcontroller }
  1993. if assigned(Debugger) then
  1994. dispose(Debugger,Done);
  1995. new(Debugger,Init(ExeFile));
  1996. {$ifdef GDBWINDOW}
  1997. InitGDBWindow;
  1998. {$endif def GDBWINDOW}
  1999. end;
  2000. procedure DoneDebugger;
  2001. begin
  2002. if assigned(Debugger) then
  2003. dispose(Debugger,Done);
  2004. Debugger:=nil;
  2005. {$ifdef DEBUG}
  2006. If Use_gdb_file then
  2007. Close(GDB_file);
  2008. Use_gdb_file:=false;
  2009. {$endif}
  2010. {DoneGDBWindow;}
  2011. end;
  2012. procedure InitGDBWindow;
  2013. var
  2014. R : TRect;
  2015. begin
  2016. if GDBWindow=nil then
  2017. begin
  2018. DeskTop^.GetExtent(R);
  2019. new(GDBWindow,init(R));
  2020. DeskTop^.Insert(GDBWindow);
  2021. end;
  2022. end;
  2023. procedure DoneGDBWindow;
  2024. begin
  2025. if assigned(GDBWindow) then
  2026. begin
  2027. DeskTop^.Delete(GDBWindow);
  2028. GDBWindow:=nil;
  2029. end;
  2030. end;
  2031. procedure InitStackWindow;
  2032. begin
  2033. if StackWindow=nil then
  2034. begin
  2035. new(StackWindow,init);
  2036. DeskTop^.Insert(StackWindow);
  2037. end;
  2038. end;
  2039. procedure DoneStackWindow;
  2040. begin
  2041. if assigned(StackWindow) then
  2042. begin
  2043. DeskTop^.Delete(StackWindow);
  2044. StackWindow:=nil;
  2045. end;
  2046. end;
  2047. procedure InitBreakpoints;
  2048. begin
  2049. New(BreakpointCollection,init(10,10));
  2050. end;
  2051. procedure DoneBreakpoints;
  2052. begin
  2053. Dispose(BreakpointCollection,Done);
  2054. BreakpointCollection:=nil;
  2055. end;
  2056. procedure InitWatches;
  2057. begin
  2058. New(WatchesCollection,init);
  2059. end;
  2060. procedure DoneWatches;
  2061. begin
  2062. Dispose(WatchesCollection,Done);
  2063. WatchesCollection:=nil;
  2064. end;
  2065. procedure RegisterFPDebugViews;
  2066. begin
  2067. RegisterType(RWatchesWindow);
  2068. RegisterType(RBreakpointsWindow);
  2069. RegisterType(RWatchesListBox);
  2070. RegisterType(RBreakpointsListBox);
  2071. RegisterType(RStackWindow);
  2072. RegisterType(RFramesListBox);
  2073. end;
  2074. end.
  2075. {
  2076. $Log$
  2077. Revision 1.30 1999-09-09 16:36:30 pierre
  2078. * Breakpoint storage problem corrected
  2079. Revision 1.29 1999/09/09 16:31:45 pierre
  2080. * some breakpoint related fixes and Help contexts
  2081. Revision 1.28 1999/09/09 14:20:05 pierre
  2082. + Stack Window
  2083. Revision 1.27 1999/08/24 22:04:33 pierre
  2084. + TCodeEditor.SetDebuggerRow
  2085. works like SetHighlightRow but is only disposed by a SetDebuggerRow(-1)
  2086. so the current stop point in debugging is not lost if
  2087. we move the cursor
  2088. Revision 1.26 1999/08/22 22:26:48 pierre
  2089. + Registration of Breakpoint/Watches windows
  2090. Revision 1.25 1999/08/16 18:25:15 peter
  2091. * Adjusting the selection when the editor didn't contain any line.
  2092. * Reserved word recognition redesigned, but this didn't affect the overall
  2093. syntax highlight speed remarkably (at least not on my Amd-K6/350).
  2094. The syntax scanner loop is a bit slow but the main problem is the
  2095. recognition of special symbols. Switching off symbol processing boosts
  2096. the performance up to ca. 200%...
  2097. * The editor didn't allow copying (for ex to clipboard) of a single character
  2098. * 'File|Save as' caused permanently run-time error 3. Not any more now...
  2099. * Compiler Messages window (actually the whole desktop) did not act on any
  2100. keypress when compilation failed and thus the window remained visible
  2101. + Message windows are now closed upon pressing Esc
  2102. + At 'Run' the IDE checks whether any sources are modified, and recompiles
  2103. only when neccessary
  2104. + BlockRead and BlockWrite (Ctrl+K+R/W) implemented in TCodeEditor
  2105. + LineSelect (Ctrl+K+L) implemented
  2106. * The IDE had problems closing help windows before saving the desktop
  2107. Revision 1.24 1999/08/03 20:22:28 peter
  2108. + TTab acts now on Ctrl+Tab and Ctrl+Shift+Tab...
  2109. + Desktop saving should work now
  2110. - History saved
  2111. - Clipboard content saved
  2112. - Desktop saved
  2113. - Symbol info saved
  2114. * syntax-highlight bug fixed, which compared special keywords case sensitive
  2115. (for ex. 'asm' caused asm-highlighting, while 'ASM' didn't)
  2116. * with 'whole words only' set, the editor didn't found occourences of the
  2117. searched text, if the text appeared previously in the same line, but didn't
  2118. satisfied the 'whole-word' condition
  2119. * ^QB jumped to (SelStart.X,SelEnd.X) instead of (SelStart.X,SelStart.Y)
  2120. (ie. the beginning of the selection)
  2121. * when started typing in a new line, but not at the start (X=0) of it,
  2122. the editor inserted the text one character more to left as it should...
  2123. * TCodeEditor.HideSelection (Ctrl-K+H) didn't update the screen
  2124. * Shift shouldn't cause so much trouble in TCodeEditor now...
  2125. * Syntax highlight had problems recognizing a special symbol if it was
  2126. prefixed by another symbol character in the source text
  2127. * Auto-save also occours at Dos shell, Tool execution, etc. now...
  2128. Revision 1.23 1999/07/28 23:11:17 peter
  2129. * fixes from gabor
  2130. Revision 1.22 1999/07/12 13:14:15 pierre
  2131. * LineEnd bug corrected, now goes end of text even if selected
  2132. + Until Return for debugger
  2133. + Code for Quit inside GDB Window
  2134. Revision 1.21 1999/07/11 00:35:14 pierre
  2135. * fix problems for wrong watches
  2136. Revision 1.20 1999/07/10 01:24:14 pierre
  2137. + First implementation of watches window
  2138. Revision 1.19 1999/06/30 23:58:12 pierre
  2139. + BreakpointsList Window implemented
  2140. with Edit/New/Delete functions
  2141. + Individual breakpoint dialog with support for all types
  2142. ignorecount and conditions
  2143. (commands are not yet implemented, don't know if this wolud be useful)
  2144. awatch and rwatch have problems because GDB does not annotate them
  2145. I fixed v4.16 for this
  2146. Revision 1.18 1999/03/16 00:44:42 peter
  2147. * forgotten in last commit :(
  2148. Revision 1.17 1999/03/02 13:48:28 peter
  2149. * fixed far problem is fpdebug
  2150. * tile/cascading with message window
  2151. * grep fixes
  2152. Revision 1.16 1999/03/01 15:41:52 peter
  2153. + Added dummy entries for functions not yet implemented
  2154. * MenuBar didn't update itself automatically on command-set changes
  2155. * Fixed Debugging/Profiling options dialog
  2156. * TCodeEditor converts spaces to tabs at save only if efUseTabChars is
  2157. set
  2158. * efBackSpaceUnindents works correctly
  2159. + 'Messages' window implemented
  2160. + Added '$CAP MSG()' and '$CAP EDIT' to available tool-macros
  2161. + Added TP message-filter support (for ex. you can call GREP thru
  2162. GREP2MSG and view the result in the messages window - just like in TP)
  2163. * A 'var' was missing from the param-list of THelpFacility.TopicSearch,
  2164. so topic search didn't work...
  2165. * In FPHELP.PAS there were still context-variables defined as word instead
  2166. of THelpCtx
  2167. * StdStatusKeys() was missing from the statusdef for help windows
  2168. + Topic-title for index-table can be specified when adding a HTML-files
  2169. Revision 1.15 1999/02/20 15:18:29 peter
  2170. + ctrl-c capture with confirm dialog
  2171. + ascii table in the tools menu
  2172. + heapviewer
  2173. * empty file fixed
  2174. * fixed callback routines in fpdebug to have far for tp7
  2175. Revision 1.14 1999/02/16 12:47:36 pierre
  2176. * GDBWindow does not popup on F7 or F8 anymore
  2177. Revision 1.13 1999/02/16 10:43:54 peter
  2178. * use -dGDB for the compiler
  2179. * only use gdb_file when -dDEBUG is used
  2180. * profiler switch is now a toggle instead of radiobutton
  2181. Revision 1.12 1999/02/11 19:07:20 pierre
  2182. * GDBWindow redesigned :
  2183. normal editor apart from
  2184. that any kbEnter will send the line (for begin to cursor)
  2185. to GDB command !
  2186. GDBWindow opened in Debugger Menu
  2187. still buggy :
  2188. -echo should not be present if at end of text
  2189. -GDBWindow becomes First after each step (I don't know why !)
  2190. Revision 1.11 1999/02/11 13:10:03 pierre
  2191. + GDBWindow only with -dGDBWindow for now : still buggy !!
  2192. Revision 1.10 1999/02/10 09:55:07 pierre
  2193. + added OldValue and CurrentValue field for watchpoints
  2194. + InitBreakpoints and DoneBreakpoints
  2195. + MessageBox if GDB stops bacause of a watchpoint !
  2196. Revision 1.9 1999/02/08 17:43:43 pierre
  2197. * RestDebugger or multiple running of debugged program now works
  2198. + added DoContToCursor(F4)
  2199. * Breakpoints are now inserted correctly (was mainlyy a problem
  2200. of directories)
  2201. Revision 1.8 1999/02/05 17:21:52 pierre
  2202. Invalid_line renamed InvalidSourceLine
  2203. Revision 1.7 1999/02/05 13:08:41 pierre
  2204. + new breakpoint types added
  2205. Revision 1.6 1999/02/05 12:11:53 pierre
  2206. + SourceDir that stores directories for sources that the
  2207. compiler should not know about
  2208. Automatically asked for addition when a new file that
  2209. needed filedialog to be found is in an unknown directory
  2210. Stored and retrieved from INIFile
  2211. + Breakpoints conditions added to INIFile
  2212. * Breakpoints insterted and removed at debin and end of debug session
  2213. Revision 1.5 1999/02/04 17:54:22 pierre
  2214. + several commands added
  2215. Revision 1.4 1999/02/04 13:32:02 pierre
  2216. * Several things added (I cannot commit them independently !)
  2217. + added TBreakpoint and TBreakpointCollection
  2218. + added cmResetDebugger,cmGrep,CmToggleBreakpoint
  2219. + Breakpoint list in INIFile
  2220. * Select items now also depend of SwitchMode
  2221. * Reading of option '-g' was not possible !
  2222. + added search for -Fu args pathes in TryToOpen
  2223. + added code for automatic opening of FileDialog
  2224. if source not found
  2225. Revision 1.3 1999/02/02 16:41:38 peter
  2226. + automatic .pas/.pp adding by opening of file
  2227. * better debuggerscreen changes
  2228. Revision 1.2 1999/01/22 18:14:09 pierre
  2229. * adaptd to changes in gdbint and gdbcon for to /
  2230. Revision 1.1 1999/01/22 10:24:03 peter
  2231. * first debugger things
  2232. }