fpdebug.pas 95 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659
  1. {
  2. $Id$
  3. This file is part of the Free Pascal Integrated Development Environment
  4. Copyright (c) 1998-2000 by Pierre Muller
  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. {$i globdir.inc}
  15. uses
  16. {$ifdef win32}
  17. Windows,
  18. {$endif win32}
  19. Objects,Dialogs,Drivers,Views,
  20. GDBCon,GDBInt,Menus,
  21. WViews,WEditor,
  22. FPViews;
  23. type
  24. PDebugController=^TDebugController;
  25. TDebugController=object(TGDBController)
  26. InvalidSourceLine : boolean;
  27. { if true the current debugger raw will stay in middle of
  28. editor window when debugging PM }
  29. CenterDebuggerRow : boolean;
  30. Disableallinvalidbreakpoints : boolean;
  31. LastFileName : string;
  32. LastSource : PView; {PsourceWindow !! }
  33. HiddenStepsCount : longint;
  34. { no need to switch if using another terminal }
  35. NoSwitch : boolean;
  36. HasExe : boolean;
  37. RunCount : longint;
  38. WindowWidth : longint;
  39. FPCBreakErrorNumber : longint;
  40. constructor Init;
  41. procedure SetExe(const exefn:string);
  42. procedure SetWidth(AWidth : longint);
  43. procedure SetDirectories;
  44. destructor Done;
  45. procedure DoSelectSourceline(const fn:string;line:longint);virtual;
  46. { procedure DoStartSession;virtual;
  47. procedure DoBreakSession;virtual;}
  48. procedure DoEndSession(code:longint);virtual;
  49. procedure DoUserSignal;virtual;
  50. procedure AnnotateError;
  51. procedure InsertBreakpoints;
  52. procedure RemoveBreakpoints;
  53. procedure ReadWatches;
  54. procedure RereadWatches;
  55. procedure ResetBreakpointsValues;
  56. procedure DoDebuggerScreen;virtual;
  57. procedure DoUserScreen;virtual;
  58. procedure Reset;virtual;
  59. procedure ResetDebuggerRows;
  60. procedure Run;virtual;
  61. procedure Continue;virtual;
  62. procedure UntilReturn;virtual;
  63. procedure CommandBegin(const s:string);virtual;
  64. procedure CommandEnd(const s:string);virtual;
  65. function IsRunning : boolean;
  66. function AllowQuit : boolean;virtual;
  67. function GetValue(Const expr : string) : pchar;
  68. function GetFramePointer : CORE_ADDR;
  69. function GetLongintAt(addr : CORE_ADDR) : longint;
  70. function GetPointerAt(addr : CORE_ADDR) : CORE_ADDR;
  71. end;
  72. BreakpointType = (bt_function,bt_file_line,bt_watch,
  73. bt_awatch,bt_rwatch,bt_address,bt_invalid);
  74. BreakpointState = (bs_enabled,bs_disabled,bs_deleted,bs_delete_after);
  75. PBreakpointCollection=^TBreakpointCollection;
  76. PBreakpoint=^TBreakpoint;
  77. TBreakpoint=object(TObject)
  78. typ : BreakpointType;
  79. state : BreakpointState;
  80. owner : PBreakpointCollection;
  81. Name : PString; { either function name or expr to watch }
  82. FileName : PString;
  83. OldValue,CurrentValue : Pstring;
  84. Line : Longint; { only used for bt_file_line type }
  85. Conditions : PString; { conditions relative to that breakpoint }
  86. IgnoreCount : Longint; { how many counts should be ignored }
  87. Commands : pchar; { commands that should be executed on breakpoint }
  88. GDBIndex : longint;
  89. GDBState : BreakpointState;
  90. constructor Init_function(Const AFunc : String);
  91. constructor Init_Address(Const AAddress : String);
  92. constructor Init_Empty;
  93. constructor Init_file_line(AFile : String; ALine : longint);
  94. constructor Init_type(atyp : BreakpointType;Const AnExpr : String);
  95. constructor Load(var S: TStream);
  96. procedure Store(var S: TStream);
  97. procedure Insert;
  98. procedure Remove;
  99. procedure Enable;
  100. procedure Disable;
  101. procedure UpdateSource;
  102. procedure ResetValues;
  103. destructor Done;virtual;
  104. end;
  105. TBreakpointCollection=object(TCollection)
  106. function At(Index: Integer): PBreakpoint;
  107. function GetGDB(index : longint) : PBreakpoint;
  108. function GetType(typ : BreakpointType;Const s : String) : PBreakpoint;
  109. function ToggleFileLine(FileName: String;LineNr : Longint) : boolean;
  110. procedure Update;
  111. procedure ShowBreakpoints(W : PFPWindow);
  112. procedure AdaptBreakpoints(Editor : PSourceEditor; Pos, Change : longint);
  113. procedure ShowAllBreakpoints;
  114. end;
  115. PBreakpointItem = ^TBreakpointItem;
  116. TBreakpointItem = object(TObject)
  117. Breakpoint : PBreakpoint;
  118. constructor Init(ABreakpoint : PBreakpoint);
  119. function GetText(MaxLen: Sw_integer): string; virtual;
  120. procedure Selected; virtual;
  121. function GetModuleName: string; virtual;
  122. end;
  123. PBreakpointsListBox = ^TBreakpointsListBox;
  124. TBreakpointsListBox = object(THSListBox)
  125. Transparent : boolean;
  126. NoSelection : boolean;
  127. MaxWidth : Sw_integer;
  128. (* ModuleNames : PStoreCollection; *)
  129. constructor Init(var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar);
  130. procedure AddBreakpoint(P: PBreakpointItem); virtual;
  131. function GetText(Item,MaxLen: Sw_Integer): String; virtual;
  132. function GetLocalMenu: PMenu;virtual;
  133. procedure Clear; virtual;
  134. procedure TrackSource; virtual;
  135. procedure EditNew; virtual;
  136. procedure EditCurrent; virtual;
  137. procedure DeleteCurrent; virtual;
  138. procedure ToggleCurrent;
  139. procedure Draw; virtual;
  140. procedure HandleEvent(var Event: TEvent); virtual;
  141. constructor Load(var S: TStream);
  142. procedure Store(var S: TStream);
  143. destructor Done; virtual;
  144. end;
  145. PBreakpointsWindow = ^TBreakpointsWindow;
  146. TBreakpointsWindow = object(TFPDlgWindow)
  147. BreakLB : PBreakpointsListBox;
  148. constructor Init;
  149. procedure AddBreakpoint(ABreakpoint : PBreakpoint);
  150. procedure ClearBreakpoints;
  151. procedure ReloadBreakpoints;
  152. procedure Close; virtual;
  153. procedure SizeLimits(var Min, Max: TPoint);virtual;
  154. procedure HandleEvent(var Event: TEvent); virtual;
  155. procedure Update; virtual;
  156. constructor Load(var S: TStream);
  157. procedure Store(var S: TStream);
  158. destructor Done; virtual;
  159. end;
  160. PBreakpointItemDialog = ^TBreakpointItemDialog;
  161. TBreakpointItemDialog = object(TCenterDialog)
  162. constructor Init(ABreakpoint: PBreakpoint);
  163. function Execute: Word; virtual;
  164. private
  165. Breakpoint : PBreakpoint;
  166. TypeRB : PRadioButtons;
  167. NameIL : PEditorInputLine;
  168. ConditionsIL: PInputLine;
  169. LineIL : PInputLine;
  170. IgnoreIL : PInputLine;
  171. end;
  172. PWatch = ^TWatch;
  173. TWatch = Object(TObject)
  174. constructor Init(s : string);
  175. constructor Load(var S: TStream);
  176. procedure Store(var S: TStream);
  177. procedure rename(s : string);
  178. procedure Get_new_value;
  179. procedure Force_new_value;
  180. destructor done;virtual;
  181. expr : pstring;
  182. private
  183. GDBRunCount : longint;
  184. last_value,current_value : pchar;
  185. end;
  186. PWatchesCollection = ^TWatchesCollection;
  187. TWatchesCollection = Object(TCollection)
  188. constructor Init;
  189. procedure Insert(Item: Pointer); virtual;
  190. function At(Index: Integer): PWatch;
  191. procedure Update;
  192. private
  193. MaxW : integer;
  194. end;
  195. PWatchesListBox = ^TWatchesListBox;
  196. TWatchesListBox = object(THSListBox)
  197. Transparent : boolean;
  198. MaxWidth : Sw_integer;
  199. constructor Init(var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar);
  200. (* procedure AddWatch(P: PWatch); virtual; *)
  201. procedure Update(AMaxWidth : integer);
  202. function GetText (Item: Sw_Integer; MaxLen: Sw_Integer): String; Virtual;
  203. function GetIndentedText(Item,Indent,MaxLen: Sw_Integer;var Modified : boolean): String; virtual;
  204. function GetLocalMenu: PMenu;virtual;
  205. (* procedure Clear; virtual;
  206. procedure TrackSource; virtual;*)
  207. procedure EditNew; virtual;
  208. procedure EditCurrent; virtual;
  209. procedure DeleteCurrent; virtual;
  210. (*procedure ToggleCurrent; *)
  211. procedure Draw; virtual;
  212. procedure HandleEvent(var Event: TEvent); virtual;
  213. constructor Load(var S: TStream);
  214. procedure Store(var S: TStream);
  215. destructor Done; virtual;
  216. end;
  217. PWatchItemDialog = ^TWatchItemDialog;
  218. TWatchItemDialog = object(TCenterDialog)
  219. constructor Init(AWatch: PWatch);
  220. function Execute: Word; virtual;
  221. private
  222. Watch : PWatch;
  223. NameIL : PEditorInputLine;
  224. TextST : PAdvancedStaticText;
  225. end;
  226. PWatchesWindow = ^TWatchesWindow;
  227. TWatchesWindow = Object(TFPDlgWindow)
  228. WLB : PWatchesListBox;
  229. Constructor Init;
  230. constructor Load(var S: TStream);
  231. procedure Store(var S: TStream);
  232. procedure Update; virtual;
  233. destructor Done; virtual;
  234. end;
  235. PFramesListBox = ^TFramesListBox;
  236. TFramesListBox = object(TMessageListBox)
  237. constructor Init(var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar);
  238. procedure Update;
  239. function GetLocalMenu: PMenu;virtual;
  240. procedure GotoSource; virtual;
  241. procedure GotoAssembly; virtual;
  242. procedure HandleEvent(var Event: TEvent); virtual;
  243. destructor Done; virtual;
  244. end;
  245. PStackWindow = ^TStackWindow;
  246. TStackWindow = Object(TFPDlgWindow)
  247. FLB : PFramesListBox;
  248. Constructor Init;
  249. constructor Load(var S: TStream);
  250. procedure Store(var S: TStream);
  251. procedure Update; virtual;
  252. destructor Done; virtual;
  253. end;
  254. procedure InitStackWindow;
  255. procedure DoneStackWindow;
  256. function ActiveBreakpoints : boolean;
  257. function GDBFileName(st : string) : string;
  258. function OSFileName(st : string) : string;
  259. const
  260. BreakpointTypeStr : Array[BreakpointType] of String[9]
  261. = ( 'function','file-line','watch','awatch','rwatch','address','invalid');
  262. BreakpointStateStr : Array[BreakpointState] of String[8]
  263. = ( 'enabled','disabled','invalid',''{'to be deleted' should never be used});
  264. var
  265. Debugger : PDebugController;
  266. BreakpointsCollection : PBreakpointCollection;
  267. WatchesCollection : PwatchesCollection;
  268. procedure InitDebugger;
  269. procedure DoneDebugger;
  270. procedure InitGDBWindow;
  271. procedure DoneGDBWindow;
  272. procedure InitDisassemblyWindow;
  273. procedure DoneDisassemblyWindow;
  274. procedure InitBreakpoints;
  275. procedure DoneBreakpoints;
  276. procedure InitWatches;
  277. procedure DoneWatches;
  278. procedure RegisterFPDebugViews;
  279. procedure UpdateDebugViews;
  280. implementation
  281. uses
  282. Dos,
  283. {$ifdef fpc}
  284. Video,
  285. {$endif fpc}
  286. {$ifdef DOS}
  287. fpusrscr,
  288. {$endif DOS}
  289. App,Strings,
  290. {$ifdef FVISION}
  291. FVConsts,
  292. {$else}
  293. Commands,HelpCtx,
  294. {$endif}
  295. {$ifdef win32}
  296. Windebug,
  297. {$endif win32}
  298. {$ifdef Unix}
  299. {$ifdef VER1_0}
  300. Linux,
  301. {$else}
  302. Unix,
  303. {$endif}
  304. {$endif Unix}
  305. Systems,Globals,
  306. FPRegs,
  307. FPString,FPVars,FPUtils,FPConst,FPSwitch,
  308. FPIntf,FPCompil,FPIde,FPHelp,
  309. Validate,WUtils,Wconsts;
  310. const
  311. RBreakpointsWindow: TStreamRec = (
  312. ObjType: 1701;
  313. VmtLink: Ofs(TypeOf(TBreakpointsWindow)^);
  314. Load: @TBreakpointsWindow.Load;
  315. Store: @TBreakpointsWindow.Store
  316. );
  317. RBreakpointsListBox : TStreamRec = (
  318. ObjType: 1702;
  319. VmtLink: Ofs(TypeOf(TBreakpointsListBox)^);
  320. Load: @TBreakpointsListBox.Load;
  321. Store: @TBreakpointsListBox.Store
  322. );
  323. RWatchesWindow: TStreamRec = (
  324. ObjType: 1703;
  325. VmtLink: Ofs(TypeOf(TWatchesWindow)^);
  326. Load: @TWatchesWindow.Load;
  327. Store: @TWatchesWindow.Store
  328. );
  329. RWatchesListBox: TStreamRec = (
  330. ObjType: 1704;
  331. VmtLink: Ofs(TypeOf(TWatchesListBox)^);
  332. Load: @TWatchesListBox.Load;
  333. Store: @TWatchesListBox.Store
  334. );
  335. RStackWindow: TStreamRec = (
  336. ObjType: 1705;
  337. VmtLink: Ofs(TypeOf(TStackWindow)^);
  338. Load: @TStackWindow.Load;
  339. Store: @TStackWindow.Store
  340. );
  341. RFramesListBox: TStreamRec = (
  342. ObjType: 1706;
  343. VmtLink: Ofs(TypeOf(TFramesListBox)^);
  344. Load: @TFramesListBox.Load;
  345. Store: @TFramesListBox.Store
  346. );
  347. RBreakpoint: TStreamRec = (
  348. ObjType: 1707;
  349. VmtLink: Ofs(TypeOf(TBreakpoint)^);
  350. Load: @TBreakpoint.Load;
  351. Store: @TBreakpoint.Store
  352. );
  353. RWatch: TStreamRec = (
  354. ObjType: 1708;
  355. VmtLink: Ofs(TypeOf(TWatch)^);
  356. Load: @TWatch.Load;
  357. Store: @TWatch.Store
  358. );
  359. RBreakpointCollection: TStreamRec = (
  360. ObjType: 1709;
  361. VmtLink: Ofs(TypeOf(TBreakpointCollection)^);
  362. Load: @TBreakpointCollection.Load;
  363. Store: @TBreakpointCollection.Store
  364. );
  365. RWatchesCollection: TStreamRec = (
  366. ObjType: 1710;
  367. VmtLink: Ofs(TypeOf(TWatchesCollection)^);
  368. Load: @TWatchesCollection.Load;
  369. Store: @TWatchesCollection.Store
  370. );
  371. {$ifdef I386}
  372. const
  373. FrameName = '$ebp';
  374. {$define FrameNameKnown}
  375. {$endif i386}
  376. {$ifdef m68k}
  377. const
  378. FrameName = '$fp';
  379. {$define FrameNameKnown}
  380. {$endif m68k}
  381. {$ifdef powerpc}
  382. { stack and frame registers are the same on powerpc,
  383. so I am not sure that this will work PM }
  384. const
  385. FrameName = '$r1';
  386. {$define FrameNameKnown}
  387. {$endif powerpc}
  388. {$ifdef TP}
  389. function HexStr(Value: longint; Len: byte): string;
  390. begin
  391. HexStr:=IntToHex(Value,Len);
  392. end;
  393. {$endif}
  394. function GDBFileName(st : string) : string;
  395. {$ifndef Unix}
  396. var i : longint;
  397. {$endif Unix}
  398. begin
  399. {$ifdef Unix}
  400. GDBFileName:=st;
  401. {$else}
  402. { should we also use / chars ? }
  403. for i:=1 to Length(st) do
  404. if st[i]='\' then
  405. {$ifdef win32}
  406. { Don't touch at '\ ' used to escapes spaces in windows file names PM }
  407. if (i=length(st)) or (st[i+1]<>' ') then
  408. {$endif win32}
  409. st[i]:='/';
  410. {$ifdef win32}
  411. { for win32 we should convert e:\ into //e/ PM }
  412. if (length(st)>2) and (st[2]=':') and (st[3]='/') then
  413. st:=CygDrivePrefix+'/'+st[1]+copy(st,3,length(st));
  414. { support spaces in the name by escaping them but without changing '\ ' into '\\ ' }
  415. for i:=Length(st) downto 1 do
  416. if (st[i]=' ') and ((i=1) or (st[i-1]<>'\')) then
  417. st:=copy(st,1,i-1)+'\'+copy(st,i,length(st));
  418. {$endif win32}
  419. {$ifdef go32v2}
  420. { for go32v2 we should convert //e/ back into e:/ PM }
  421. if (length(st)>3) and (st[1]='/') and (st[2]='/') and (st[4]='/') then
  422. st:=st[3]+':/'+copy(st,5,length(st));
  423. {$endif go32v2}
  424. GDBFileName:=LowerCaseStr(st);
  425. {$endif}
  426. end;
  427. function OSFileName(st : string) : string;
  428. {$ifndef Unix}
  429. var i : longint;
  430. {$endif Unix}
  431. begin
  432. {$ifdef Unix}
  433. OSFileName:=st;
  434. {$else}
  435. {$ifdef win32}
  436. { for win32 we should convert /cygdrive/e/ into e:\ PM }
  437. if pos(CygDrivePrefix+'/',st)=1 then
  438. st:=st[Length(CygdrivePrefix)+2]+':\'+copy(st,length(CygdrivePrefix)+4,length(st));
  439. {$endif win32}
  440. { support spaces in the name by escaping them but without changing '\ ' into '\\ ' }
  441. for i:=Length(st) downto 2 do
  442. if (st[i]=' ') and (st[i-1]='\') then
  443. st:=copy(st,1,i-2)+copy(st,i,length(st));
  444. {$ifdef go32v2}
  445. { for go32v2 we should convert //e/ back into e:/ PM }
  446. if (length(st)>3) and (st[1]='/') and (st[2]='/') and (st[4]='/') then
  447. st:=st[3]+':\'+copy(st,5,length(st));
  448. {$endif go32v2}
  449. { should we also use / chars ? }
  450. for i:=1 to Length(st) do
  451. if st[i]='/' then
  452. st[i]:='\';
  453. OSFileName:=LowerCaseStr(st);
  454. {$endif}
  455. end;
  456. {****************************************************************************
  457. TDebugController
  458. ****************************************************************************}
  459. procedure UpdateDebugViews;
  460. begin
  461. {$ifdef SUPPORT_REMOTE}
  462. PushStatus(msg_getting_info_on+RemoteMachine);
  463. {$endif SUPPORT_REMOTE}
  464. DeskTop^.Lock;
  465. If assigned(StackWindow) then
  466. StackWindow^.Update;
  467. If assigned(RegistersWindow) then
  468. RegistersWindow^.Update;
  469. If assigned(Debugger) then
  470. Debugger^.ReadWatches;
  471. If assigned(FPUWindow) then
  472. FPUWindow^.Update;
  473. DeskTop^.UnLock;
  474. {$ifdef SUPPORT_REMOTE}
  475. PopStatus;
  476. {$endif SUPPORT_REMOTE}
  477. end;
  478. constructor TDebugController.Init;
  479. begin
  480. inherited Init;
  481. CenterDebuggerRow:=IniCenterDebuggerRow;
  482. Disableallinvalidbreakpoints:=false;
  483. NoSwitch:=False;
  484. HasExe:=false;
  485. Debugger:=@self;
  486. WindowWidth:=-1;
  487. {$ifndef GABOR}
  488. switch_to_user:=true;
  489. {$endif}
  490. Command('set print object off');
  491. end;
  492. procedure TDebugController.SetExe(const exefn:string);
  493. var f : string;
  494. begin
  495. f := GDBFileName(GetShortName(exefn));
  496. if (f<>'') and ExistsFile(exefn) then
  497. begin
  498. LoadFile(f);
  499. HasExe:=true;
  500. Command('b FPC_BREAK_ERROR');
  501. FPCBreakErrorNumber:=last_breakpoint_number;
  502. {$ifdef FrameNameKnown}
  503. { this fails in GDB 5.1 because
  504. GDB replies that there is an attempt to dereference
  505. a generic pointer...
  506. test delayed in DoSourceLine... PM
  507. Command('cond '+IntToStr(FPCBreakErrorNumber)+
  508. ' (('+FrameName+' + 8)^ <> 0) or'+
  509. ' (('+FrameName+' + 12)^ <> 0)'); }
  510. {$endif FrameNameKnown}
  511. SetArgs(GetRunParameters);
  512. SetDirectories;
  513. InsertBreakpoints;
  514. ReadWatches;
  515. end
  516. else
  517. begin
  518. HasExe:=false;
  519. Command('file');
  520. end;
  521. end;
  522. procedure TDebugController.SetWidth(AWidth : longint);
  523. begin
  524. WindowWidth:=AWidth;
  525. Command('set width '+inttostr(WindowWidth));
  526. end;
  527. procedure TDebugController.SetDirectories;
  528. var f,s: string;
  529. i : longint;
  530. Dir : SearchRec;
  531. begin
  532. f:=GetSourceDirectories;
  533. repeat
  534. i:=pos(';',f);
  535. if i=0 then
  536. s:=f
  537. else
  538. begin
  539. s:=copy(f,1,i-1);
  540. system.delete(f,1,i);
  541. end;
  542. DefaultReplacements(s);
  543. if (pos('*',s)=0) and ExistsDir(s) then
  544. Command('dir '+GDBFileName(GetShortName(s)))
  545. { we should also handle the /* cases of -Fu option }
  546. else if pos('*',s)>0 then
  547. begin
  548. Dos.FindFirst(s,Directory,Dir);
  549. { the '*' can only be in the last dir level }
  550. s:=DirOf(s);
  551. while Dos.DosError=0 do
  552. begin
  553. if ((Dir.attr and Directory) <> 0) and ExistsDir(s+Dir.Name) then
  554. Command('dir '+GDBFileName(GetShortName(s+Dir.Name)));
  555. Dos.FindNext(Dir);
  556. end;
  557. {$ifdef FPC}
  558. Dos.FindClose(Dir);
  559. {$endif def FPC}
  560. end;
  561. until i=0;
  562. end;
  563. procedure TDebugController.InsertBreakpoints;
  564. procedure DoInsert(PB : PBreakpoint);
  565. begin
  566. PB^.Insert;
  567. end;
  568. begin
  569. BreakpointsCollection^.ForEach(@DoInsert);
  570. Disableallinvalidbreakpoints:=false;
  571. end;
  572. procedure TDebugController.ReadWatches;
  573. procedure DoRead(PB : PWatch);
  574. begin
  575. PB^.Get_new_value;
  576. end;
  577. begin
  578. WatchesCollection^.ForEach(@DoRead);
  579. If Assigned(WatchesWindow) then
  580. WatchesWindow^.Update;
  581. end;
  582. procedure TDebugController.RereadWatches;
  583. procedure DoRead(PB : PWatch);
  584. begin
  585. PB^.Force_new_value;
  586. end;
  587. begin
  588. WatchesCollection^.ForEach(@DoRead);
  589. If Assigned(WatchesWindow) then
  590. WatchesWindow^.Update;
  591. end;
  592. procedure TDebugController.RemoveBreakpoints;
  593. procedure DoDelete(PB : PBreakpoint);
  594. begin
  595. PB^.Remove;
  596. end;
  597. begin
  598. BreakpointsCollection^.ForEach(@DoDelete);
  599. end;
  600. procedure TDebugController.ResetBreakpointsValues;
  601. procedure DoResetVal(PB : PBreakpoint);
  602. begin
  603. PB^.ResetValues;
  604. end;
  605. begin
  606. BreakpointsCollection^.ForEach(@DoResetVal);
  607. end;
  608. function ActiveBreakpoints : boolean;
  609. var
  610. IsActive : boolean;
  611. procedure TestActive(PB : PBreakpoint);
  612. begin
  613. If PB^.state=bs_enabled then
  614. IsActive:=true;
  615. end;
  616. begin
  617. IsActive:=false;
  618. If assigned(BreakpointsCollection) then
  619. BreakpointsCollection^.ForEach(@TestActive);
  620. ActiveBreakpoints:=IsActive;
  621. end;
  622. destructor TDebugController.Done;
  623. begin
  624. { kill the program if running }
  625. Reset;
  626. RemoveBreakpoints;
  627. inherited Done;
  628. end;
  629. procedure TDebugController.Run;
  630. {$ifdef Unix}
  631. var
  632. Debuggeefile : text;
  633. ResetOK, TTYUsed : boolean;
  634. {$endif Unix}
  635. {$ifdef SUPPORT_REMOTE}
  636. var
  637. S,ErrorStr : string;
  638. {$endif SUPPORT_REMOTE}
  639. begin
  640. ResetBreakpointsValues;
  641. {$ifdef SUPPORT_REMOTE}
  642. NoSwitch:=true;
  643. {$ifndef CROSSGDB}
  644. If (RemoteMachine<>'') and (RemotePort<>'') then
  645. {$else CROSSGDB}
  646. if true then
  647. {$endif CROSSGDB}
  648. begin
  649. S:=RemoteMachine;
  650. If pos('@',S)>0 then
  651. S:=copy(S,pos('@',S)+1,High(S));
  652. Command('target remote '+S+':'+RemotePort);
  653. if Error then
  654. begin
  655. ErrorStr:=strpas(GetError);
  656. ErrorBox(#3'Error in "target remote"'#13#3+ErrorStr,nil);
  657. exit;
  658. end;
  659. end
  660. else
  661. begin
  662. {$endif SUPPORT_REMOTE}
  663. {$ifdef win32}
  664. { Run the debugge in another console }
  665. if DebuggeeTTY<>'' then
  666. Command('set new-console on')
  667. else
  668. Command('set new-console off');
  669. NoSwitch:=DebuggeeTTY<>'';
  670. {$endif win32}
  671. {$ifdef Unix}
  672. { Run the debuggee in another tty }
  673. if DebuggeeTTY <> '' then
  674. begin
  675. {$I-}
  676. Assign(Debuggeefile,DebuggeeTTY);
  677. system.Reset(Debuggeefile);
  678. ResetOK:=IOResult=0;
  679. If ResetOK and IsATTY(textrec(Debuggeefile).handle) then
  680. begin
  681. Command('tty '+DebuggeeTTY);
  682. TTYUsed:=true;
  683. end
  684. else
  685. begin
  686. Command('tty ');
  687. TTYUsed:=false;
  688. end;
  689. if ResetOK then
  690. close(Debuggeefile);
  691. if TTYUsed and (DebuggeeTTY<>TTYName(stdout)) then
  692. NoSwitch:= true
  693. else
  694. NoSwitch:=false;
  695. end
  696. else
  697. begin
  698. if TTYName(input)<>'' then
  699. Command('tty '+TTYName(input));
  700. NoSwitch := false;
  701. end;
  702. {$endif Unix}
  703. {$ifdef SUPPORT_REMOTE}
  704. end;
  705. {$endif SUPPORT_REMOTE}
  706. { Switch to user screen to get correct handles }
  707. UserScreen;
  708. { Don't try to print GDB messages while in User Screen mode }
  709. If assigned(GDBWindow) then
  710. GDBWindow^.Editor^.Lock;
  711. {$ifndef SUPPORT_REMOTE}
  712. inherited Run;
  713. {$else SUPPORT_REMOTE}
  714. inc(init_count);
  715. { pass the stop in start code }
  716. Command('continue');
  717. {$endif SUPPORT_REMOTE}
  718. DebuggerScreen;
  719. If assigned(GDBWindow) then
  720. GDBWindow^.Editor^.UnLock;
  721. IDEApp.SetCmdState([cmResetDebugger,cmUntilReturn],true);
  722. IDEApp.UpdateRunMenu(true);
  723. UpdateDebugViews;
  724. end;
  725. function TDebugController.IsRunning : boolean;
  726. begin
  727. IsRunning:=debuggee_started;
  728. end;
  729. procedure TDebugController.Continue;
  730. begin
  731. {$ifdef NODEBUG}
  732. NoDebugger;
  733. {$else}
  734. if not debuggee_started then
  735. Run
  736. else
  737. inherited Continue;
  738. UpdateDebugViews;
  739. {$endif NODEBUG}
  740. end;
  741. procedure TDebugController.UntilReturn;
  742. begin
  743. Command('finish');
  744. UpdateDebugViews;
  745. { We could try to get the return value !
  746. Not done yet }
  747. end;
  748. procedure TDebugController.CommandBegin(const s:string);
  749. begin
  750. if assigned(GDBWindow) and (in_command>1) then
  751. begin
  752. { We should do something special for errors !! }
  753. If StrLen(GetError)>0 then
  754. GDBWindow^.WriteErrorText(GetError);
  755. GDBWindow^.WriteOutputText(GetOutput);
  756. end;
  757. if assigned(GDBWindow) then
  758. GDBWindow^.WriteString(S);
  759. end;
  760. procedure TDebugController.CommandEnd(const s:string);
  761. begin
  762. if assigned(GDBWindow) and (in_command<=1) then
  763. begin
  764. { We should do something special for errors !! }
  765. If StrLen(GetError)>0 then
  766. GDBWindow^.WriteErrorText(GetError);
  767. GDBWindow^.WriteOutputText(GetOutput);
  768. GDBWindow^.Editor^.TextEnd;
  769. end;
  770. end;
  771. function TDebugController.AllowQuit : boolean;
  772. begin
  773. if IsRunning then
  774. begin
  775. if ConfirmBox('Really quit GDB window'#13+
  776. 'and kill running program?',nil,true)=cmYes then
  777. begin
  778. Reset;
  779. DoneGDBWindow;
  780. {AllowQuit:=true;}
  781. AllowQuit:=false;
  782. end
  783. else
  784. AllowQuit:=false;
  785. end
  786. else if ConfirmBox('Really quit GDB window?',nil,true)=cmYes then
  787. begin
  788. DoneGDBWindow;
  789. {AllowQuit:=true;}
  790. AllowQuit:=false;
  791. end
  792. else
  793. AllowQuit:=false;
  794. end;
  795. procedure TDebugController.ResetDebuggerRows;
  796. procedure ResetDebuggerRow(P: PView); {$ifndef FPC}far;{$endif}
  797. begin
  798. if assigned(P) and
  799. (TypeOf(P^)=TypeOf(TSourceWindow)) then
  800. PSourceWindow(P)^.Editor^.SetLineFlagExclusive(lfDebuggerRow,-1);
  801. end;
  802. begin
  803. Desktop^.ForEach(@ResetDebuggerRow);
  804. end;
  805. procedure TDebugController.Reset;
  806. begin
  807. inherited Reset;
  808. { we need to free the executable
  809. if we want to recompile it }
  810. SetExe('');
  811. NoSwitch:=false;
  812. { In case we have something that the compiler touched }
  813. If IDEApp.IsRunning then
  814. begin
  815. IDEApp.SetCmdState([cmResetDebugger,cmUntilReturn],false);
  816. IDEApp.UpdateRunMenu(false);
  817. AskToReloadAllModifiedFiles;
  818. ResetDebuggerRows;
  819. end;
  820. end;
  821. procedure TDebugController.AnnotateError;
  822. var errornb : longint;
  823. begin
  824. if error then
  825. begin
  826. errornb:=error_num;
  827. UpdateDebugViews;
  828. ErrorBox(#3'Error within GDB'#13#3'Error code = %d',@errornb);
  829. end;
  830. end;
  831. function TDebugController.GetValue(Const expr : string) : pchar;
  832. var
  833. p,p2,p3 : pchar;
  834. begin
  835. if WindowWidth<>-1 then
  836. Command('set width 0xffffffff');
  837. Command('p '+expr);
  838. p:=GetOutput;
  839. p3:=nil;
  840. if assigned(p) and (p[strlen(p)-1]=#10) then
  841. begin
  842. p3:=p+strlen(p)-1;
  843. p3^:=#0;
  844. end;
  845. if assigned(p) then
  846. p2:=strpos(p,'=')
  847. else
  848. p2:=nil;
  849. if assigned(p2) then
  850. p:=p2+1;
  851. while p^ in [' ',TAB] do
  852. inc(p);
  853. { get rid of type }
  854. if p^ = '(' then
  855. p:=strpos(p,')')+1;
  856. while p^ in [' ',TAB] do
  857. inc(p);
  858. if assigned(p) then
  859. GetValue:=StrNew(p)
  860. else
  861. GetValue:=StrNew(GetError);
  862. if assigned(p3) then
  863. p3^:=#10;
  864. got_error:=false;
  865. if WindowWidth<>-1 then
  866. Command('set width '+IntToStr(WindowWidth));
  867. end;
  868. function TDebugController.GetFramePointer : CORE_ADDR;
  869. var
  870. st : string;
  871. p : longint;
  872. begin
  873. {$ifdef FrameNameKnown}
  874. Command('p /d '+FrameName);
  875. st:=strpas(GetOutput);
  876. p:=pos('=',st);
  877. while (p<length(st)) and (st[p+1] in [' ',#9]) do
  878. inc(p);
  879. Delete(st,1,p);
  880. p:=1;
  881. while (st[p] in ['0'..'9']) do
  882. inc(p);
  883. Delete(st,p,High(st));
  884. GetFramePointer:=StrToCard(st);
  885. {$else not FrameNameKnown}
  886. GetFramePointer:=0;
  887. {$endif not FrameNameKnown}
  888. end;
  889. function TDebugController.GetLongintAt(addr : CORE_ADDR) : longint;
  890. var
  891. st : string;
  892. p : longint;
  893. begin
  894. Command('x /wd 0x'+hexstr(longint(addr),8));
  895. st:=strpas(GetOutput);
  896. p:=pos(':',st);
  897. while (p<length(st)) and (st[p+1] in [' ',#9]) do
  898. inc(p);
  899. Delete(st,1,p);
  900. p:=1;
  901. while (st[p] in ['0'..'9']) do
  902. inc(p);
  903. Delete(st,p,High(st));
  904. GetLongintAt:=StrToInt(st);
  905. end;
  906. function TDebugController.GetPointerAt(addr : CORE_ADDR) : CORE_ADDR;
  907. var
  908. val : CORE_ADDR;
  909. st : string;
  910. p : longint;
  911. begin
  912. Command('x /wx 0x'+hexstr(longint(addr),8));
  913. st:=strpas(GetOutput);
  914. p:=pos(':',st);
  915. while (p<length(st)) and (st[p+1] in [' ',#9]) do
  916. inc(p);
  917. if (p<length(st)) and (st[p+1]='$') then
  918. inc(p);
  919. Delete(st,1,p);
  920. p:=1;
  921. while (st[p] in ['0'..'9','A'..'F','a'..'f']) do
  922. inc(p);
  923. Delete(st,p,High(st));
  924. GetPointerAt:=HexToCard(st);
  925. end;
  926. procedure TDebugController.DoSelectSourceLine(const fn:string;line:longint);
  927. var
  928. W: PSourceWindow;
  929. Found : boolean;
  930. PB : PBreakpoint;
  931. S : String;
  932. BreakIndex : longint;
  933. ebp,stop_addr : CORE_ADDR;
  934. i,ExitCode : longint;
  935. ExitAddr,ExitFrame : CORE_ADDR;
  936. const
  937. FirstArgOffset = 2 * sizeof(CORE_ADDR);
  938. SecondArgOffset = 3 * sizeof(CORE_ADDR);
  939. ThirdArgOffset = 4 * sizeof(CORE_ADDR);
  940. begin
  941. BreakIndex:=stop_breakpoint_number;
  942. Desktop^.Lock;
  943. { 0 based line count in Editor }
  944. if Line>0 then
  945. dec(Line);
  946. S:=fn;
  947. stop_addr:=current_pc;
  948. if (BreakIndex=FPCBreakErrorNumber) then
  949. begin
  950. { Procedure HandleErrorAddrFrame
  951. (Errno : longint;addr,frame : longint);
  952. [public,alias:'FPC_BREAK_ERROR']; }
  953. {$ifdef FrameNameKnown}
  954. ExitCode:=GetLongintAt(GetFramePointer+FirstArgOffset);
  955. ExitAddr:=GetPointerAt(GetFramePointer+SecondArgOffset);
  956. ExitFrame:=GetPointerAt(GetFramePointer+ThirdArgOffset);
  957. if (ExitCode=0) and (ExitAddr=0) then
  958. begin
  959. Desktop^.Unlock;
  960. Command('continue');
  961. exit;
  962. end;
  963. { forget all old frames }
  964. clear_frames;
  965. { record new frames }
  966. Command('backtrace');
  967. for i:=0 to frame_count-1 do
  968. begin
  969. with frames[i]^ do
  970. begin
  971. if ExitAddr=address then
  972. begin
  973. Command('f '+IntToStr(i));
  974. if assigned(file_name) then
  975. begin
  976. s:=strpas(file_name);
  977. line:=line_number;
  978. stop_addr:=address;
  979. end;
  980. break;
  981. end;
  982. end;
  983. end;
  984. {$endif FrameNameKnown}
  985. end;
  986. { Update Disassembly position }
  987. if Assigned(DisassemblyWindow) then
  988. DisassemblyWindow^.SetCurAddress(stop_addr);
  989. if (fn=LastFileName) then
  990. begin
  991. W:=PSourceWindow(LastSource);
  992. if assigned(W) then
  993. begin
  994. W^.Editor^.SetCurPtr(0,Line);
  995. W^.Editor^.TrackCursor(CenterDebuggerRow);
  996. W^.Editor^.SetLineFlagExclusive(lfDebuggerRow,Line);
  997. UpdateDebugViews;
  998. {if Not assigned(GDBWindow) or not GDBWindow^.GetState(sfActive) then
  999. handled by SelectInDebugSession}
  1000. W^.SelectInDebugSession;
  1001. InvalidSourceLine:=false;
  1002. end
  1003. else
  1004. InvalidSourceLine:=true;
  1005. end
  1006. else
  1007. begin
  1008. if s='' then
  1009. W:=nil
  1010. else
  1011. W:=TryToOpenFile(nil,s,0,Line,false);
  1012. if assigned(W) then
  1013. begin
  1014. W^.Editor^.SetLineFlagExclusive(lfDebuggerRow,Line);
  1015. W^.Editor^.TrackCursor(CenterDebuggerRow);
  1016. UpdateDebugViews;
  1017. {if Not assigned(GDBWindow) or not GDBWindow^.GetState(sfActive) then
  1018. handled by SelectInDebugSession}
  1019. W^.SelectInDebugSession;
  1020. LastSource:=W;
  1021. InvalidSourceLine:=false;
  1022. end
  1023. { only search a file once }
  1024. else
  1025. begin
  1026. Desktop^.UnLock;
  1027. if s='' then
  1028. Found:=false
  1029. else
  1030. { it is easier to handle with a * at the end }
  1031. Found:=IDEApp.OpenSearch(s+'*');
  1032. Desktop^.Lock;
  1033. if not Found then
  1034. begin
  1035. InvalidSourceLine:=true;
  1036. LastSource:=Nil;
  1037. { Show the stack in that case }
  1038. InitStackWindow;
  1039. UpdateDebugViews;
  1040. StackWindow^.MakeFirst;
  1041. end
  1042. else
  1043. begin
  1044. { should now be open }
  1045. W:=TryToOpenFile(nil,s,0,Line,true);
  1046. W^.Editor^.SetLineFlagExclusive(lfDebuggerRow,Line);
  1047. W^.Editor^.TrackCursor(CenterDebuggerRow);
  1048. UpdateDebugViews;
  1049. {if Not assigned(GDBWindow) or not GDBWindow^.GetState(sfActive) then
  1050. handled by SelectInDebugSession}
  1051. W^.SelectInDebugSession;
  1052. LastSource:=W;
  1053. InvalidSourceLine:=false;
  1054. end;
  1055. end;
  1056. end;
  1057. LastFileName:=s;
  1058. Desktop^.UnLock;
  1059. if BreakIndex>0 then
  1060. begin
  1061. PB:=BreakpointsCollection^.GetGDB(BreakIndex);
  1062. if (BreakIndex=FPCBreakErrorNumber) then
  1063. begin
  1064. if (ExitCode<>0) or (ExitAddr<>0) then
  1065. WarningBox(#3'Run Time Error '+IntToStr(ExitCode)+#13+
  1066. #3'Error address $'+IntToHex(ExitAddr,8),nil)
  1067. else
  1068. WarningBox(#3'Run Time Error',nil);
  1069. end
  1070. else if not assigned(PB) then
  1071. begin
  1072. WarningBox(#3'Stopped by breakpoint '+IntToStr(BreakIndex),nil);
  1073. end
  1074. { For watch we should get old and new value !! }
  1075. else if (Not assigned(GDBWindow) or not GDBWindow^.GetState(sfActive)) and
  1076. (PB^.typ<>bt_file_line) and (PB^.typ<>bt_function) and
  1077. (PB^.typ<>bt_address) then
  1078. begin
  1079. Command('p '+GetStr(PB^.Name));
  1080. S:=GetPChar(GetOutput);
  1081. got_error:=false;
  1082. If Pos('=',S)>0 then
  1083. S:=Copy(S,Pos('=',S)+1,255);
  1084. If S[Length(S)]=#10 then
  1085. Delete(S,Length(S),1);
  1086. if Assigned(PB^.OldValue) then
  1087. DisposeStr(PB^.OldValue);
  1088. PB^.OldValue:=PB^.CurrentValue;
  1089. PB^.CurrentValue:=NewStr(S);
  1090. If PB^.typ=bt_function then
  1091. WarningBox(#3'GDB stopped due to'#13+
  1092. #3+BreakpointTypeStr[PB^.typ]+' '+GetStr(PB^.Name),nil)
  1093. else if (GetStr(PB^.OldValue)<>S) then
  1094. WarningBox(#3'GDB stopped due to'#13+
  1095. #3+BreakpointTypeStr[PB^.typ]+' '+GetStr(PB^.Name)+#13+
  1096. #3+'Old value = '+GetStr(PB^.OldValue)+#13+
  1097. #3+'New value = '+GetStr(PB^.CurrentValue),nil)
  1098. else
  1099. WarningBox(#3'GDB stopped due to'#13+
  1100. #3+BreakpointTypeStr[PB^.typ]+' '+GetStr(PB^.Name)+#13+
  1101. #3+' value = '+GetStr(PB^.CurrentValue),nil);
  1102. end;
  1103. end;
  1104. end;
  1105. procedure TDebugController.DoUserSignal;
  1106. var P :Array[1..2] of pstring;
  1107. S1, S2 : string;
  1108. begin
  1109. S1:=strpas(signal_name);
  1110. S2:=strpas(signal_string);
  1111. P[1]:=@S1;
  1112. P[2]:=@S2;
  1113. WarningBox(msg_programsignal,@P);
  1114. end;
  1115. procedure TDebugController.DoEndSession(code:longint);
  1116. var P :Array[1..2] of longint;
  1117. begin
  1118. IDEApp.SetCmdState([cmUntilReturn,cmResetDebugger],false);
  1119. IDEApp.UpdateRunMenu(false);
  1120. ResetDebuggerRows;
  1121. LastExitCode:=Code;
  1122. If HiddenStepsCount=0 then
  1123. InformationBox(msg_programexitedwithexitcode,@code)
  1124. else
  1125. begin
  1126. P[1]:=code;
  1127. P[2]:=HiddenStepsCount;
  1128. WarningBox(msg_programexitedwithcodeandsteps,@P);
  1129. end;
  1130. { In case we have something that the compiler touched }
  1131. AskToReloadAllModifiedFiles;
  1132. {$ifdef win32}
  1133. main_pid_valid:=false;
  1134. {$endif win32}
  1135. end;
  1136. procedure TDebugController.DoDebuggerScreen;
  1137. {$ifdef win32}
  1138. var
  1139. IdeMode : DWord;
  1140. {$endif win32}
  1141. begin
  1142. if NoSwitch then
  1143. begin
  1144. PopStatus;
  1145. end
  1146. else
  1147. begin
  1148. IDEApp.ShowIDEScreen;
  1149. Message(Application,evBroadcast,cmDebuggerStopped,pointer(RunCount));
  1150. PopStatus;
  1151. end;
  1152. {$ifdef win32}
  1153. if NoSwitch then
  1154. begin
  1155. { Ctrl-C as normal char }
  1156. GetConsoleMode(GetStdHandle(cardinal(Std_Input_Handle)), @IdeMode);
  1157. IdeMode:=(IdeMode or ENABLE_MOUSE_INPUT or ENABLE_WINDOW_INPUT) and not ENABLE_PROCESSED_INPUT;
  1158. SetConsoleMode(GetStdHandle(cardinal(Std_Input_Handle)), IdeMode);
  1159. end;
  1160. ChangeDebuggeeWindowTitleTo(Stopped_State);
  1161. {$endif win32}
  1162. end;
  1163. procedure TDebugController.DoUserScreen;
  1164. {$ifdef win32}
  1165. var
  1166. IdeMode : DWord;
  1167. {$endif win32}
  1168. begin
  1169. Inc(RunCount);
  1170. if NoSwitch then
  1171. begin
  1172. {$ifdef SUPPORT_REMOTE}
  1173. PushStatus(msg_runningremotely+RemoteMachine);
  1174. {$else not SUPPORT_REMOTE}
  1175. {$ifdef Unix}
  1176. PushStatus(msg_runninginanotherwindow+DebuggeeTTY);
  1177. {$else not Unix}
  1178. PushStatus(msg_runninginanotherwindow);
  1179. {$endif Unix}
  1180. {$endif not SUPPORT_REMOTE}
  1181. end
  1182. else
  1183. begin
  1184. PushStatus(msg_runningprogram);
  1185. IDEApp.ShowUserScreen;
  1186. end;
  1187. {$ifdef win32}
  1188. if NoSwitch then
  1189. begin
  1190. { Ctrl-C as interrupt }
  1191. GetConsoleMode(GetStdHandle(cardinal(Std_Input_Handle)), @IdeMode);
  1192. IdeMode:=(IdeMode or ENABLE_MOUSE_INPUT or ENABLE_PROCESSED_INPUT or ENABLE_WINDOW_INPUT);
  1193. SetConsoleMode(GetStdHandle(cardinal(Std_Input_Handle)), IdeMode);
  1194. end;
  1195. ChangeDebuggeeWindowTitleTo(Running_State);
  1196. {$endif win32}
  1197. end;
  1198. {****************************************************************************
  1199. TBreakpoint
  1200. ****************************************************************************}
  1201. constructor TBreakpoint.Init_function(Const AFunc : String);
  1202. begin
  1203. typ:=bt_function;
  1204. state:=bs_enabled;
  1205. GDBState:=bs_deleted;
  1206. Name:=NewStr(AFunc);
  1207. FileName:=nil;
  1208. Line:=0;
  1209. IgnoreCount:=0;
  1210. Commands:=nil;
  1211. Conditions:=nil;
  1212. OldValue:=nil;
  1213. CurrentValue:=nil;
  1214. end;
  1215. constructor TBreakpoint.Init_Address(Const AAddress : String);
  1216. begin
  1217. typ:=bt_address;
  1218. state:=bs_enabled;
  1219. GDBState:=bs_deleted;
  1220. Name:=NewStr(AAddress);
  1221. FileName:=nil;
  1222. Line:=0;
  1223. IgnoreCount:=0;
  1224. Commands:=nil;
  1225. Conditions:=nil;
  1226. OldValue:=nil;
  1227. CurrentValue:=nil;
  1228. end;
  1229. constructor TBreakpoint.Init_Empty;
  1230. begin
  1231. typ:=bt_function;
  1232. state:=bs_enabled;
  1233. GDBState:=bs_deleted;
  1234. Name:=Nil;
  1235. FileName:=nil;
  1236. Line:=0;
  1237. IgnoreCount:=0;
  1238. Commands:=nil;
  1239. Conditions:=nil;
  1240. OldValue:=nil;
  1241. CurrentValue:=nil;
  1242. end;
  1243. constructor TBreakpoint.Init_type(atyp : BreakpointType;Const AnExpr : String);
  1244. begin
  1245. typ:=atyp;
  1246. state:=bs_enabled;
  1247. GDBState:=bs_deleted;
  1248. Name:=NewStr(AnExpr);
  1249. IgnoreCount:=0;
  1250. Commands:=nil;
  1251. Conditions:=nil;
  1252. OldValue:=nil;
  1253. CurrentValue:=nil;
  1254. end;
  1255. constructor TBreakpoint.Init_file_line(AFile : String; ALine : longint);
  1256. var
  1257. CurDir : String;
  1258. begin
  1259. typ:=bt_file_line;
  1260. state:=bs_enabled;
  1261. GDBState:=bs_deleted;
  1262. { d:test.pas:12 does not work !! }
  1263. { I do not know how to solve this if
  1264. if (Length(AFile)>1) and (AFile[2]=':') then
  1265. AFile:=Copy(AFile,3,255); }
  1266. {$ifdef Unix}
  1267. CurDir:=GetCurDir;
  1268. {$else}
  1269. CurDir:=LowerCaseStr(GetCurDir);
  1270. {$endif Unix}
  1271. if Pos(CurDir,OSFileName(FEXpand(AFile)))=1 then
  1272. FileName:=NewStr(Copy(OSFileName(FExpand(AFile)),length(CurDir)+1,255))
  1273. else
  1274. FileName:=NewStr(OSFileName(FExpand(AFile)));
  1275. Name:=nil;
  1276. Line:=ALine;
  1277. IgnoreCount:=0;
  1278. Commands:=nil;
  1279. Conditions:=nil;
  1280. OldValue:=nil;
  1281. CurrentValue:=nil;
  1282. end;
  1283. constructor TBreakpoint.Load(var S: TStream);
  1284. var
  1285. FName : PString;
  1286. begin
  1287. S.Read(typ,SizeOf(BreakpointType));
  1288. S.Read(state,SizeOf(BreakpointState));
  1289. GDBState:=bs_deleted;
  1290. case typ of
  1291. bt_file_line :
  1292. begin
  1293. { convert to current target }
  1294. FName:=S.ReadStr;
  1295. FileName:=NewStr(OSFileName(GetStr(FName)));
  1296. If Assigned(FName) then
  1297. DisposeStr(FName);
  1298. S.Read(Line,SizeOf(Line));
  1299. Name:=nil;
  1300. end;
  1301. else
  1302. begin
  1303. Name:=S.ReadStr;
  1304. Line:=0;
  1305. FileName:=nil;
  1306. end;
  1307. end;
  1308. S.Read(IgnoreCount,SizeOf(IgnoreCount));
  1309. Commands:=S.StrRead;
  1310. Conditions:=S.ReadStr;
  1311. OldValue:=nil;
  1312. CurrentValue:=nil;
  1313. end;
  1314. procedure TBreakpoint.Store(var S: TStream);
  1315. var
  1316. St : String;
  1317. begin
  1318. S.Write(typ,SizeOf(BreakpointType));
  1319. S.Write(state,SizeOf(BreakpointState));
  1320. case typ of
  1321. bt_file_line :
  1322. begin
  1323. st:=OSFileName(GetStr(FileName));
  1324. S.WriteStr(@St);
  1325. S.Write(Line,SizeOf(Line));
  1326. end;
  1327. else
  1328. begin
  1329. S.WriteStr(Name);
  1330. end;
  1331. end;
  1332. S.Write(IgnoreCount,SizeOf(IgnoreCount));
  1333. S.StrWrite(Commands);
  1334. S.WriteStr(Conditions);
  1335. end;
  1336. procedure TBreakpoint.Insert;
  1337. var
  1338. p,p2 : pchar;
  1339. st : string;
  1340. begin
  1341. If not assigned(Debugger) then Exit;
  1342. Remove;
  1343. Debugger^.last_breakpoint_number:=0;
  1344. if (GDBState=bs_deleted) and (state=bs_enabled) then
  1345. begin
  1346. if (typ=bt_file_line) and assigned(FileName) then
  1347. Debugger^.Command('break '+GDBFileName(NameAndExtOf(GetStr(FileName)))+':'+IntToStr(Line))
  1348. else if (typ=bt_function) and assigned(name) then
  1349. Debugger^.Command('break '+name^)
  1350. else if (typ=bt_address) and assigned(name) then
  1351. Debugger^.Command('break *0x'+name^)
  1352. else if (typ=bt_watch) and assigned(name) then
  1353. Debugger^.Command('watch '+name^)
  1354. else if (typ=bt_awatch) and assigned(name) then
  1355. Debugger^.Command('awatch '+name^)
  1356. else if (typ=bt_rwatch) and assigned(name) then
  1357. Debugger^.Command('rwatch '+name^);
  1358. if Debugger^.last_breakpoint_number<>0 then
  1359. begin
  1360. GDBIndex:=Debugger^.last_breakpoint_number;
  1361. GDBState:=bs_enabled;
  1362. Debugger^.Command('cond '+IntToStr(GDBIndex)+' '+GetStr(Conditions));
  1363. If IgnoreCount>0 then
  1364. Debugger^.Command('ignore '+IntToStr(GDBIndex)+' '+IntToStr(IgnoreCount));
  1365. If Assigned(Commands) then
  1366. begin
  1367. {Commands are not handled yet }
  1368. Debugger^.Command('command '+IntToStr(GDBIndex));
  1369. p:=commands;
  1370. while assigned(p) do
  1371. begin
  1372. p2:=strscan(p,#10);
  1373. if assigned(p2) then
  1374. p2^:=#0;
  1375. st:=strpas(p);
  1376. Debugger^.command(st);
  1377. if assigned(p2) then
  1378. p2^:=#10;
  1379. p:=p2;
  1380. if assigned(p) then
  1381. inc(p);
  1382. end;
  1383. Debugger^.Command('end');
  1384. end;
  1385. end
  1386. else
  1387. { Here there was a problem !! }
  1388. begin
  1389. GDBIndex:=0;
  1390. if not Debugger^.Disableallinvalidbreakpoints then
  1391. begin
  1392. if (typ=bt_file_line) and assigned(FileName) then
  1393. begin
  1394. ClearFormatParams;
  1395. AddFormatParamStr(NameAndExtOf(FileName^));
  1396. AddFormatParamInt(Line);
  1397. if ChoiceBox(msg_couldnotsetbreakpointat,@FormatParams,[btn_ok,button_DisableAllBreakpoints],false)=cmUserBtn2 then
  1398. Debugger^.Disableallinvalidbreakpoints:=true;
  1399. end
  1400. else
  1401. begin
  1402. ClearFormatParams;
  1403. AddFormatParamStr(BreakpointTypeStr[typ]);
  1404. AddFormatParamStr(GetStr(Name));
  1405. if ChoiceBox(msg_couldnotsetbreakpointtype,@FormatParams,[btn_ok,button_DisableAllBreakpoints],false)=cmUserBtn2 then
  1406. Debugger^.Disableallinvalidbreakpoints:=true;
  1407. end;
  1408. end;
  1409. state:=bs_disabled;
  1410. UpdateSource;
  1411. end;
  1412. end
  1413. else if (GDBState=bs_disabled) and (state=bs_enabled) then
  1414. Enable
  1415. else if (GDBState=bs_enabled) and (state=bs_disabled) then
  1416. Disable;
  1417. end;
  1418. procedure TBreakpoint.Remove;
  1419. begin
  1420. If not assigned(Debugger) then Exit;
  1421. if GDBIndex>0 then
  1422. Debugger^.Command('delete '+IntToStr(GDBIndex));
  1423. GDBIndex:=0;
  1424. GDBState:=bs_deleted;
  1425. end;
  1426. procedure TBreakpoint.Enable;
  1427. begin
  1428. If not assigned(Debugger) then Exit;
  1429. if GDBIndex>0 then
  1430. Debugger^.Command('enable '+IntToStr(GDBIndex))
  1431. else
  1432. Insert;
  1433. GDBState:=bs_enabled;
  1434. end;
  1435. procedure TBreakpoint.Disable;
  1436. begin
  1437. If not assigned(Debugger) then Exit;
  1438. if GDBIndex>0 then
  1439. Debugger^.Command('disable '+IntToStr(GDBIndex));
  1440. GDBState:=bs_disabled;
  1441. end;
  1442. procedure TBreakpoint.ResetValues;
  1443. begin
  1444. if assigned(OldValue) then
  1445. DisposeStr(OldValue);
  1446. OldValue:=nil;
  1447. if assigned(CurrentValue) then
  1448. DisposeStr(CurrentValue);
  1449. CurrentValue:=nil;
  1450. end;
  1451. procedure TBreakpoint.UpdateSource;
  1452. var W: PSourceWindow;
  1453. b : boolean;
  1454. begin
  1455. if typ=bt_file_line then
  1456. begin
  1457. W:=SearchOnDesktop(FExpand(OSFileName(GetStr(FileName))),false);
  1458. If assigned(W) then
  1459. begin
  1460. if state=bs_enabled then
  1461. b:=true
  1462. else
  1463. b:=false;
  1464. W^.Editor^.SetLineFlagState(Line-1,lfBreakpoint,b);
  1465. end;
  1466. end;
  1467. end;
  1468. destructor TBreakpoint.Done;
  1469. begin
  1470. Remove;
  1471. ResetValues;
  1472. if assigned(Name) then
  1473. DisposeStr(Name);
  1474. if assigned(FileName) then
  1475. DisposeStr(FileName);
  1476. if assigned(Conditions) then
  1477. DisposeStr(Conditions);
  1478. if assigned(Commands) then
  1479. StrDispose(Commands);
  1480. inherited Done;
  1481. end;
  1482. {****************************************************************************
  1483. TBreakpointCollection
  1484. ****************************************************************************}
  1485. function TBreakpointCollection.At(Index: Integer): PBreakpoint;
  1486. begin
  1487. At:=inherited At(Index);
  1488. end;
  1489. procedure TBreakpointCollection.Update;
  1490. begin
  1491. if assigned(Debugger) then
  1492. begin
  1493. Debugger^.RemoveBreakpoints;
  1494. Debugger^.InsertBreakpoints;
  1495. end;
  1496. if assigned(BreakpointsWindow) then
  1497. BreakpointsWindow^.Update;
  1498. end;
  1499. function TBreakpointCollection.GetGDB(index : longint) : PBreakpoint;
  1500. function IsNum(P : PBreakpoint) : boolean;{$ifndef FPC}far;{$endif}
  1501. begin
  1502. IsNum:=P^.GDBIndex=index;
  1503. end;
  1504. begin
  1505. if index=0 then
  1506. GetGDB:=nil
  1507. else
  1508. GetGDB:=FirstThat(@IsNum);
  1509. end;
  1510. procedure TBreakpointCollection.ShowBreakpoints(W : PFPWindow);
  1511. procedure SetInSource(P : PBreakpoint);{$ifndef FPC}far;{$endif}
  1512. begin
  1513. If assigned(P^.FileName) and
  1514. (OSFileName(FExpand(P^.FileName^))=OSFileName(FExpand(PSourceWindow(W)^.Editor^.FileName))) then
  1515. PSourceWindow(W)^.Editor^.SetLineFlagState(P^.Line-1,lfBreakpoint,P^.state=bs_enabled);
  1516. end;
  1517. procedure SetInDisassembly(P : PBreakpoint);{$ifndef FPC}far;{$endif}
  1518. var
  1519. PDL : PDisasLine;
  1520. S : string;
  1521. ps,qs,i : longint;
  1522. begin
  1523. for i:=0 to PDisassemblyWindow(W)^.Editor^.GetLineCount-1 do
  1524. begin
  1525. PDL:=PDisasLine(PDisassemblyWindow(W)^.Editor^.GetLine(i));
  1526. if PDL^.Address=0 then
  1527. begin
  1528. if (P^.typ=bt_file_line) then
  1529. begin
  1530. S:=PDisassemblyWindow(W)^.Editor^.GetDisplayText(i);
  1531. ps:=pos(':',S);
  1532. qs:=pos(' ',copy(S,ps+1,High(S)));
  1533. if (GDBFileName(FExpand(P^.FileName^))=GDBFileName(FExpand(Copy(S,1,ps-1)))) and
  1534. (StrToInt(copy(S,ps+1,qs-1))=P^.line) then
  1535. PDisassemblyWindow(W)^.Editor^.SetLineFlagState(i,lfBreakpoint,P^.state=bs_enabled);
  1536. end;
  1537. end
  1538. else
  1539. begin
  1540. If (P^.typ=bt_address) and (PDL^.Address=HexToCard(P^.Name^)) then
  1541. PDisassemblyWindow(W)^.Editor^.SetLineFlagState(i,lfBreakpoint,P^.state=bs_enabled);
  1542. end;
  1543. end;
  1544. end;
  1545. begin
  1546. if W=PFPWindow(DisassemblyWindow) then
  1547. ForEach(@SetInDisassembly)
  1548. else
  1549. ForEach(@SetInSource);
  1550. end;
  1551. procedure TBreakpointCollection.AdaptBreakpoints(Editor : PSourceEditor; Pos, Change : longint);
  1552. procedure AdaptInSource(P : PBreakpoint);{$ifndef FPC}far;{$endif}
  1553. begin
  1554. If assigned(P^.FileName) and
  1555. (OSFileName(FExpand(P^.FileName^))=OSFileName(FExpand(Editor^.FileName))) then
  1556. begin
  1557. if P^.state=bs_enabled then
  1558. Editor^.SetLineFlagState(P^.Line-1,lfBreakpoint,false);
  1559. if P^.Line-1>=Pos then
  1560. begin
  1561. if (Change>0) or (P^.Line-1>=Pos-Change) then
  1562. P^.line:=P^.Line+Change
  1563. else
  1564. begin
  1565. { removing inside a ForEach call leads to problems }
  1566. { so we do that after PM }
  1567. P^.state:=bs_delete_after;
  1568. end;
  1569. end;
  1570. if P^.state=bs_enabled then
  1571. Editor^.SetLineFlagState(P^.Line-1,lfBreakpoint,true);
  1572. end;
  1573. end;
  1574. var
  1575. I : longint;
  1576. begin
  1577. ForEach(@AdaptInSource);
  1578. I:=Count-1;
  1579. While (I>=0) do
  1580. begin
  1581. if At(I)^.state=bs_delete_after then
  1582. AtFree(I);
  1583. Dec(I);
  1584. end;
  1585. end;
  1586. procedure TBreakpointCollection.ShowAllBreakpoints;
  1587. procedure SetInSource(P : PBreakpoint);{$ifndef FPC}far;{$endif}
  1588. var
  1589. W : PSourceWindow;
  1590. begin
  1591. If assigned(P^.FileName) then
  1592. begin
  1593. W:=SearchOnDesktop(P^.FileName^,false);
  1594. if assigned(W) then
  1595. W^.Editor^.SetLineFlagState(P^.Line-1,lfBreakpoint,P^.state=bs_enabled);
  1596. end;
  1597. end;
  1598. begin
  1599. ForEach(@SetInSource);
  1600. end;
  1601. function TBreakpointCollection.GetType(typ : BreakpointType;Const s : String) : PBreakpoint;
  1602. function IsThis(P : PBreakpoint) : boolean;{$ifndef FPC}far;{$endif}
  1603. begin
  1604. IsThis:=(P^.typ=typ) and (GetStr(P^.Name)=S);
  1605. end;
  1606. begin
  1607. GetType:=FirstThat(@IsThis);
  1608. end;
  1609. function TBreakpointCollection.ToggleFileLine(FileName: String;LineNr : Longint) : boolean;
  1610. var PB : PBreakpoint;
  1611. function IsThere(P : PBreakpoint) : boolean;{$ifndef FPC}far;{$endif}
  1612. begin
  1613. IsThere:=(P^.typ=bt_file_line) and assigned(P^.FileName) and
  1614. (OSFileName(FExpand(P^.FileName^))=FileName) and (P^.Line=LineNr);
  1615. end;
  1616. begin
  1617. FileName:=OSFileName(FileName);
  1618. PB:=FirstThat(@IsThere);
  1619. ToggleFileLine:=false;
  1620. If Assigned(PB) then
  1621. if PB^.state=bs_disabled then
  1622. begin
  1623. PB^.state:=bs_enabled;
  1624. ToggleFileLine:=true;
  1625. end
  1626. else if PB^.state=bs_enabled then
  1627. PB^.state:=bs_disabled;
  1628. If not assigned(PB) then
  1629. begin
  1630. PB:= New(PBreakpoint,Init_file_line(FileName,LineNr));
  1631. if assigned(PB) then
  1632. Begin
  1633. Insert(PB);
  1634. ToggleFileLine:=true;
  1635. End;
  1636. end;
  1637. if assigned(PB) then
  1638. PB^.UpdateSource;
  1639. Update;
  1640. end;
  1641. {****************************************************************************
  1642. TBreakpointItem
  1643. ****************************************************************************}
  1644. constructor TBreakpointItem.Init(ABreakpoint : PBreakpoint);
  1645. begin
  1646. inherited Init;
  1647. Breakpoint:=ABreakpoint;
  1648. end;
  1649. function TBreakpointItem.GetText(MaxLen: Sw_integer): string;
  1650. var S: string;
  1651. begin
  1652. with Breakpoint^ do
  1653. begin
  1654. S:=BreakpointTypeStr[typ];
  1655. While Length(S)<10 do
  1656. S:=S+' ';
  1657. S:=S+'|';
  1658. S:=S+BreakpointStateStr[state]+' ';
  1659. While Length(S)<20 do
  1660. S:=S+' ';
  1661. S:=S+'|';
  1662. if (typ=bt_file_line) then
  1663. S:=S+NameAndExtOf(GetStr(FileName))+':'+IntToStr(Line)
  1664. else
  1665. S:=S+GetStr(name);
  1666. While Length(S)<40 do
  1667. S:=S+' ';
  1668. S:=S+'|';
  1669. if IgnoreCount>0 then
  1670. S:=S+IntToStr(IgnoreCount);
  1671. While Length(S)<49 do
  1672. S:=S+' ';
  1673. S:=S+'|';
  1674. if assigned(Conditions) then
  1675. S:=S+' '+GetStr(Conditions);
  1676. if length(S)>MaxLen then S:=copy(S,1,MaxLen-2)+'..';
  1677. GetText:=S;
  1678. end;
  1679. end;
  1680. procedure TBreakpointItem.Selected;
  1681. begin
  1682. end;
  1683. function TBreakpointItem.GetModuleName: string;
  1684. begin
  1685. if breakpoint^.typ=bt_file_line then
  1686. GetModuleName:=GetStr(breakpoint^.FileName)
  1687. else
  1688. GetModuleName:='';
  1689. end;
  1690. {****************************************************************************
  1691. TBreakpointsListBox
  1692. ****************************************************************************}
  1693. constructor TBreakpointsListBox.Init(var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar);
  1694. begin
  1695. inherited Init(Bounds,1,AHScrollBar, AVScrollBar);
  1696. GrowMode:=gfGrowLoX+gfGrowHiX+gfGrowHiY;
  1697. NoSelection:=true;
  1698. end;
  1699. function TBreakpointsListBox.GetLocalMenu: PMenu;
  1700. var M: PMenu;
  1701. begin
  1702. if (Owner<>nil) and (Owner^.GetState(sfModal)) then M:=nil else
  1703. M:=NewMenu(
  1704. NewItem(menu_bplocal_gotosource,'',kbNoKey,cmMsgGotoSource,hcMsgGotoSource,
  1705. NewItem(menu_bplocal_editbreakpoint,'',kbNoKey,cmEditBreakpoint,hcEditBreakpoint,
  1706. NewItem(menu_bplocal_newbreakpoint,'',kbNoKey,cmNewBreakpoint,hcNewBreakpoint,
  1707. NewItem(menu_bplocal_deletebreakpoint,'',kbNoKey,cmDeleteBreakpoint,hcDeleteBreakpoint,
  1708. NewItem(menu_bplocal_togglestate,'',kbNoKey,cmToggleBreakpoint,hcToggleBreakpoint,
  1709. nil))))));
  1710. GetLocalMenu:=M;
  1711. end;
  1712. procedure TBreakpointsListBox.HandleEvent(var Event: TEvent);
  1713. var DontClear: boolean;
  1714. begin
  1715. case Event.What of
  1716. evKeyDown :
  1717. begin
  1718. DontClear:=false;
  1719. case Event.KeyCode of
  1720. kbEnter :
  1721. Message(@Self,evCommand,cmMsgGotoSource,nil);
  1722. kbIns :
  1723. Message(@Self,evCommand,cmNewBreakpoint,nil);
  1724. kbDel :
  1725. Message(@Self,evCommand,cmDeleteBreakpoint,nil);
  1726. else
  1727. DontClear:=true;
  1728. end;
  1729. if not DontClear then
  1730. ClearEvent(Event);
  1731. end;
  1732. evBroadcast :
  1733. case Event.Command of
  1734. cmListItemSelected :
  1735. if Event.InfoPtr=@Self then
  1736. Message(@Self,evCommand,cmEditBreakpoint,nil);
  1737. end;
  1738. evCommand :
  1739. begin
  1740. DontClear:=false;
  1741. case Event.Command of
  1742. cmMsgTrackSource :
  1743. if Range>0 then
  1744. TrackSource;
  1745. cmEditBreakpoint :
  1746. EditCurrent;
  1747. cmToggleBreakpoint :
  1748. ToggleCurrent;
  1749. cmDeleteBreakpoint :
  1750. DeleteCurrent;
  1751. cmNewBreakpoint :
  1752. EditNew;
  1753. cmMsgClear :
  1754. Clear;
  1755. else
  1756. DontClear:=true;
  1757. end;
  1758. if not DontClear then
  1759. ClearEvent(Event);
  1760. end;
  1761. end;
  1762. inherited HandleEvent(Event);
  1763. end;
  1764. procedure TBreakpointsListBox.AddBreakpoint(P: PBreakpointItem);
  1765. var W : integer;
  1766. begin
  1767. if List=nil then New(List, Init(20,20));
  1768. W:=length(P^.GetText(255));
  1769. if W>MaxWidth then
  1770. begin
  1771. MaxWidth:=W;
  1772. if HScrollBar<>nil then
  1773. HScrollBar^.SetRange(0,MaxWidth);
  1774. end;
  1775. List^.Insert(P);
  1776. SetRange(List^.Count);
  1777. if Focused=List^.Count-1-1 then
  1778. FocusItem(List^.Count-1);
  1779. P^.Breakpoint^.UpdateSource;
  1780. DrawView;
  1781. end;
  1782. (* function TBreakpointsListBox.AddModuleName(const Name: string): PString;
  1783. var P: PString;
  1784. begin
  1785. if ModuleNames<>nil then
  1786. P:=ModuleNames^.Add(Name)
  1787. else
  1788. P:=nil;
  1789. AddModuleName:=P;
  1790. end; *)
  1791. function TBreakpointsListBox.GetText(Item,MaxLen: Sw_Integer): String;
  1792. var P: PBreakpointItem;
  1793. S: string;
  1794. begin
  1795. P:=List^.At(Item);
  1796. S:=P^.GetText(MaxLen);
  1797. GetText:=copy(S,1,MaxLen);
  1798. end;
  1799. procedure TBreakpointsListBox.Clear;
  1800. begin
  1801. if assigned(List) then
  1802. Dispose(List, Done);
  1803. List:=nil;
  1804. MaxWidth:=0;
  1805. (* if assigned(ModuleNames) then
  1806. ModuleNames^.FreeAll; *)
  1807. SetRange(0); DrawView;
  1808. Message(Application,evBroadcast,cmClearLineHighlights,@Self);
  1809. end;
  1810. procedure TBreakpointsListBox.TrackSource;
  1811. var W: PSourceWindow;
  1812. P: PBreakpointItem;
  1813. R: TRect;
  1814. (* Row,Col: sw_integer; *)
  1815. begin
  1816. (*Message(Application,evBroadcast,cmClearLineHighlights,@Self);
  1817. if Range=0 then Exit;*)
  1818. P:=List^.At(Focused);
  1819. if P^.GetModuleName='' then Exit;
  1820. Desktop^.Lock;
  1821. GetNextEditorBounds(R);
  1822. R.B.Y:=Owner^.Origin.Y;
  1823. W:=EditorWindowFile(P^.GetModuleName);
  1824. if assigned(W) then
  1825. begin
  1826. W^.GetExtent(R);
  1827. R.B.Y:=Owner^.Origin.Y;
  1828. W^.ChangeBounds(R);
  1829. W^.Editor^.SetCurPtr(1,P^.Breakpoint^.Line);
  1830. end
  1831. else
  1832. W:=TryToOpenFile(@R,P^.GetModuleName,1,P^.Breakpoint^.Line,true);
  1833. if W<>nil then
  1834. begin
  1835. W^.Select;
  1836. W^.Editor^.TrackCursor(true);
  1837. W^.Editor^.SetLineFlagExclusive(lfHighlightRow,P^.Breakpoint^.Line);
  1838. end;
  1839. if Assigned(Owner) then
  1840. Owner^.Select;
  1841. Desktop^.UnLock;
  1842. end;
  1843. procedure TBreakpointsListBox.ToggleCurrent;
  1844. var
  1845. P: PBreakpointItem;
  1846. begin
  1847. if Range=0 then Exit;
  1848. P:=List^.At(Focused);
  1849. if P=nil then Exit;
  1850. if P^.Breakpoint^.state=bs_enabled then
  1851. P^.Breakpoint^.state:=bs_disabled
  1852. else if P^.Breakpoint^.state=bs_disabled then
  1853. P^.Breakpoint^.state:=bs_enabled;
  1854. P^.Breakpoint^.UpdateSource;
  1855. BreakpointsCollection^.Update;
  1856. end;
  1857. procedure TBreakpointsListBox.EditCurrent;
  1858. var
  1859. P: PBreakpointItem;
  1860. begin
  1861. if Range=0 then Exit;
  1862. P:=List^.At(Focused);
  1863. if P=nil then Exit;
  1864. Application^.ExecuteDialog(New(PBreakpointItemDialog,Init(P^.Breakpoint)),nil);
  1865. P^.Breakpoint^.UpdateSource;
  1866. BreakpointsCollection^.Update;
  1867. end;
  1868. procedure TBreakpointsListBox.DeleteCurrent;
  1869. var
  1870. P: PBreakpointItem;
  1871. begin
  1872. if Range=0 then Exit;
  1873. P:=List^.At(Focused);
  1874. if P=nil then Exit;
  1875. { delete it form source window }
  1876. P^.Breakpoint^.state:=bs_disabled;
  1877. P^.Breakpoint^.UpdateSource;
  1878. BreakpointsCollection^.free(P^.Breakpoint);
  1879. List^.free(P);
  1880. BreakpointsCollection^.Update;
  1881. end;
  1882. procedure TBreakpointsListBox.EditNew;
  1883. var
  1884. P: PBreakpoint;
  1885. begin
  1886. P:=New(PBreakpoint,Init_Empty);
  1887. if Application^.ExecuteDialog(New(PBreakpointItemDialog,Init(P)),nil)<>cmCancel then
  1888. begin
  1889. P^.UpdateSource;
  1890. BreakpointsCollection^.Insert(P);
  1891. BreakpointsCollection^.Update;
  1892. end
  1893. else
  1894. dispose(P,Done);
  1895. end;
  1896. procedure TBreakpointsListBox.Draw;
  1897. var
  1898. I, J, Item: Sw_Integer;
  1899. NormalColor, SelectedColor, FocusedColor, Color: Word;
  1900. ColWidth, CurCol, Indent: Integer;
  1901. B: TDrawBuffer;
  1902. Text: String;
  1903. SCOff: Byte;
  1904. TC: byte;
  1905. procedure MT(var C: word); begin if TC<>0 then C:=(C and $ff0f) or (TC and $f0); end;
  1906. begin
  1907. if (Owner<>nil) then TC:=ord(Owner^.GetColor(6)) else TC:=0;
  1908. if State and (sfSelected + sfActive) = (sfSelected + sfActive) then
  1909. begin
  1910. NormalColor := GetColor(1);
  1911. FocusedColor := GetColor(3);
  1912. SelectedColor := GetColor(4);
  1913. end else
  1914. begin
  1915. NormalColor := GetColor(2);
  1916. SelectedColor := GetColor(4);
  1917. end;
  1918. if Transparent then
  1919. begin MT(NormalColor); MT(SelectedColor); end;
  1920. if NoSelection then
  1921. SelectedColor:=NormalColor;
  1922. if HScrollBar <> nil then Indent := HScrollBar^.Value
  1923. else Indent := 0;
  1924. ColWidth := Size.X div NumCols + 1;
  1925. for I := 0 to Size.Y - 1 do
  1926. begin
  1927. for J := 0 to NumCols-1 do
  1928. begin
  1929. Item := J*Size.Y + I + TopItem;
  1930. CurCol := J*ColWidth;
  1931. if (State and (sfSelected + sfActive) = (sfSelected + sfActive)) and
  1932. (Focused = Item) and (Range > 0) then
  1933. begin
  1934. Color := FocusedColor;
  1935. SetCursor(CurCol+1,I);
  1936. SCOff := 0;
  1937. end
  1938. else if (Item < Range) and IsSelected(Item) then
  1939. begin
  1940. Color := SelectedColor;
  1941. SCOff := 2;
  1942. end
  1943. else
  1944. begin
  1945. Color := NormalColor;
  1946. SCOff := 4;
  1947. end;
  1948. MoveChar(B[CurCol], ' ', Color, ColWidth);
  1949. if Item < Range then
  1950. begin
  1951. Text := GetText(Item, ColWidth + Indent);
  1952. Text := Copy(Text,Indent,ColWidth);
  1953. MoveStr(B[CurCol+1], Text, Color);
  1954. if ShowMarkers then
  1955. begin
  1956. WordRec(B[CurCol]).Lo := Byte(SpecialChars[SCOff]);
  1957. WordRec(B[CurCol+ColWidth-2]).Lo := Byte(SpecialChars[SCOff+1]);
  1958. end;
  1959. end;
  1960. MoveChar(B[CurCol+ColWidth-1], #179, GetColor(5), 1);
  1961. end;
  1962. WriteLine(0, I, Size.X, 1, B);
  1963. end;
  1964. end;
  1965. constructor TBreakpointsListBox.Load(var S: TStream);
  1966. begin
  1967. inherited Load(S);
  1968. end;
  1969. procedure TBreakpointsListBox.Store(var S: TStream);
  1970. var OL: PCollection;
  1971. OldR : integer;
  1972. begin
  1973. OL:=List;
  1974. OldR:=Range;
  1975. Range:=0;
  1976. New(List, Init(1,1));
  1977. inherited Store(S);
  1978. Dispose(List, Done);
  1979. Range:=OldR;
  1980. List:=OL;
  1981. { ^^^ nasty trick - has anyone a better idea how to avoid storing the
  1982. collection? Pasting here a modified version of TListBox.Store+
  1983. TAdvancedListBox.Store isn't a better solution, since by eventually
  1984. changing the obj-hierarchy you'll always have to modify this, too - BG }
  1985. end;
  1986. destructor TBreakpointsListBox.Done;
  1987. begin
  1988. inherited Done;
  1989. if List<>nil then Dispose(List, Done);
  1990. (* if ModuleNames<>nil then Dispose(ModuleNames, Done);*)
  1991. end;
  1992. {****************************************************************************
  1993. TBreakpointsWindow
  1994. ****************************************************************************}
  1995. constructor TBreakpointsWindow.Init;
  1996. var R,R2: TRect;
  1997. HSB,VSB: PScrollBar;
  1998. ST: PStaticText;
  1999. S: String;
  2000. X,X1 : Sw_integer;
  2001. Btn: PButton;
  2002. const
  2003. NumButtons = 5;
  2004. begin
  2005. Desktop^.GetExtent(R); R.A.Y:=R.B.Y-18;
  2006. inherited Init(R, dialog_breakpointlist, wnNoNumber);
  2007. HelpCtx:=hcBreakpointListWindow;
  2008. GetExtent(R); R.Grow(-1,-1); R.B.Y:=R.A.Y+1;
  2009. S:=label_breakpointpropheader;
  2010. New(ST, Init(R,S));
  2011. ST^.GrowMode:=gfGrowHiX;
  2012. Insert(ST);
  2013. GetExtent(R); R.Grow(-1,-1); Inc(R.A.Y,1); R.B.Y:=R.A.Y+1;
  2014. New(ST, Init(R, CharStr('Ä', MaxViewWidth)));
  2015. ST^.GrowMode:=gfGrowHiX;
  2016. Insert(ST);
  2017. GetExtent(R); R.Grow(-1,-1); Inc(R.A.Y,2);Dec(R.B.Y,5);
  2018. R2.Copy(R); Inc(R2.B.Y); R2.A.Y:=R2.B.Y-1;
  2019. New(HSB, Init(R2)); HSB^.GrowMode:=gfGrowLoY+gfGrowHiY+gfGrowHiX; Insert(HSB);
  2020. HSB^.SetStep(R.B.X-R.A.X-2,1);
  2021. R2.Copy(R); Inc(R2.B.X); R2.A.X:=R2.B.X-1;
  2022. New(VSB, Init(R2)); VSB^.GrowMode:=gfGrowLoX+gfGrowHiX+gfGrowHiY; Insert(VSB);
  2023. VSB^.SetStep(R.B.Y-R.A.Y-2,1);
  2024. New(BreakLB, Init(R,HSB,VSB));
  2025. BreakLB^.GrowMode:=gfGrowHiX+gfGrowHiY;
  2026. BreakLB^.Transparent:=true;
  2027. Insert(BreakLB);
  2028. GetExtent(R);R.Grow(-1,-1);
  2029. Dec(R.B.Y);
  2030. R.A.Y:=R.B.Y-2;
  2031. X:=(R.B.X-R.A.X) div NumButtons;
  2032. X1:=R.A.X+(X div 2);
  2033. R.A.X:=X1-3;R.B.X:=X1+7;
  2034. New(Btn, Init(R, button_Close, cmClose, bfDefault));
  2035. Btn^.GrowMode:=gfGrowLoY+gfGrowHiY;
  2036. Insert(Btn);
  2037. X1:=X1+X;
  2038. R.A.X:=X1-3;R.B.X:=X1+7;
  2039. New(Btn, Init(R, button_New, cmNewBreakpoint, bfNormal));
  2040. Btn^.GrowMode:=gfGrowLoY+gfGrowHiY;
  2041. Insert(Btn);
  2042. X1:=X1+X;
  2043. R.A.X:=X1-3;R.B.X:=X1+7;
  2044. New(Btn, Init(R, button_Edit, cmEditBreakpoint, bfNormal));
  2045. Btn^.GrowMode:=gfGrowLoY+gfGrowHiY;
  2046. Insert(Btn);
  2047. X1:=X1+X;
  2048. R.A.X:=X1-3;R.B.X:=X1+7;
  2049. New(Btn, Init(R, button_ToggleButton, cmToggleBreakInList, bfNormal));
  2050. Btn^.GrowMode:=gfGrowLoY+gfGrowHiY;
  2051. Insert(Btn);
  2052. X1:=X1+X;
  2053. R.A.X:=X1-3;R.B.X:=X1+7;
  2054. New(Btn, Init(R, button_Delete, cmDeleteBreakpoint, bfNormal));
  2055. Btn^.GrowMode:=gfGrowLoY+gfGrowHiY;
  2056. Insert(Btn);
  2057. BreakLB^.Select;
  2058. Update;
  2059. BreakpointsWindow:=@self;
  2060. end;
  2061. constructor TBreakpointsWindow.Load(var S: TStream);
  2062. begin
  2063. inherited Load(S);
  2064. GetSubViewPtr(S,BreakLB);
  2065. end;
  2066. procedure TBreakpointsWindow.Store(var S: TStream);
  2067. begin
  2068. inherited Store(S);
  2069. PutSubViewPtr(S,BreakLB);
  2070. end;
  2071. procedure TBreakpointsWindow.AddBreakpoint(ABreakpoint : PBreakpoint);
  2072. begin
  2073. BreakLB^.AddBreakpoint(New(PBreakpointItem, Init(ABreakpoint)));
  2074. end;
  2075. procedure TBreakpointsWindow.ClearBreakpoints;
  2076. begin
  2077. BreakLB^.Clear;
  2078. ReDraw;
  2079. end;
  2080. procedure TBreakpointsWindow.ReloadBreakpoints;
  2081. procedure InsertInBreakLB(P : PBreakpoint);
  2082. begin
  2083. BreakLB^.AddBreakpoint(New(PBreakpointItem, Init(P)));
  2084. end;
  2085. begin
  2086. If not assigned(BreakpointsCollection) then
  2087. exit;
  2088. BreakpointsCollection^.ForEach(@InsertInBreakLB);
  2089. ReDraw;
  2090. end;
  2091. procedure TBreakpointsWindow.SizeLimits(var Min, Max: TPoint);
  2092. begin
  2093. inherited SizeLimits(Min,Max);
  2094. Min.X:=40; Min.Y:=18;
  2095. end;
  2096. procedure TBreakpointsWindow.Close;
  2097. begin
  2098. Hide;
  2099. end;
  2100. procedure TBreakpointsWindow.HandleEvent(var Event: TEvent);
  2101. var DontClear : boolean;
  2102. begin
  2103. case Event.What of
  2104. evKeyDown :
  2105. begin
  2106. if (Event.KeyCode=kbEnter) or (Event.KeyCode=kbEsc) then
  2107. begin
  2108. ClearEvent(Event);
  2109. Hide;
  2110. end;
  2111. end;
  2112. evCommand :
  2113. begin
  2114. DontClear:=False;
  2115. case Event.Command of
  2116. cmNewBreakpoint :
  2117. BreakLB^.EditNew;
  2118. cmEditBreakpoint :
  2119. BreakLB^.EditCurrent;
  2120. cmDeleteBreakpoint :
  2121. BreakLB^.DeleteCurrent;
  2122. cmToggleBreakInList :
  2123. BreakLB^.ToggleCurrent;
  2124. cmClose :
  2125. Hide;
  2126. else
  2127. DontClear:=true;
  2128. end;
  2129. if not DontClear then
  2130. ClearEvent(Event);
  2131. end;
  2132. evBroadcast :
  2133. case Event.Command of
  2134. cmUpdate :
  2135. Update;
  2136. end;
  2137. end;
  2138. inherited HandleEvent(Event);
  2139. end;
  2140. procedure TBreakpointsWindow.Update;
  2141. var
  2142. StoreFocus : longint;
  2143. begin
  2144. StoreFocus:=BreakLB^.Focused;
  2145. ClearBreakpoints;
  2146. ReloadBreakpoints;
  2147. If StoreFocus<BreakLB^.Range then
  2148. BreakLB^.FocusItem(StoreFocus);
  2149. end;
  2150. destructor TBreakpointsWindow.Done;
  2151. begin
  2152. inherited Done;
  2153. BreakpointsWindow:=nil;
  2154. end;
  2155. {****************************************************************************
  2156. TBreakpointItemDialog
  2157. ****************************************************************************}
  2158. constructor TBreakpointItemDialog.Init(ABreakpoint: PBreakpoint);
  2159. var R,R2,R3: TRect;
  2160. Items: PSItem;
  2161. I : BreakpointType;
  2162. KeyCount: sw_integer;
  2163. begin
  2164. KeyCount:=longint(high(BreakpointType));
  2165. R.Assign(0,0,60,Max(9+KeyCount,18));
  2166. inherited Init(R,dialog_modifynewbreakpoint);
  2167. Breakpoint:=ABreakpoint;
  2168. GetExtent(R); R.Grow(-3,-2); R3.Copy(R);
  2169. Inc(R.A.Y); R.B.Y:=R.A.Y+1; R.B.X:=R.B.X-3;
  2170. New(NameIL, Init(R, 255)); Insert(NameIL);
  2171. R2.Copy(R); R2.A.X:=R2.B.X; R2.B.X:=R2.A.X+3;
  2172. Insert(New(PHistory, Init(R2, NameIL, hidWatchDialog)));
  2173. R.Copy(R3); Inc(R.A.Y); R.B.Y:=R.A.Y+1;
  2174. R2.Copy(R); R2.Move(-1,-1);
  2175. Insert(New(PLabel, Init(R2, label_breakpoint_name, NameIL)));
  2176. R.Move(0,3);
  2177. New(ConditionsIL, Init(R, 255)); Insert(ConditionsIL);
  2178. R2.Copy(R); R2.Move(-1,-1); Insert(New(PLabel, Init(R2, label_breakpoint_conditions, ConditionsIL)));
  2179. R.Move(0,3); R.B.X:=R.A.X+36;
  2180. New(LineIL, Init(R, 128)); Insert(LineIL);
  2181. LineIL^.SetValidator(New(PRangeValidator, Init(0,MaxInt)));
  2182. R2.Copy(R); R2.Move(-1,-1); Insert(New(PLabel, Init(R2, label_breakpoint_line, LineIL)));
  2183. R.Move(0,3);
  2184. New(IgnoreIL, Init(R, 128)); Insert(IgnoreIL);
  2185. IgnoreIL^.SetValidator(New(PRangeValidator, Init(0,MaxInt)));
  2186. R2.Copy(R); R2.Move(-1,-1); Insert(New(PLabel, Init(R2, label_breakpoint_ignorecount, IgnoreIL)));
  2187. R.Copy(R3); Inc(R.A.X,38); Inc(R.A.Y,7); R.B.Y:=R.A.Y+KeyCount;
  2188. Items:=nil;
  2189. { don't use invalid type }
  2190. for I:=pred(high(BreakpointType)) downto low(BreakpointType) do
  2191. Items:=NewSItem(BreakpointTypeStr[I], Items);
  2192. New(TypeRB, Init(R, Items));
  2193. R2.Copy(R); R2.Move(-1,-1); R2.B.Y:=R2.A.Y+1;
  2194. Insert(New(PLabel, Init(R2, label_breakpoint_type, TypeRB)));
  2195. Insert(TypeRB);
  2196. InsertButtons(@Self);
  2197. NameIL^.Select;
  2198. end;
  2199. function TBreakpointItemDialog.Execute: Word;
  2200. var R: word;
  2201. S1: string;
  2202. err: word;
  2203. L: longint;
  2204. begin
  2205. R:=longint(Breakpoint^.typ);
  2206. TypeRB^.SetData(R);
  2207. If Breakpoint^.typ=bt_file_line then
  2208. S1:=GetStr(Breakpoint^.FileName)
  2209. else
  2210. S1:=GetStr(Breakpoint^.name);
  2211. NameIL^.SetData(S1);
  2212. If Breakpoint^.typ=bt_file_line then
  2213. S1:=IntToStr(Breakpoint^.Line)
  2214. else
  2215. S1:='0';
  2216. LineIL^.SetData(S1);
  2217. S1:=IntToStr(Breakpoint^.IgnoreCount);
  2218. IgnoreIL^.SetData(S1);
  2219. S1:=GetStr(Breakpoint^.Conditions);
  2220. ConditionsIL^.SetData(S1);
  2221. if assigned(FirstEditorWindow) then
  2222. FindReplaceEditor:=FirstEditorWindow^.Editor;
  2223. R:=inherited Execute;
  2224. FindReplaceEditor:=nil;
  2225. if R=cmOK then
  2226. begin
  2227. TypeRB^.GetData(R);
  2228. L:=R;
  2229. Breakpoint^.typ:=BreakpointType(L);
  2230. NameIL^.GetData(S1);
  2231. If Breakpoint^.typ=bt_file_line then
  2232. begin
  2233. If assigned(Breakpoint^.FileName) then
  2234. DisposeStr(Breakpoint^.FileName);
  2235. Breakpoint^.FileName:=NewStr(S1);
  2236. end
  2237. else
  2238. begin
  2239. If assigned(Breakpoint^.Name) then
  2240. DisposeStr(Breakpoint^.Name);
  2241. Breakpoint^.name:=NewStr(S1);
  2242. end;
  2243. If Breakpoint^.typ=bt_file_line then
  2244. begin
  2245. LineIL^.GetData(S1);
  2246. Val(S1,L,err);
  2247. Breakpoint^.Line:=L;
  2248. end;
  2249. IgnoreIL^.GetData(S1);
  2250. Val(S1,L,err);
  2251. Breakpoint^.IgnoreCount:=L;
  2252. ConditionsIL^.GetData(S1);
  2253. If assigned(Breakpoint^.Conditions) then
  2254. DisposeStr(Breakpoint^.Conditions);
  2255. Breakpoint^.Conditions:=NewStr(S1);
  2256. end;
  2257. Execute:=R;
  2258. end;
  2259. {****************************************************************************
  2260. TWatch
  2261. ****************************************************************************}
  2262. constructor TWatch.Init(s : string);
  2263. begin
  2264. expr:=NewStr(s);
  2265. last_value:=nil;
  2266. current_value:=nil;
  2267. Get_new_value;
  2268. GDBRunCount:=-1;
  2269. end;
  2270. constructor TWatch.Load(var S: TStream);
  2271. begin
  2272. expr:=S.ReadStr;
  2273. last_value:=nil;
  2274. current_value:=nil;
  2275. Get_new_value;
  2276. GDBRunCount:=-1;
  2277. end;
  2278. procedure TWatch.Store(var S: TStream);
  2279. begin
  2280. S.WriteStr(expr);
  2281. end;
  2282. procedure TWatch.rename(s : string);
  2283. begin
  2284. if assigned(expr) then
  2285. begin
  2286. if GetStr(expr)=S then
  2287. exit;
  2288. DisposeStr(expr);
  2289. end;
  2290. expr:=NewStr(s);
  2291. if assigned(last_value) then
  2292. StrDispose(last_value);
  2293. last_value:=nil;
  2294. if assigned(current_value) then
  2295. StrDispose(current_value);
  2296. current_value:=nil;
  2297. GDBRunCount:=-1;
  2298. Get_new_value;
  2299. end;
  2300. procedure TWatch.Get_new_value;
  2301. var p, q : pchar;
  2302. i, j, curframe, startframe : longint;
  2303. s,s2 : string;
  2304. loop_higher, found : boolean;
  2305. last_removed : char;
  2306. function GetValue(var s : string) : boolean;
  2307. begin
  2308. Debugger^.command('p '+s);
  2309. if not Debugger^.Error then
  2310. begin
  2311. s:=StrPas(Debugger^.GetOutput);
  2312. GetValue:=true;
  2313. end
  2314. else
  2315. begin
  2316. s:=StrPas(Debugger^.GetError);
  2317. GetValue:=false;
  2318. { do not open a messagebox for such errors }
  2319. Debugger^.got_error:=false;
  2320. end;
  2321. end;
  2322. begin
  2323. If not assigned(Debugger) or Not Debugger^.HasExe or
  2324. (GDBRunCount=Debugger^.RunCount) then
  2325. exit;
  2326. GDBRunCount:=Debugger^.RunCount;
  2327. if assigned(last_value) then
  2328. strdispose(last_value);
  2329. last_value:=current_value;
  2330. s:=GetStr(expr);
  2331. found:=GetValue(s);
  2332. Debugger^.got_error:=false;
  2333. loop_higher:=not found;
  2334. if not found then
  2335. begin
  2336. curframe:=Debugger^.get_current_frame;
  2337. startframe:=curframe;
  2338. end
  2339. else
  2340. begin
  2341. curframe:=0;
  2342. startframe:=0;
  2343. end;
  2344. while loop_higher do
  2345. begin
  2346. s:='parent_ebp';
  2347. if GetValue(s) then
  2348. begin
  2349. repeat
  2350. inc(curframe);
  2351. if not Debugger^.set_current_frame(curframe) then
  2352. loop_higher:=false;
  2353. {$ifdef FrameNameKnown}
  2354. s2:='/x '+FrameName;
  2355. {$else not FrameNameKnown}
  2356. s2:='/x $ebp';
  2357. {$endif FrameNameKnown}
  2358. getValue(s2);
  2359. j:=pos('=',s2);
  2360. if j>0 then
  2361. s2:=copy(s2,j+1,length(s2));
  2362. while s2[1] in [' ',TAB] do
  2363. delete(s2,1,1);
  2364. if pos(s2,s)>0 then
  2365. loop_higher :=false;
  2366. until not loop_higher;
  2367. { try again at that level }
  2368. s:=GetStr(expr);
  2369. found:=GetValue(s);
  2370. loop_higher:=not found;
  2371. end
  2372. else
  2373. loop_higher:=false;
  2374. end;
  2375. if found then
  2376. p:=StrNew(Debugger^.GetOutput)
  2377. else
  2378. begin
  2379. { get a reasonable output at least }
  2380. s:=GetStr(expr);
  2381. GetValue(s);
  2382. p:=StrNew(Debugger^.GetError);
  2383. end;
  2384. Debugger^.got_error:=false;
  2385. { We should try here to find the expr in parent
  2386. procedure if there are
  2387. I will implement this as I added a
  2388. parent_ebp pseudo local var to local procedure
  2389. in stabs debug info PM }
  2390. { But there are some pitfalls like
  2391. locals redefined in other sublocals that call the function }
  2392. if curframe<>startframe then
  2393. Debugger^.set_current_frame(startframe);
  2394. q:=nil;
  2395. if assigned(p) and (p[0]='$') then
  2396. q:=StrPos(p,'=');
  2397. if not assigned(q) then
  2398. q:=p;
  2399. if assigned(q) then
  2400. i:=strlen(q)
  2401. else
  2402. i:=0;
  2403. if (i>0) and (q[i-1]=#10) then
  2404. begin
  2405. while (i>1) and ((q[i-2]=' ') or (q[i-2]=#9)) do
  2406. dec(i);
  2407. last_removed:=q[i-1];
  2408. q[i-1]:=#0;
  2409. end
  2410. else
  2411. last_removed:=#0;
  2412. if assigned(q) then
  2413. current_value:=strnew(q)
  2414. else
  2415. current_value:=strnew('');
  2416. if last_removed<>#0 then
  2417. q[i-1]:=last_removed;
  2418. strdispose(p);
  2419. GDBRunCount:=Debugger^.RunCount;
  2420. end;
  2421. procedure TWatch.Force_new_value;
  2422. begin
  2423. GDBRunCount:=-1;
  2424. Get_new_value;
  2425. end;
  2426. destructor TWatch.Done;
  2427. begin
  2428. if assigned(expr) then
  2429. disposestr(expr);
  2430. if assigned(last_value) then
  2431. strdispose(last_value);
  2432. if assigned(current_value) then
  2433. strdispose(current_value);
  2434. inherited done;
  2435. end;
  2436. {****************************************************************************
  2437. TWatchesCollection
  2438. ****************************************************************************}
  2439. constructor TWatchesCollection.Init;
  2440. begin
  2441. inherited Init(10,10);
  2442. end;
  2443. procedure TWatchesCollection.Insert(Item: Pointer);
  2444. begin
  2445. PWatch(Item)^.Get_new_value;
  2446. Inherited Insert(Item);
  2447. Update;
  2448. end;
  2449. procedure TWatchesCollection.Update;
  2450. var
  2451. W,W1 : integer;
  2452. procedure GetMax(P : PWatch);
  2453. begin
  2454. if assigned(P^.Current_value) then
  2455. W1:=StrLen(P^.Current_value)+3+Length(GetStr(P^.expr))
  2456. else
  2457. W1:=2+Length(GetStr(P^.expr));
  2458. if W1>W then
  2459. W:=W1;
  2460. end;
  2461. begin
  2462. W:=0;
  2463. ForEach(@GetMax);
  2464. MaxW:=W;
  2465. If assigned(WatchesWindow) then
  2466. WatchesWindow^.WLB^.Update(MaxW);
  2467. end;
  2468. function TWatchesCollection.At(Index: Integer): PWatch;
  2469. begin
  2470. At:=Inherited At(Index);
  2471. end;
  2472. {****************************************************************************
  2473. TWatchesListBox
  2474. ****************************************************************************}
  2475. constructor TWatchesListBox.Init(var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar);
  2476. begin
  2477. inherited Init(Bounds,1,AHScrollBar,AVScrollBar);
  2478. If assigned(List) then
  2479. dispose(list,done);
  2480. List:=WatchesCollection;
  2481. end;
  2482. procedure TWatchesListBox.Update(AMaxWidth : integer);
  2483. var R : TRect;
  2484. begin
  2485. GetExtent(R);
  2486. MaxWidth:=AMaxWidth;
  2487. if (HScrollBar<>nil) and (R.B.X-R.A.X<MaxWidth) then
  2488. HScrollBar^.SetRange(0,MaxWidth-(R.B.X-R.A.X))
  2489. else
  2490. HScrollBar^.SetRange(0,0);
  2491. if R.B.X-R.A.X>MaxWidth then
  2492. HScrollBar^.Hide
  2493. else
  2494. HScrollBar^.Show;
  2495. SetRange(List^.Count+1);
  2496. if R.B.Y-R.A.Y>Range then
  2497. VScrollBar^.Hide
  2498. else
  2499. VScrollBar^.Show;
  2500. {if Focused=List^.Count-1-1 then
  2501. FocusItem(List^.Count-1);
  2502. What was that for ?? PM }
  2503. DrawView;
  2504. end;
  2505. function TWatchesListBox.GetIndentedText(Item,Indent,MaxLen: Sw_Integer;var Modified : boolean): String;
  2506. var
  2507. PW : PWatch;
  2508. ValOffset : Sw_integer;
  2509. S : String;
  2510. begin
  2511. Modified:=false;
  2512. if Item>=WatchesCollection^.Count then
  2513. begin
  2514. GetIndentedText:='';
  2515. exit;
  2516. end;
  2517. PW:=WatchesCollection^.At(Item);
  2518. ValOffset:=Length(GetStr(PW^.Expr))+2;
  2519. if not assigned(PW^.expr) then
  2520. GetIndentedText:=''
  2521. else if Indent<ValOffset then
  2522. begin
  2523. S:=GetStr(PW^.Expr);
  2524. if Indent=0 then
  2525. S:=' '+S
  2526. else
  2527. S:=Copy(S,Indent,High(S));
  2528. if not assigned(PW^.current_value) then
  2529. S:=S+' <Unknown value>'
  2530. else
  2531. S:=S+' '+GetPChar(PW^.Current_value);
  2532. GetIndentedText:=Copy(S,1,MaxLen);
  2533. end
  2534. else
  2535. begin
  2536. if not assigned(PW^.Current_value) or
  2537. (StrLen(PW^.Current_value)<Indent-Valoffset) then
  2538. S:=''
  2539. else
  2540. S:=GetPchar(@(PW^.Current_Value[Indent-Valoffset]));
  2541. GetIndentedText:=Copy(S,1,MaxLen);
  2542. end;
  2543. if assigned(PW^.current_value) and
  2544. assigned(PW^.last_value) and
  2545. (strcomp(PW^.Last_value,PW^.Current_value)<>0) then
  2546. Modified:=true;
  2547. end;
  2548. procedure TWatchesListBox.EditCurrent;
  2549. var
  2550. P: PWatch;
  2551. begin
  2552. if Range=0 then Exit;
  2553. if Focused<WatchesCollection^.Count then
  2554. P:=WatchesCollection^.At(Focused)
  2555. else
  2556. P:=New(PWatch,Init(''));
  2557. Application^.ExecuteDialog(New(PWatchItemDialog,Init(P)),nil);
  2558. WatchesCollection^.Update;
  2559. end;
  2560. function TWatchesListBox.GetText (Item: Sw_Integer; MaxLen: Sw_Integer): String;
  2561. var
  2562. Dummy_Modified : boolean;
  2563. begin
  2564. GetText:=GetIndentedText(Item, 0, MaxLen, Dummy_Modified);
  2565. end;
  2566. procedure TWatchesListBox.DeleteCurrent;
  2567. var
  2568. P: PWatch;
  2569. begin
  2570. if (Range=0) or
  2571. (Focused>=WatchesCollection^.Count) then
  2572. exit;
  2573. P:=WatchesCollection^.At(Focused);
  2574. WatchesCollection^.free(P);
  2575. WatchesCollection^.Update;
  2576. end;
  2577. procedure TWatchesListBox.EditNew;
  2578. var
  2579. P: PWatch;
  2580. S : string;
  2581. begin
  2582. if Focused<WatchesCollection^.Count then
  2583. begin
  2584. P:=WatchesCollection^.At(Focused);
  2585. S:=GetStr(P^.expr);
  2586. end
  2587. else
  2588. S:='';
  2589. P:=New(PWatch,Init(S));
  2590. if Application^.ExecuteDialog(New(PWatchItemDialog,Init(P)),nil)<>cmCancel then
  2591. begin
  2592. WatchesCollection^.AtInsert(Focused,P);
  2593. WatchesCollection^.Update;
  2594. end
  2595. else
  2596. dispose(P,Done);
  2597. end;
  2598. procedure TWatchesListBox.Draw;
  2599. var
  2600. I, J, Item: Sw_Integer;
  2601. NormalColor, SelectedColor, FocusedColor, Color: Word;
  2602. ColWidth, CurCol, Indent: Integer;
  2603. B: TDrawBuffer;
  2604. Modified : boolean;
  2605. Text: String;
  2606. SCOff: Byte;
  2607. TC: byte;
  2608. procedure MT(var C: word);
  2609. begin
  2610. if TC<>0 then C:=(C and $ff0f) or (TC and $f0);
  2611. end;
  2612. begin
  2613. if (Owner<>nil) then TC:=ord(Owner^.GetColor(6)) else TC:=0;
  2614. if State and (sfSelected + sfActive) = (sfSelected + sfActive) then
  2615. begin
  2616. NormalColor := GetColor(1);
  2617. FocusedColor := GetColor(3);
  2618. SelectedColor := GetColor(4);
  2619. end else
  2620. begin
  2621. NormalColor := GetColor(2);
  2622. SelectedColor := GetColor(4);
  2623. end;
  2624. if Transparent then
  2625. begin MT(NormalColor); MT(SelectedColor); end;
  2626. (* if NoSelection then
  2627. SelectedColor:=NormalColor;*)
  2628. if HScrollBar <> nil then Indent := HScrollBar^.Value
  2629. else Indent := 0;
  2630. ColWidth := Size.X div NumCols + 1;
  2631. for I := 0 to Size.Y - 1 do
  2632. begin
  2633. for J := 0 to NumCols-1 do
  2634. begin
  2635. Item := J*Size.Y + I + TopItem;
  2636. CurCol := J*ColWidth;
  2637. if (State and (sfSelected + sfActive) = (sfSelected + sfActive)) and
  2638. (Focused = Item) and (Range > 0) then
  2639. begin
  2640. Color := FocusedColor;
  2641. SetCursor(CurCol+1,I);
  2642. SCOff := 0;
  2643. end
  2644. else if (Item < Range) and IsSelected(Item) then
  2645. begin
  2646. Color := SelectedColor;
  2647. SCOff := 2;
  2648. end
  2649. else
  2650. begin
  2651. Color := NormalColor;
  2652. SCOff := 4;
  2653. end;
  2654. MoveChar(B[CurCol], ' ', Color, ColWidth);
  2655. if Item < Range then
  2656. begin
  2657. (* Text := GetText(Item, ColWidth + Indent);
  2658. Text := Copy(Text,Indent,ColWidth); *)
  2659. Text:=GetIndentedText(Item,Indent,ColWidth,Modified);
  2660. if modified then
  2661. begin
  2662. SCOff:=0;
  2663. Color:=(Color and $fff0) or Red;
  2664. end;
  2665. MoveStr(B[CurCol], Text, Color);
  2666. if {ShowMarkers or } Modified then
  2667. begin
  2668. WordRec(B[CurCol]).Lo := Byte(SpecialChars[SCOff]);
  2669. WordRec(B[CurCol+ColWidth-2]).Lo := Byte(SpecialChars[SCOff+1]);
  2670. WordRec(B[CurCol+ColWidth-2]).Hi := Color and $ff;
  2671. end;
  2672. end;
  2673. MoveChar(B[CurCol+ColWidth-1], #179, GetColor(5), 1);
  2674. end;
  2675. WriteLine(0, I, Size.X, 1, B);
  2676. end;
  2677. end;
  2678. function TWatchesListBox.GetLocalMenu: PMenu;
  2679. var M: PMenu;
  2680. begin
  2681. if (Owner<>nil) and (Owner^.GetState(sfModal)) then M:=nil else
  2682. M:=NewMenu(
  2683. NewItem(menu_watchlocal_edit,'',kbNoKey,cmEdit,hcNoContext,
  2684. NewItem(menu_watchlocal_new,'',kbNoKey,cmNew,hcNoContext,
  2685. NewItem(menu_watchlocal_delete,'',kbNoKey,cmDelete,hcNoContext,
  2686. NewLine(
  2687. NewItem(menu_msglocal_saveas,'',kbNoKey,cmSaveAs,hcSaveAs,
  2688. nil))))));
  2689. GetLocalMenu:=M;
  2690. end;
  2691. procedure TWatchesListBox.HandleEvent(var Event: TEvent);
  2692. var DontClear: boolean;
  2693. begin
  2694. case Event.What of
  2695. evKeyDown :
  2696. begin
  2697. DontClear:=false;
  2698. case Event.KeyCode of
  2699. kbEnter :
  2700. Message(@Self,evCommand,cmEdit,nil);
  2701. kbIns :
  2702. Message(@Self,evCommand,cmNew,nil);
  2703. kbDel :
  2704. Message(@Self,evCommand,cmDelete,nil);
  2705. else
  2706. DontClear:=true;
  2707. end;
  2708. if not DontClear then
  2709. ClearEvent(Event);
  2710. end;
  2711. evBroadcast :
  2712. case Event.Command of
  2713. cmListItemSelected :
  2714. if Event.InfoPtr=@Self then
  2715. Message(@Self,evCommand,cmEdit,nil);
  2716. end;
  2717. evCommand :
  2718. begin
  2719. DontClear:=false;
  2720. case Event.Command of
  2721. cmEdit :
  2722. EditCurrent;
  2723. cmDelete :
  2724. DeleteCurrent;
  2725. cmNew :
  2726. EditNew;
  2727. else
  2728. DontClear:=true;
  2729. end;
  2730. if not DontClear then
  2731. ClearEvent(Event);
  2732. end;
  2733. end;
  2734. inherited HandleEvent(Event);
  2735. end;
  2736. constructor TWatchesListBox.Load(var S: TStream);
  2737. begin
  2738. inherited Load(S);
  2739. If assigned(List) then
  2740. dispose(list,done);
  2741. List:=WatchesCollection;
  2742. { we must set Range PM }
  2743. SetRange(List^.count+1);
  2744. end;
  2745. procedure TWatchesListBox.Store(var S: TStream);
  2746. var OL: PCollection;
  2747. OldRange : Sw_integer;
  2748. begin
  2749. OL:=List;
  2750. OldRange:=Range;
  2751. Range:=0;
  2752. New(List, Init(1,1));
  2753. inherited Store(S);
  2754. Dispose(List, Done);
  2755. List:=OL;
  2756. { ^^^ nasty trick - has anyone a better idea how to avoid storing the
  2757. collection? Pasting here a modified version of TListBox.Store+
  2758. TAdvancedListBox.Store isn't a better solution, since by eventually
  2759. changing the obj-hierarchy you'll always have to modify this, too - BG }
  2760. SetRange(OldRange);
  2761. end;
  2762. destructor TWatchesListBox.Done;
  2763. begin
  2764. List:=nil;
  2765. inherited Done;
  2766. end;
  2767. {****************************************************************************
  2768. TWatchesWindow
  2769. ****************************************************************************}
  2770. Constructor TWatchesWindow.Init;
  2771. var
  2772. HSB,VSB: PScrollBar;
  2773. R,R2 : trect;
  2774. begin
  2775. Desktop^.GetExtent(R);
  2776. R.A.Y:=R.B.Y-7;
  2777. inherited Init(R, dialog_watches,SearchFreeWindowNo);
  2778. Palette:=wpCyanWindow;
  2779. GetExtent(R);
  2780. HelpCtx:=hcWatchesWindow;
  2781. R.Grow(-1,-1);
  2782. R2.Copy(R);
  2783. Inc(R2.B.Y);
  2784. R2.A.Y:=R2.B.Y-1;
  2785. New(HSB, Init(R2));
  2786. HSB^.GrowMode:=gfGrowLoY+gfGrowHiY+gfGrowHiX;
  2787. HSB^.SetStep(R.B.X-R.A.X,1);
  2788. Insert(HSB);
  2789. R2.Copy(R);
  2790. Inc(R2.B.X);
  2791. R2.A.X:=R2.B.X-1;
  2792. New(VSB, Init(R2));
  2793. VSB^.GrowMode:=gfGrowLoX+gfGrowHiX+gfGrowHiY;
  2794. Insert(VSB);
  2795. New(WLB,Init(R,HSB,VSB));
  2796. WLB^.GrowMode:=gfGrowHiX+gfGrowHiY;
  2797. WLB^.Transparent:=true;
  2798. Insert(WLB);
  2799. If assigned(WatchesWindow) then
  2800. dispose(WatchesWindow,done);
  2801. WatchesWindow:=@Self;
  2802. Update;
  2803. end;
  2804. procedure TWatchesWindow.Update;
  2805. begin
  2806. WatchesCollection^.Update;
  2807. Draw;
  2808. end;
  2809. constructor TWatchesWindow.Load(var S: TStream);
  2810. begin
  2811. inherited Load(S);
  2812. GetSubViewPtr(S,WLB);
  2813. If assigned(WatchesWindow) then
  2814. dispose(WatchesWindow,done);
  2815. WatchesWindow:=@Self;
  2816. end;
  2817. procedure TWatchesWindow.Store(var S: TStream);
  2818. begin
  2819. inherited Store(S);
  2820. PutSubViewPtr(S,WLB);
  2821. end;
  2822. Destructor TWatchesWindow.Done;
  2823. begin
  2824. WatchesWindow:=nil;
  2825. Dispose(WLB,done);
  2826. inherited done;
  2827. end;
  2828. {****************************************************************************
  2829. TWatchItemDialog
  2830. ****************************************************************************}
  2831. constructor TWatchItemDialog.Init(AWatch: PWatch);
  2832. var R,R2: TRect;
  2833. begin
  2834. R.Assign(0,0,50,10);
  2835. inherited Init(R,'Edit Watch');
  2836. Watch:=AWatch;
  2837. GetExtent(R); R.Grow(-3,-2);
  2838. Inc(R.A.Y); R.B.Y:=R.A.Y+1; R.B.X:=R.A.X+36;
  2839. New(NameIL, Init(R, 255)); Insert(NameIL);
  2840. R2.Copy(R); R2.A.X:=R2.B.X; R2.B.X:=R2.A.X+3;
  2841. Insert(New(PHistory, Init(R2, NameIL, hidWatchDialog)));
  2842. R2.Copy(R); R2.Move(-1,-1);
  2843. Insert(New(PLabel, Init(R2, label_watch_expressiontowatch, NameIL)));
  2844. GetExtent(R);
  2845. R.Grow(-3,-1);
  2846. R.A.Y:=R.A.Y+3;
  2847. TextST:=New(PAdvancedStaticText, Init(R, label_watch_values));
  2848. Insert(TextST);
  2849. InsertButtons(@Self);
  2850. NameIL^.Select;
  2851. end;
  2852. function TWatchItemDialog.Execute: Word;
  2853. var R: word;
  2854. S1,S2: string;
  2855. begin
  2856. S1:=GetStr(Watch^.expr);
  2857. NameIL^.SetData(S1);
  2858. S1:=GetPChar(Watch^.Current_value);
  2859. S2:=GetPChar(Watch^.Last_value);
  2860. ClearFormatParams;
  2861. AddFormatParamStr(S1);
  2862. AddFormatParamStr(S2);
  2863. if assigned(Watch^.Last_value) and
  2864. assigned(Watch^.Current_value) and
  2865. (strcomp(Watch^.Last_value,Watch^.Current_value)=0) then
  2866. S1:=FormatStrF(msg_watch_currentvalue,FormatParams)
  2867. else
  2868. S1:=FormatStrF(msg_watch_currentandpreviousvalue,FormatParams);
  2869. TextST^.SetText(S1);
  2870. if assigned(FirstEditorWindow) then
  2871. FindReplaceEditor:=FirstEditorWindow^.Editor;
  2872. R:=inherited Execute;
  2873. FindReplaceEditor:=nil;
  2874. if R=cmOK then
  2875. begin
  2876. NameIL^.GetData(S1);
  2877. Watch^.Rename(S1);
  2878. If assigned(Debugger) then
  2879. Debugger^.ReadWatches;
  2880. end;
  2881. Execute:=R;
  2882. end;
  2883. {****************************************************************************
  2884. TStackWindow
  2885. ****************************************************************************}
  2886. constructor TFramesListBox.Init(var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar);
  2887. begin
  2888. Inherited Init(Bounds,AHScrollBar,AVScrollBar);
  2889. end;
  2890. procedure TFramesListBox.Update;
  2891. var i : longint;
  2892. W : PSourceWindow;
  2893. begin
  2894. { call backtrace command }
  2895. If not assigned(Debugger) then
  2896. exit;
  2897. {$ifndef NODEBUG}
  2898. DeskTop^.Lock;
  2899. Clear;
  2900. { forget all old frames }
  2901. Debugger^.clear_frames;
  2902. if Debugger^.WindowWidth<>-1 then
  2903. Debugger^.Command('set width 0xffffffff');
  2904. Debugger^.Command('backtrace');
  2905. { generate list }
  2906. { all is in tframeentry }
  2907. for i:=0 to Debugger^.frame_count-1 do
  2908. begin
  2909. with Debugger^.frames[i]^ do
  2910. begin
  2911. if assigned(file_name) then
  2912. AddItem(new(PMessageItem,init(0,GetPChar(function_name)+GetPChar(args),
  2913. AddModuleName(GetPChar(file_name)),line_number,1)))
  2914. else
  2915. AddItem(new(PMessageItem,init(0,HexStr(address,8)+' '+GetPChar(function_name)+GetPChar(args),
  2916. AddModuleName(''),line_number,1)));
  2917. W:=SearchOnDesktop(GetPChar(file_name),false);
  2918. { First reset all Debugger rows }
  2919. If assigned(W) then
  2920. begin
  2921. W^.Editor^.SetLineFlagExclusive(lfDebuggerRow,-1);
  2922. W^.Editor^.DebuggerRow:=-1;
  2923. end;
  2924. end;
  2925. end;
  2926. { Now set all Debugger rows }
  2927. for i:=0 to Debugger^.frame_count-1 do
  2928. begin
  2929. with Debugger^.frames[i]^ do
  2930. begin
  2931. W:=SearchOnDesktop(GetPChar(file_name),false);
  2932. If assigned(W) then
  2933. begin
  2934. If W^.Editor^.DebuggerRow=-1 then
  2935. begin
  2936. W^.Editor^.SetLineFlagState(line_number-1,lfDebuggerRow,true);
  2937. W^.Editor^.DebuggerRow:=line_number-1;
  2938. end;
  2939. end;
  2940. end;
  2941. end;
  2942. if Assigned(list) and (List^.Count > 0) then
  2943. FocusItem(0);
  2944. if Debugger^.WindowWidth<>-1 then
  2945. Debugger^.Command('set width '+IntToStr(Debugger^.WindowWidth));
  2946. DeskTop^.Unlock;
  2947. {$endif}
  2948. end;
  2949. function TFramesListBox.GetLocalMenu: PMenu;
  2950. begin
  2951. GetLocalMenu:=Inherited GetLocalMenu;
  2952. end;
  2953. procedure TFramesListBox.GotoSource;
  2954. begin
  2955. { select frame for watches }
  2956. If not assigned(Debugger) then
  2957. exit;
  2958. {$ifndef NODEBUG}
  2959. Debugger^.Command('f '+IntToStr(Focused));
  2960. { for local vars }
  2961. Debugger^.RereadWatches;
  2962. {$endif}
  2963. { goto source }
  2964. inherited GotoSource;
  2965. end;
  2966. procedure TFramesListBox.GotoAssembly;
  2967. begin
  2968. { select frame for watches }
  2969. If not assigned(Debugger) then
  2970. exit;
  2971. {$ifndef NODEBUG}
  2972. Debugger^.Command('f '+IntToStr(Focused));
  2973. { for local vars }
  2974. Debugger^.RereadWatches;
  2975. {$endif}
  2976. { goto source/assembly mixture }
  2977. InitDisassemblyWindow;
  2978. DisassemblyWindow^.LoadFunction('');
  2979. DisassemblyWindow^.SetCurAddress(Debugger^.frames[Focused]^.address);
  2980. DisassemblyWindow^.SelectInDebugSession;
  2981. end;
  2982. procedure TFramesListBox.HandleEvent(var Event: TEvent);
  2983. begin
  2984. if ((Event.What=EvKeyDown) and (Event.CharCode='i')) or
  2985. ((Event.What=EvCommand) and (Event.Command=cmDisassemble)) then
  2986. GotoAssembly;
  2987. inherited HandleEvent(Event);
  2988. end;
  2989. destructor TFramesListBox.Done;
  2990. begin
  2991. Inherited Done;
  2992. end;
  2993. Constructor TStackWindow.Init;
  2994. var
  2995. HSB,VSB: PScrollBar;
  2996. R,R2 : trect;
  2997. begin
  2998. Desktop^.GetExtent(R);
  2999. R.A.Y:=R.B.Y-5;
  3000. inherited Init(R, dialog_callstack, wnNoNumber);
  3001. Palette:=wpCyanWindow;
  3002. GetExtent(R);
  3003. HelpCtx:=hcStackWindow;
  3004. R.Grow(-1,-1);
  3005. R2.Copy(R);
  3006. Inc(R2.B.Y);
  3007. R2.A.Y:=R2.B.Y-1;
  3008. New(HSB, Init(R2));
  3009. HSB^.GrowMode:=gfGrowLoY+gfGrowHiY+gfGrowHiX;
  3010. Insert(HSB);
  3011. R2.Copy(R);
  3012. Inc(R2.B.X);
  3013. R2.A.X:=R2.B.X-1;
  3014. New(VSB, Init(R2));
  3015. VSB^.GrowMode:=gfGrowLoX+gfGrowHiX+gfGrowHiY;
  3016. Insert(VSB);
  3017. New(FLB,Init(R,HSB,VSB));
  3018. FLB^.GrowMode:=gfGrowHiX+gfGrowHiY;
  3019. Insert(FLB);
  3020. If assigned(StackWindow) then
  3021. dispose(StackWindow,done);
  3022. StackWindow:=@Self;
  3023. Update;
  3024. end;
  3025. procedure TStackWindow.Update;
  3026. begin
  3027. FLB^.Update;
  3028. DrawView;
  3029. end;
  3030. constructor TStackWindow.Load(var S: TStream);
  3031. begin
  3032. inherited Load(S);
  3033. GetSubViewPtr(S,FLB);
  3034. If assigned(StackWindow) then
  3035. dispose(StackWindow,done);
  3036. StackWindow:=@Self;
  3037. end;
  3038. procedure TStackWindow.Store(var S: TStream);
  3039. begin
  3040. inherited Store(S);
  3041. PutSubViewPtr(S,FLB);
  3042. end;
  3043. Destructor TStackWindow.Done;
  3044. begin
  3045. StackWindow:=nil;
  3046. Dispose(FLB,done);
  3047. inherited done;
  3048. end;
  3049. {****************************************************************************
  3050. Init/Final
  3051. ****************************************************************************}
  3052. function GetGDBTargetShortName : string;
  3053. begin
  3054. {$ifdef SUPPORT_REMOTE}
  3055. GetGDBTargetShortName:='linux';
  3056. {$else not SUPPORT_REMOTE}
  3057. {$ifdef COMPILER_1_0}
  3058. GetGDBTargetShortName:=source_os.shortname
  3059. {$else}
  3060. GetGDBTargetShortName:=source_info.shortname
  3061. {$endif}
  3062. {$endif not SUPPORT_REMOTE}
  3063. end;
  3064. procedure InitDebugger;
  3065. {$ifdef DEBUG}
  3066. var s : string;
  3067. i,p : longint;
  3068. {$endif DEBUG}
  3069. var
  3070. NeedRecompileExe : boolean;
  3071. cm : longint;
  3072. begin
  3073. {$ifdef DEBUG}
  3074. if not use_gdb_file then
  3075. begin
  3076. Assign(gdb_file,GDBOutFileName);
  3077. {$I-}
  3078. Rewrite(gdb_file);
  3079. if InOutRes<>0 then
  3080. begin
  3081. s:=GDBOutFileName;
  3082. p:=pos('.',s);
  3083. if p>1 then
  3084. for i:=0 to 9 do
  3085. begin
  3086. s:=copy(s,1,p-2)+chr(i+ord('0'))+copy(s,p,length(s));
  3087. InOutRes:=0;
  3088. Assign(gdb_file,s);
  3089. rewrite(gdb_file);
  3090. if InOutRes=0 then
  3091. break;
  3092. end;
  3093. end;
  3094. if IOResult=0 then
  3095. Use_gdb_file:=true;
  3096. end;
  3097. {$I+}
  3098. {$endif}
  3099. NeedRecompileExe:=false;
  3100. if TargetSwitches^.GetCurrSelParam<>GetGDBTargetShortName then
  3101. begin
  3102. ClearFormatParams;
  3103. AddFormatParamStr(TargetSwitches^.GetCurrSelParam);
  3104. AddFormatParamStr(GetGDBTargetShortName);
  3105. cm:=ConfirmBox(msg_cantdebugchangetargetto,@FormatParams,true);
  3106. if cm=cmCancel then
  3107. Exit;
  3108. if cm=cmYes then
  3109. begin
  3110. { force recompilation }
  3111. PrevMainFile:='';
  3112. NeedRecompileExe:=true;
  3113. TargetSwitches^.SetCurrSelParam(GetGDBTargetShortName);
  3114. If DebugInfoSwitches^.GetCurrSelParam='-' then
  3115. DebugInfoSwitches^.SetCurrSelParam('l');
  3116. IDEApp.UpdateTarget;
  3117. end;
  3118. end;
  3119. if not NeedRecompileExe then
  3120. NeedRecompileExe:=(not ExistsFile(ExeFile)) or (CompilationPhase<>cpDone) or
  3121. (PrevMainFile<>MainFile) or NeedRecompile(cRun,false);
  3122. if Not NeedRecompileExe and Not MainHasDebugInfo then
  3123. begin
  3124. ClearFormatParams;
  3125. cm:=ConfirmBox(msg_compiledwithoutdebuginforecompile,nil,true);
  3126. if cm=cmCancel then
  3127. Exit;
  3128. if cm=cmYes then
  3129. begin
  3130. { force recompilation }
  3131. PrevMainFile:='';
  3132. NeedRecompileExe:=true;
  3133. DebugInfoSwitches^.SetCurrSelParam('l');
  3134. end;
  3135. end;
  3136. if NeedRecompileExe then
  3137. DoCompile(cRun);
  3138. if CompilationPhase<>cpDone then
  3139. Exit;
  3140. if (EXEFile='') then
  3141. begin
  3142. ErrorBox(msg_nothingtodebug,nil);
  3143. Exit;
  3144. end;
  3145. { init debugcontroller }
  3146. if not assigned(Debugger) then
  3147. begin
  3148. PushStatus(msg_startingdebugger);
  3149. new(Debugger,Init);
  3150. PopStatus;
  3151. end;
  3152. Debugger^.SetExe(ExeFile);
  3153. {$ifdef GDBWINDOW}
  3154. InitGDBWindow;
  3155. {$endif def GDBWINDOW}
  3156. end;
  3157. procedure DoneDebugger;
  3158. begin
  3159. {$ifdef DEBUG}
  3160. If IDEApp.IsRunning then
  3161. PushStatus('Closing debugger');
  3162. {$endif}
  3163. if assigned(Debugger) then
  3164. dispose(Debugger,Done);
  3165. Debugger:=nil;
  3166. {$ifdef DOS}
  3167. If assigned(UserScreen) then
  3168. PDosScreen(UserScreen)^.FreeGraphBuffer;
  3169. {$endif DOS}
  3170. {$ifdef DEBUG}
  3171. If Use_gdb_file then
  3172. begin
  3173. Use_gdb_file:=false;
  3174. Close(GDB_file);
  3175. end;
  3176. If IDEApp.IsRunning then
  3177. PopStatus;
  3178. {$endif DEBUG}
  3179. end;
  3180. procedure InitGDBWindow;
  3181. var
  3182. R : TRect;
  3183. begin
  3184. if GDBWindow=nil then
  3185. begin
  3186. DeskTop^.GetExtent(R);
  3187. new(GDBWindow,init(R));
  3188. DeskTop^.Insert(GDBWindow);
  3189. end;
  3190. end;
  3191. procedure DoneGDBWindow;
  3192. begin
  3193. If IDEApp.IsRunning and
  3194. assigned(GDBWindow) then
  3195. begin
  3196. DeskTop^.Delete(GDBWindow);
  3197. end;
  3198. GDBWindow:=nil;
  3199. end;
  3200. procedure InitDisassemblyWindow;
  3201. var
  3202. R : TRect;
  3203. begin
  3204. if DisassemblyWindow=nil then
  3205. begin
  3206. DeskTop^.GetExtent(R);
  3207. new(DisassemblyWindow,init(R));
  3208. DeskTop^.Insert(DisassemblyWindow);
  3209. end;
  3210. end;
  3211. procedure DoneDisassemblyWindow;
  3212. begin
  3213. if assigned(DisassemblyWindow) then
  3214. begin
  3215. DeskTop^.Delete(DisassemblyWindow);
  3216. Dispose(DisassemblyWindow,Done);
  3217. DisassemblyWindow:=nil;
  3218. end;
  3219. end;
  3220. procedure InitStackWindow;
  3221. begin
  3222. if StackWindow=nil then
  3223. begin
  3224. new(StackWindow,init);
  3225. DeskTop^.Insert(StackWindow);
  3226. end;
  3227. end;
  3228. procedure DoneStackWindow;
  3229. begin
  3230. if assigned(StackWindow) then
  3231. begin
  3232. DeskTop^.Delete(StackWindow);
  3233. StackWindow:=nil;
  3234. end;
  3235. end;
  3236. procedure InitBreakpoints;
  3237. begin
  3238. New(BreakpointsCollection,init(10,10));
  3239. end;
  3240. procedure DoneBreakpoints;
  3241. begin
  3242. Dispose(BreakpointsCollection,Done);
  3243. BreakpointsCollection:=nil;
  3244. end;
  3245. procedure InitWatches;
  3246. begin
  3247. New(WatchesCollection,init);
  3248. end;
  3249. procedure DoneWatches;
  3250. begin
  3251. Dispose(WatchesCollection,Done);
  3252. WatchesCollection:=nil;
  3253. end;
  3254. procedure RegisterFPDebugViews;
  3255. begin
  3256. RegisterType(RWatchesWindow);
  3257. RegisterType(RBreakpointsWindow);
  3258. RegisterType(RWatchesListBox);
  3259. RegisterType(RBreakpointsListBox);
  3260. RegisterType(RStackWindow);
  3261. RegisterType(RFramesListBox);
  3262. RegisterType(RBreakpoint);
  3263. RegisterType(RWatch);
  3264. RegisterType(RBreakpointCollection);
  3265. RegisterType(RWatchesCollection);
  3266. end;
  3267. end.
  3268. {
  3269. $Log$
  3270. Revision 1.41 2002-12-16 09:05:28 pierre
  3271. * sanity ceck in ToggleFileLine method
  3272. Revision 1.40 2002/02/09 02:04:46 pierre
  3273. * fix problem with disable all invalid breakpoints
  3274. Revision 1.39 2002/12/12 00:05:57 pierre
  3275. * add code for breakpoint moves + registers in fprags.pas unit
  3276. Revision 1.38 2002/11/30 01:56:52 pierre
  3277. + powerpc cpu support started
  3278. Revision 1.37 2002/11/28 13:00:25 pierre
  3279. + remote support
  3280. Revision 1.36 2002/11/21 17:52:28 pierre
  3281. * some crossgdb infos added
  3282. Revision 1.35 2002/11/21 15:48:39 pierre
  3283. * fix several problems related to remote cross debugging
  3284. Revision 1.34 2002/11/21 00:37:56 pierre
  3285. + some cross gdb enhancements
  3286. Revision 1.33 2002/09/21 22:23:49 pierre
  3287. * restore text mode on reset for Dos apps
  3288. Revision 1.32 2002/09/17 21:58:45 pierre
  3289. * correct last fpu patch so 'info all' is called only once
  3290. Revision 1.31 2002/09/17 21:48:41 pierre
  3291. * allow fpu window to be resized
  3292. Revision 1.30 2002/09/17 21:20:07 pierre
  3293. * fix infinite recursion if GDB window and register window open
  3294. Revision 1.29 2002/09/13 22:30:50 pierre
  3295. * only fpc uses video unit
  3296. Revision 1.28 2002/09/13 08:13:07 pierre
  3297. * avoid RTE 201 in hexstr calls
  3298. Revision 1.27 2002/09/07 21:04:41 carl
  3299. * fix range check errors for version 1.1 compilation
  3300. Revision 1.26 2002/09/07 15:40:42 peter
  3301. * old logs removed and tabs fixed
  3302. Revision 1.25 2002/09/03 13:59:47 pierre
  3303. + added history for watches and breakpoints
  3304. Revision 1.24 2002/09/02 10:18:09 pierre
  3305. * fix problems with breakpoint lists
  3306. Revision 1.23 2002/08/13 08:59:12 pierre
  3307. + Run menu changes depending on wether the debuggee is running or not
  3308. Revision 1.22 2002/08/13 07:15:02 pierre
  3309. + Disable all invalid breakpoints feature added
  3310. Revision 1.21 2002/06/10 19:26:48 pierre
  3311. * check if DebuggeTTY is a valid terminal
  3312. Revision 1.20 2002/06/06 14:11:25 pierre
  3313. * handle win32 Ctrl-C change for graphic version
  3314. Revision 1.19 2002/06/06 08:16:18 pierre
  3315. * avoid crashes if quitting while debuggee is running
  3316. Revision 1.18 2002/04/25 13:33:31 pierre
  3317. * fix the problem with dirs containing asterisks
  3318. Revision 1.17 2002/04/17 11:11:54 pierre
  3319. * avoid problems for ClassVariable in Watches window
  3320. Revision 1.16 2002/04/11 06:41:13 pierre
  3321. * fix problem of TWatchesListBox with fvision
  3322. Revision 1.15 2002/04/03 06:18:30 pierre
  3323. * fix some win32 GDB filename problems
  3324. Revision 1.14 2002/04/02 15:09:38 pierre
  3325. * fixed wrong exit without unlock
  3326. Revision 1.13 2002/04/02 13:23:54 pierre
  3327. * Use StrToCard and HexToCard functions to avoid signed/unsigned overflows
  3328. Revision 1.12 2002/04/02 12:20:58 pierre
  3329. * fix problem with breakpoints in subdirs
  3330. Revision 1.11 2002/04/02 11:10:29 pierre
  3331. * fix FPC_BREAK_ERROR problem and avoid blinking J
  3332. Revision 1.10 2002/03/27 11:24:09 pierre
  3333. * fix several problems related to long file nmze support for win32 exes
  3334. Revision 1.9 2002/02/06 14:45:00 pierre
  3335. + handle signals
  3336. }