fpdebug.pas 95 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655
  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 (OSFileName(FExpand(P^.FileName^))=FileName) and (P^.Line=LineNr);
  1614. end;
  1615. begin
  1616. FileName:=OSFileName(FileName);
  1617. PB:=FirstThat(@IsThere);
  1618. ToggleFileLine:=false;
  1619. If Assigned(PB) then
  1620. if PB^.state=bs_disabled then
  1621. begin
  1622. PB^.state:=bs_enabled;
  1623. ToggleFileLine:=true;
  1624. end
  1625. else if PB^.state=bs_enabled then
  1626. PB^.state:=bs_disabled;
  1627. If not assigned(PB) then
  1628. begin
  1629. PB:= New(PBreakpoint,Init_file_line(FileName,LineNr));
  1630. if assigned(PB) then
  1631. Begin
  1632. Insert(PB);
  1633. ToggleFileLine:=true;
  1634. End;
  1635. end;
  1636. if assigned(PB) then
  1637. PB^.UpdateSource;
  1638. Update;
  1639. end;
  1640. {****************************************************************************
  1641. TBreakpointItem
  1642. ****************************************************************************}
  1643. constructor TBreakpointItem.Init(ABreakpoint : PBreakpoint);
  1644. begin
  1645. inherited Init;
  1646. Breakpoint:=ABreakpoint;
  1647. end;
  1648. function TBreakpointItem.GetText(MaxLen: Sw_integer): string;
  1649. var S: string;
  1650. begin
  1651. with Breakpoint^ do
  1652. begin
  1653. S:=BreakpointTypeStr[typ];
  1654. While Length(S)<10 do
  1655. S:=S+' ';
  1656. S:=S+'|';
  1657. S:=S+BreakpointStateStr[state]+' ';
  1658. While Length(S)<20 do
  1659. S:=S+' ';
  1660. S:=S+'|';
  1661. if (typ=bt_file_line) then
  1662. S:=S+NameAndExtOf(GetStr(FileName))+':'+IntToStr(Line)
  1663. else
  1664. S:=S+GetStr(name);
  1665. While Length(S)<40 do
  1666. S:=S+' ';
  1667. S:=S+'|';
  1668. if IgnoreCount>0 then
  1669. S:=S+IntToStr(IgnoreCount);
  1670. While Length(S)<49 do
  1671. S:=S+' ';
  1672. S:=S+'|';
  1673. if assigned(Conditions) then
  1674. S:=S+' '+GetStr(Conditions);
  1675. if length(S)>MaxLen then S:=copy(S,1,MaxLen-2)+'..';
  1676. GetText:=S;
  1677. end;
  1678. end;
  1679. procedure TBreakpointItem.Selected;
  1680. begin
  1681. end;
  1682. function TBreakpointItem.GetModuleName: string;
  1683. begin
  1684. if breakpoint^.typ=bt_file_line then
  1685. GetModuleName:=GetStr(breakpoint^.FileName)
  1686. else
  1687. GetModuleName:='';
  1688. end;
  1689. {****************************************************************************
  1690. TBreakpointsListBox
  1691. ****************************************************************************}
  1692. constructor TBreakpointsListBox.Init(var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar);
  1693. begin
  1694. inherited Init(Bounds,1,AHScrollBar, AVScrollBar);
  1695. GrowMode:=gfGrowLoX+gfGrowHiX+gfGrowHiY;
  1696. NoSelection:=true;
  1697. end;
  1698. function TBreakpointsListBox.GetLocalMenu: PMenu;
  1699. var M: PMenu;
  1700. begin
  1701. if (Owner<>nil) and (Owner^.GetState(sfModal)) then M:=nil else
  1702. M:=NewMenu(
  1703. NewItem(menu_bplocal_gotosource,'',kbNoKey,cmMsgGotoSource,hcMsgGotoSource,
  1704. NewItem(menu_bplocal_editbreakpoint,'',kbNoKey,cmEditBreakpoint,hcEditBreakpoint,
  1705. NewItem(menu_bplocal_newbreakpoint,'',kbNoKey,cmNewBreakpoint,hcNewBreakpoint,
  1706. NewItem(menu_bplocal_deletebreakpoint,'',kbNoKey,cmDeleteBreakpoint,hcDeleteBreakpoint,
  1707. NewItem(menu_bplocal_togglestate,'',kbNoKey,cmToggleBreakpoint,hcToggleBreakpoint,
  1708. nil))))));
  1709. GetLocalMenu:=M;
  1710. end;
  1711. procedure TBreakpointsListBox.HandleEvent(var Event: TEvent);
  1712. var DontClear: boolean;
  1713. begin
  1714. case Event.What of
  1715. evKeyDown :
  1716. begin
  1717. DontClear:=false;
  1718. case Event.KeyCode of
  1719. kbEnter :
  1720. Message(@Self,evCommand,cmMsgGotoSource,nil);
  1721. kbIns :
  1722. Message(@Self,evCommand,cmNewBreakpoint,nil);
  1723. kbDel :
  1724. Message(@Self,evCommand,cmDeleteBreakpoint,nil);
  1725. else
  1726. DontClear:=true;
  1727. end;
  1728. if not DontClear then
  1729. ClearEvent(Event);
  1730. end;
  1731. evBroadcast :
  1732. case Event.Command of
  1733. cmListItemSelected :
  1734. if Event.InfoPtr=@Self then
  1735. Message(@Self,evCommand,cmEditBreakpoint,nil);
  1736. end;
  1737. evCommand :
  1738. begin
  1739. DontClear:=false;
  1740. case Event.Command of
  1741. cmMsgTrackSource :
  1742. if Range>0 then
  1743. TrackSource;
  1744. cmEditBreakpoint :
  1745. EditCurrent;
  1746. cmToggleBreakpoint :
  1747. ToggleCurrent;
  1748. cmDeleteBreakpoint :
  1749. DeleteCurrent;
  1750. cmNewBreakpoint :
  1751. EditNew;
  1752. cmMsgClear :
  1753. Clear;
  1754. else
  1755. DontClear:=true;
  1756. end;
  1757. if not DontClear then
  1758. ClearEvent(Event);
  1759. end;
  1760. end;
  1761. inherited HandleEvent(Event);
  1762. end;
  1763. procedure TBreakpointsListBox.AddBreakpoint(P: PBreakpointItem);
  1764. var W : integer;
  1765. begin
  1766. if List=nil then New(List, Init(20,20));
  1767. W:=length(P^.GetText(255));
  1768. if W>MaxWidth then
  1769. begin
  1770. MaxWidth:=W;
  1771. if HScrollBar<>nil then
  1772. HScrollBar^.SetRange(0,MaxWidth);
  1773. end;
  1774. List^.Insert(P);
  1775. SetRange(List^.Count);
  1776. if Focused=List^.Count-1-1 then
  1777. FocusItem(List^.Count-1);
  1778. P^.Breakpoint^.UpdateSource;
  1779. DrawView;
  1780. end;
  1781. (* function TBreakpointsListBox.AddModuleName(const Name: string): PString;
  1782. var P: PString;
  1783. begin
  1784. if ModuleNames<>nil then
  1785. P:=ModuleNames^.Add(Name)
  1786. else
  1787. P:=nil;
  1788. AddModuleName:=P;
  1789. end; *)
  1790. function TBreakpointsListBox.GetText(Item,MaxLen: Sw_Integer): String;
  1791. var P: PBreakpointItem;
  1792. S: string;
  1793. begin
  1794. P:=List^.At(Item);
  1795. S:=P^.GetText(MaxLen);
  1796. GetText:=copy(S,1,MaxLen);
  1797. end;
  1798. procedure TBreakpointsListBox.Clear;
  1799. begin
  1800. if assigned(List) then
  1801. Dispose(List, Done);
  1802. List:=nil;
  1803. MaxWidth:=0;
  1804. (* if assigned(ModuleNames) then
  1805. ModuleNames^.FreeAll; *)
  1806. SetRange(0); DrawView;
  1807. Message(Application,evBroadcast,cmClearLineHighlights,@Self);
  1808. end;
  1809. procedure TBreakpointsListBox.TrackSource;
  1810. var W: PSourceWindow;
  1811. P: PBreakpointItem;
  1812. R: TRect;
  1813. (* Row,Col: sw_integer; *)
  1814. begin
  1815. (*Message(Application,evBroadcast,cmClearLineHighlights,@Self);
  1816. if Range=0 then Exit;*)
  1817. P:=List^.At(Focused);
  1818. if P^.GetModuleName='' then Exit;
  1819. Desktop^.Lock;
  1820. GetNextEditorBounds(R);
  1821. R.B.Y:=Owner^.Origin.Y;
  1822. W:=EditorWindowFile(P^.GetModuleName);
  1823. if assigned(W) then
  1824. begin
  1825. W^.GetExtent(R);
  1826. R.B.Y:=Owner^.Origin.Y;
  1827. W^.ChangeBounds(R);
  1828. W^.Editor^.SetCurPtr(1,P^.Breakpoint^.Line);
  1829. end
  1830. else
  1831. W:=TryToOpenFile(@R,P^.GetModuleName,1,P^.Breakpoint^.Line,true);
  1832. if W<>nil then
  1833. begin
  1834. W^.Select;
  1835. W^.Editor^.TrackCursor(true);
  1836. W^.Editor^.SetLineFlagExclusive(lfHighlightRow,P^.Breakpoint^.Line);
  1837. end;
  1838. if Assigned(Owner) then
  1839. Owner^.Select;
  1840. Desktop^.UnLock;
  1841. end;
  1842. procedure TBreakpointsListBox.ToggleCurrent;
  1843. var
  1844. P: PBreakpointItem;
  1845. begin
  1846. if Range=0 then Exit;
  1847. P:=List^.At(Focused);
  1848. if P=nil then Exit;
  1849. if P^.Breakpoint^.state=bs_enabled then
  1850. P^.Breakpoint^.state:=bs_disabled
  1851. else if P^.Breakpoint^.state=bs_disabled then
  1852. P^.Breakpoint^.state:=bs_enabled;
  1853. P^.Breakpoint^.UpdateSource;
  1854. BreakpointsCollection^.Update;
  1855. end;
  1856. procedure TBreakpointsListBox.EditCurrent;
  1857. var
  1858. P: PBreakpointItem;
  1859. begin
  1860. if Range=0 then Exit;
  1861. P:=List^.At(Focused);
  1862. if P=nil then Exit;
  1863. Application^.ExecuteDialog(New(PBreakpointItemDialog,Init(P^.Breakpoint)),nil);
  1864. P^.Breakpoint^.UpdateSource;
  1865. BreakpointsCollection^.Update;
  1866. end;
  1867. procedure TBreakpointsListBox.DeleteCurrent;
  1868. var
  1869. P: PBreakpointItem;
  1870. begin
  1871. if Range=0 then Exit;
  1872. P:=List^.At(Focused);
  1873. if P=nil then Exit;
  1874. { delete it form source window }
  1875. P^.Breakpoint^.state:=bs_disabled;
  1876. P^.Breakpoint^.UpdateSource;
  1877. BreakpointsCollection^.free(P^.Breakpoint);
  1878. List^.free(P);
  1879. BreakpointsCollection^.Update;
  1880. end;
  1881. procedure TBreakpointsListBox.EditNew;
  1882. var
  1883. P: PBreakpoint;
  1884. begin
  1885. P:=New(PBreakpoint,Init_Empty);
  1886. if Application^.ExecuteDialog(New(PBreakpointItemDialog,Init(P)),nil)<>cmCancel then
  1887. begin
  1888. P^.UpdateSource;
  1889. BreakpointsCollection^.Insert(P);
  1890. BreakpointsCollection^.Update;
  1891. end
  1892. else
  1893. dispose(P,Done);
  1894. end;
  1895. procedure TBreakpointsListBox.Draw;
  1896. var
  1897. I, J, Item: Sw_Integer;
  1898. NormalColor, SelectedColor, FocusedColor, Color: Word;
  1899. ColWidth, CurCol, Indent: Integer;
  1900. B: TDrawBuffer;
  1901. Text: String;
  1902. SCOff: Byte;
  1903. TC: byte;
  1904. procedure MT(var C: word); begin if TC<>0 then C:=(C and $ff0f) or (TC and $f0); end;
  1905. begin
  1906. if (Owner<>nil) then TC:=ord(Owner^.GetColor(6)) else TC:=0;
  1907. if State and (sfSelected + sfActive) = (sfSelected + sfActive) then
  1908. begin
  1909. NormalColor := GetColor(1);
  1910. FocusedColor := GetColor(3);
  1911. SelectedColor := GetColor(4);
  1912. end else
  1913. begin
  1914. NormalColor := GetColor(2);
  1915. SelectedColor := GetColor(4);
  1916. end;
  1917. if Transparent then
  1918. begin MT(NormalColor); MT(SelectedColor); end;
  1919. if NoSelection then
  1920. SelectedColor:=NormalColor;
  1921. if HScrollBar <> nil then Indent := HScrollBar^.Value
  1922. else Indent := 0;
  1923. ColWidth := Size.X div NumCols + 1;
  1924. for I := 0 to Size.Y - 1 do
  1925. begin
  1926. for J := 0 to NumCols-1 do
  1927. begin
  1928. Item := J*Size.Y + I + TopItem;
  1929. CurCol := J*ColWidth;
  1930. if (State and (sfSelected + sfActive) = (sfSelected + sfActive)) and
  1931. (Focused = Item) and (Range > 0) then
  1932. begin
  1933. Color := FocusedColor;
  1934. SetCursor(CurCol+1,I);
  1935. SCOff := 0;
  1936. end
  1937. else if (Item < Range) and IsSelected(Item) then
  1938. begin
  1939. Color := SelectedColor;
  1940. SCOff := 2;
  1941. end
  1942. else
  1943. begin
  1944. Color := NormalColor;
  1945. SCOff := 4;
  1946. end;
  1947. MoveChar(B[CurCol], ' ', Color, ColWidth);
  1948. if Item < Range then
  1949. begin
  1950. Text := GetText(Item, ColWidth + Indent);
  1951. Text := Copy(Text,Indent,ColWidth);
  1952. MoveStr(B[CurCol+1], Text, Color);
  1953. if ShowMarkers then
  1954. begin
  1955. WordRec(B[CurCol]).Lo := Byte(SpecialChars[SCOff]);
  1956. WordRec(B[CurCol+ColWidth-2]).Lo := Byte(SpecialChars[SCOff+1]);
  1957. end;
  1958. end;
  1959. MoveChar(B[CurCol+ColWidth-1], #179, GetColor(5), 1);
  1960. end;
  1961. WriteLine(0, I, Size.X, 1, B);
  1962. end;
  1963. end;
  1964. constructor TBreakpointsListBox.Load(var S: TStream);
  1965. begin
  1966. inherited Load(S);
  1967. end;
  1968. procedure TBreakpointsListBox.Store(var S: TStream);
  1969. var OL: PCollection;
  1970. OldR : integer;
  1971. begin
  1972. OL:=List;
  1973. OldR:=Range;
  1974. Range:=0;
  1975. New(List, Init(1,1));
  1976. inherited Store(S);
  1977. Dispose(List, Done);
  1978. Range:=OldR;
  1979. List:=OL;
  1980. { ^^^ nasty trick - has anyone a better idea how to avoid storing the
  1981. collection? Pasting here a modified version of TListBox.Store+
  1982. TAdvancedListBox.Store isn't a better solution, since by eventually
  1983. changing the obj-hierarchy you'll always have to modify this, too - BG }
  1984. end;
  1985. destructor TBreakpointsListBox.Done;
  1986. begin
  1987. inherited Done;
  1988. if List<>nil then Dispose(List, Done);
  1989. (* if ModuleNames<>nil then Dispose(ModuleNames, Done);*)
  1990. end;
  1991. {****************************************************************************
  1992. TBreakpointsWindow
  1993. ****************************************************************************}
  1994. constructor TBreakpointsWindow.Init;
  1995. var R,R2: TRect;
  1996. HSB,VSB: PScrollBar;
  1997. ST: PStaticText;
  1998. S: String;
  1999. X,X1 : Sw_integer;
  2000. Btn: PButton;
  2001. const
  2002. NumButtons = 5;
  2003. begin
  2004. Desktop^.GetExtent(R); R.A.Y:=R.B.Y-18;
  2005. inherited Init(R, dialog_breakpointlist, wnNoNumber);
  2006. HelpCtx:=hcBreakpointListWindow;
  2007. GetExtent(R); R.Grow(-1,-1); R.B.Y:=R.A.Y+1;
  2008. S:=label_breakpointpropheader;
  2009. New(ST, Init(R,S));
  2010. ST^.GrowMode:=gfGrowHiX;
  2011. Insert(ST);
  2012. GetExtent(R); R.Grow(-1,-1); Inc(R.A.Y,1); R.B.Y:=R.A.Y+1;
  2013. New(ST, Init(R, CharStr('Ä', MaxViewWidth)));
  2014. ST^.GrowMode:=gfGrowHiX;
  2015. Insert(ST);
  2016. GetExtent(R); R.Grow(-1,-1); Inc(R.A.Y,2);Dec(R.B.Y,5);
  2017. R2.Copy(R); Inc(R2.B.Y); R2.A.Y:=R2.B.Y-1;
  2018. New(HSB, Init(R2)); HSB^.GrowMode:=gfGrowLoY+gfGrowHiY+gfGrowHiX; Insert(HSB);
  2019. HSB^.SetStep(R.B.X-R.A.X-2,1);
  2020. R2.Copy(R); Inc(R2.B.X); R2.A.X:=R2.B.X-1;
  2021. New(VSB, Init(R2)); VSB^.GrowMode:=gfGrowLoX+gfGrowHiX+gfGrowHiY; Insert(VSB);
  2022. VSB^.SetStep(R.B.Y-R.A.Y-2,1);
  2023. New(BreakLB, Init(R,HSB,VSB));
  2024. BreakLB^.GrowMode:=gfGrowHiX+gfGrowHiY;
  2025. BreakLB^.Transparent:=true;
  2026. Insert(BreakLB);
  2027. GetExtent(R);R.Grow(-1,-1);
  2028. Dec(R.B.Y);
  2029. R.A.Y:=R.B.Y-2;
  2030. X:=(R.B.X-R.A.X) div NumButtons;
  2031. X1:=R.A.X+(X div 2);
  2032. R.A.X:=X1-3;R.B.X:=X1+7;
  2033. New(Btn, Init(R, button_Close, cmClose, bfDefault));
  2034. Btn^.GrowMode:=gfGrowLoY+gfGrowHiY;
  2035. Insert(Btn);
  2036. X1:=X1+X;
  2037. R.A.X:=X1-3;R.B.X:=X1+7;
  2038. New(Btn, Init(R, button_New, cmNewBreakpoint, bfNormal));
  2039. Btn^.GrowMode:=gfGrowLoY+gfGrowHiY;
  2040. Insert(Btn);
  2041. X1:=X1+X;
  2042. R.A.X:=X1-3;R.B.X:=X1+7;
  2043. New(Btn, Init(R, button_Edit, cmEditBreakpoint, bfNormal));
  2044. Btn^.GrowMode:=gfGrowLoY+gfGrowHiY;
  2045. Insert(Btn);
  2046. X1:=X1+X;
  2047. R.A.X:=X1-3;R.B.X:=X1+7;
  2048. New(Btn, Init(R, button_ToggleButton, cmToggleBreakInList, bfNormal));
  2049. Btn^.GrowMode:=gfGrowLoY+gfGrowHiY;
  2050. Insert(Btn);
  2051. X1:=X1+X;
  2052. R.A.X:=X1-3;R.B.X:=X1+7;
  2053. New(Btn, Init(R, button_Delete, cmDeleteBreakpoint, bfNormal));
  2054. Btn^.GrowMode:=gfGrowLoY+gfGrowHiY;
  2055. Insert(Btn);
  2056. BreakLB^.Select;
  2057. Update;
  2058. BreakpointsWindow:=@self;
  2059. end;
  2060. constructor TBreakpointsWindow.Load(var S: TStream);
  2061. begin
  2062. inherited Load(S);
  2063. GetSubViewPtr(S,BreakLB);
  2064. end;
  2065. procedure TBreakpointsWindow.Store(var S: TStream);
  2066. begin
  2067. inherited Store(S);
  2068. PutSubViewPtr(S,BreakLB);
  2069. end;
  2070. procedure TBreakpointsWindow.AddBreakpoint(ABreakpoint : PBreakpoint);
  2071. begin
  2072. BreakLB^.AddBreakpoint(New(PBreakpointItem, Init(ABreakpoint)));
  2073. end;
  2074. procedure TBreakpointsWindow.ClearBreakpoints;
  2075. begin
  2076. BreakLB^.Clear;
  2077. ReDraw;
  2078. end;
  2079. procedure TBreakpointsWindow.ReloadBreakpoints;
  2080. procedure InsertInBreakLB(P : PBreakpoint);
  2081. begin
  2082. BreakLB^.AddBreakpoint(New(PBreakpointItem, Init(P)));
  2083. end;
  2084. begin
  2085. If not assigned(BreakpointsCollection) then
  2086. exit;
  2087. BreakpointsCollection^.ForEach(@InsertInBreakLB);
  2088. ReDraw;
  2089. end;
  2090. procedure TBreakpointsWindow.SizeLimits(var Min, Max: TPoint);
  2091. begin
  2092. inherited SizeLimits(Min,Max);
  2093. Min.X:=40; Min.Y:=18;
  2094. end;
  2095. procedure TBreakpointsWindow.Close;
  2096. begin
  2097. Hide;
  2098. end;
  2099. procedure TBreakpointsWindow.HandleEvent(var Event: TEvent);
  2100. var DontClear : boolean;
  2101. begin
  2102. case Event.What of
  2103. evKeyDown :
  2104. begin
  2105. if (Event.KeyCode=kbEnter) or (Event.KeyCode=kbEsc) then
  2106. begin
  2107. ClearEvent(Event);
  2108. Hide;
  2109. end;
  2110. end;
  2111. evCommand :
  2112. begin
  2113. DontClear:=False;
  2114. case Event.Command of
  2115. cmNewBreakpoint :
  2116. BreakLB^.EditNew;
  2117. cmEditBreakpoint :
  2118. BreakLB^.EditCurrent;
  2119. cmDeleteBreakpoint :
  2120. BreakLB^.DeleteCurrent;
  2121. cmToggleBreakInList :
  2122. BreakLB^.ToggleCurrent;
  2123. cmClose :
  2124. Hide;
  2125. else
  2126. DontClear:=true;
  2127. end;
  2128. if not DontClear then
  2129. ClearEvent(Event);
  2130. end;
  2131. evBroadcast :
  2132. case Event.Command of
  2133. cmUpdate :
  2134. Update;
  2135. end;
  2136. end;
  2137. inherited HandleEvent(Event);
  2138. end;
  2139. procedure TBreakpointsWindow.Update;
  2140. var
  2141. StoreFocus : longint;
  2142. begin
  2143. StoreFocus:=BreakLB^.Focused;
  2144. ClearBreakpoints;
  2145. ReloadBreakpoints;
  2146. If StoreFocus<BreakLB^.Range then
  2147. BreakLB^.FocusItem(StoreFocus);
  2148. end;
  2149. destructor TBreakpointsWindow.Done;
  2150. begin
  2151. inherited Done;
  2152. BreakpointsWindow:=nil;
  2153. end;
  2154. {****************************************************************************
  2155. TBreakpointItemDialog
  2156. ****************************************************************************}
  2157. constructor TBreakpointItemDialog.Init(ABreakpoint: PBreakpoint);
  2158. var R,R2,R3: TRect;
  2159. Items: PSItem;
  2160. I : BreakpointType;
  2161. KeyCount: sw_integer;
  2162. begin
  2163. KeyCount:=longint(high(BreakpointType));
  2164. R.Assign(0,0,60,Max(9+KeyCount,18));
  2165. inherited Init(R,dialog_modifynewbreakpoint);
  2166. Breakpoint:=ABreakpoint;
  2167. GetExtent(R); R.Grow(-3,-2); R3.Copy(R);
  2168. Inc(R.A.Y); R.B.Y:=R.A.Y+1; R.B.X:=R.B.X-3;
  2169. New(NameIL, Init(R, 255)); Insert(NameIL);
  2170. R2.Copy(R); R2.A.X:=R2.B.X; R2.B.X:=R2.A.X+3;
  2171. Insert(New(PHistory, Init(R2, NameIL, hidWatchDialog)));
  2172. R.Copy(R3); Inc(R.A.Y); R.B.Y:=R.A.Y+1;
  2173. R2.Copy(R); R2.Move(-1,-1);
  2174. Insert(New(PLabel, Init(R2, label_breakpoint_name, NameIL)));
  2175. R.Move(0,3);
  2176. New(ConditionsIL, Init(R, 255)); Insert(ConditionsIL);
  2177. R2.Copy(R); R2.Move(-1,-1); Insert(New(PLabel, Init(R2, label_breakpoint_conditions, ConditionsIL)));
  2178. R.Move(0,3); R.B.X:=R.A.X+36;
  2179. New(LineIL, Init(R, 128)); Insert(LineIL);
  2180. LineIL^.SetValidator(New(PRangeValidator, Init(0,MaxInt)));
  2181. R2.Copy(R); R2.Move(-1,-1); Insert(New(PLabel, Init(R2, label_breakpoint_line, LineIL)));
  2182. R.Move(0,3);
  2183. New(IgnoreIL, Init(R, 128)); Insert(IgnoreIL);
  2184. IgnoreIL^.SetValidator(New(PRangeValidator, Init(0,MaxInt)));
  2185. R2.Copy(R); R2.Move(-1,-1); Insert(New(PLabel, Init(R2, label_breakpoint_ignorecount, IgnoreIL)));
  2186. R.Copy(R3); Inc(R.A.X,38); Inc(R.A.Y,7); R.B.Y:=R.A.Y+KeyCount;
  2187. Items:=nil;
  2188. { don't use invalid type }
  2189. for I:=pred(high(BreakpointType)) downto low(BreakpointType) do
  2190. Items:=NewSItem(BreakpointTypeStr[I], Items);
  2191. New(TypeRB, Init(R, Items));
  2192. R2.Copy(R); R2.Move(-1,-1); R2.B.Y:=R2.A.Y+1;
  2193. Insert(New(PLabel, Init(R2, label_breakpoint_type, TypeRB)));
  2194. Insert(TypeRB);
  2195. InsertButtons(@Self);
  2196. NameIL^.Select;
  2197. end;
  2198. function TBreakpointItemDialog.Execute: Word;
  2199. var R: word;
  2200. S1: string;
  2201. err: word;
  2202. L: longint;
  2203. begin
  2204. R:=longint(Breakpoint^.typ);
  2205. TypeRB^.SetData(R);
  2206. If Breakpoint^.typ=bt_file_line then
  2207. S1:=GetStr(Breakpoint^.FileName)
  2208. else
  2209. S1:=GetStr(Breakpoint^.name);
  2210. NameIL^.SetData(S1);
  2211. If Breakpoint^.typ=bt_file_line then
  2212. S1:=IntToStr(Breakpoint^.Line)
  2213. else
  2214. S1:='0';
  2215. LineIL^.SetData(S1);
  2216. S1:=IntToStr(Breakpoint^.IgnoreCount);
  2217. IgnoreIL^.SetData(S1);
  2218. S1:=GetStr(Breakpoint^.Conditions);
  2219. ConditionsIL^.SetData(S1);
  2220. if assigned(FirstEditorWindow) then
  2221. FindReplaceEditor:=FirstEditorWindow^.Editor;
  2222. R:=inherited Execute;
  2223. FindReplaceEditor:=nil;
  2224. if R=cmOK then
  2225. begin
  2226. TypeRB^.GetData(R);
  2227. L:=R;
  2228. Breakpoint^.typ:=BreakpointType(L);
  2229. NameIL^.GetData(S1);
  2230. If Breakpoint^.typ=bt_file_line then
  2231. begin
  2232. If assigned(Breakpoint^.FileName) then
  2233. DisposeStr(Breakpoint^.FileName);
  2234. Breakpoint^.FileName:=NewStr(S1);
  2235. end
  2236. else
  2237. begin
  2238. If assigned(Breakpoint^.Name) then
  2239. DisposeStr(Breakpoint^.Name);
  2240. Breakpoint^.name:=NewStr(S1);
  2241. end;
  2242. If Breakpoint^.typ=bt_file_line then
  2243. begin
  2244. LineIL^.GetData(S1);
  2245. Val(S1,L,err);
  2246. Breakpoint^.Line:=L;
  2247. end;
  2248. IgnoreIL^.GetData(S1);
  2249. Val(S1,L,err);
  2250. Breakpoint^.IgnoreCount:=L;
  2251. ConditionsIL^.GetData(S1);
  2252. If assigned(Breakpoint^.Conditions) then
  2253. DisposeStr(Breakpoint^.Conditions);
  2254. Breakpoint^.Conditions:=NewStr(S1);
  2255. end;
  2256. Execute:=R;
  2257. end;
  2258. {****************************************************************************
  2259. TWatch
  2260. ****************************************************************************}
  2261. constructor TWatch.Init(s : string);
  2262. begin
  2263. expr:=NewStr(s);
  2264. last_value:=nil;
  2265. current_value:=nil;
  2266. Get_new_value;
  2267. GDBRunCount:=-1;
  2268. end;
  2269. constructor TWatch.Load(var S: TStream);
  2270. begin
  2271. expr:=S.ReadStr;
  2272. last_value:=nil;
  2273. current_value:=nil;
  2274. Get_new_value;
  2275. GDBRunCount:=-1;
  2276. end;
  2277. procedure TWatch.Store(var S: TStream);
  2278. begin
  2279. S.WriteStr(expr);
  2280. end;
  2281. procedure TWatch.rename(s : string);
  2282. begin
  2283. if assigned(expr) then
  2284. begin
  2285. if GetStr(expr)=S then
  2286. exit;
  2287. DisposeStr(expr);
  2288. end;
  2289. expr:=NewStr(s);
  2290. if assigned(last_value) then
  2291. StrDispose(last_value);
  2292. last_value:=nil;
  2293. if assigned(current_value) then
  2294. StrDispose(current_value);
  2295. current_value:=nil;
  2296. GDBRunCount:=-1;
  2297. Get_new_value;
  2298. end;
  2299. procedure TWatch.Get_new_value;
  2300. var p, q : pchar;
  2301. i, j, curframe, startframe : longint;
  2302. s,s2 : string;
  2303. loop_higher, found : boolean;
  2304. last_removed : char;
  2305. function GetValue(var s : string) : boolean;
  2306. begin
  2307. Debugger^.command('p '+s);
  2308. if not Debugger^.Error then
  2309. begin
  2310. s:=StrPas(Debugger^.GetOutput);
  2311. GetValue:=true;
  2312. end
  2313. else
  2314. begin
  2315. s:=StrPas(Debugger^.GetError);
  2316. GetValue:=false;
  2317. { do not open a messagebox for such errors }
  2318. Debugger^.got_error:=false;
  2319. end;
  2320. end;
  2321. begin
  2322. If not assigned(Debugger) or Not Debugger^.HasExe or
  2323. (GDBRunCount=Debugger^.RunCount) then
  2324. exit;
  2325. GDBRunCount:=Debugger^.RunCount;
  2326. if assigned(last_value) then
  2327. strdispose(last_value);
  2328. last_value:=current_value;
  2329. s:=GetStr(expr);
  2330. found:=GetValue(s);
  2331. Debugger^.got_error:=false;
  2332. loop_higher:=not found;
  2333. if not found then
  2334. begin
  2335. curframe:=Debugger^.get_current_frame;
  2336. startframe:=curframe;
  2337. end
  2338. else
  2339. begin
  2340. curframe:=0;
  2341. startframe:=0;
  2342. end;
  2343. while loop_higher do
  2344. begin
  2345. s:='parent_ebp';
  2346. if GetValue(s) then
  2347. begin
  2348. repeat
  2349. inc(curframe);
  2350. if not Debugger^.set_current_frame(curframe) then
  2351. loop_higher:=false;
  2352. {$ifdef FrameNameKnown}
  2353. s2:='/x '+FrameName;
  2354. {$else not FrameNameKnown}
  2355. s2:='/x $ebp';
  2356. {$endif FrameNameKnown}
  2357. getValue(s2);
  2358. j:=pos('=',s2);
  2359. if j>0 then
  2360. s2:=copy(s2,j+1,length(s2));
  2361. while s2[1] in [' ',TAB] do
  2362. delete(s2,1,1);
  2363. if pos(s2,s)>0 then
  2364. loop_higher :=false;
  2365. until not loop_higher;
  2366. { try again at that level }
  2367. s:=GetStr(expr);
  2368. found:=GetValue(s);
  2369. loop_higher:=not found;
  2370. end
  2371. else
  2372. loop_higher:=false;
  2373. end;
  2374. if found then
  2375. p:=StrNew(Debugger^.GetOutput)
  2376. else
  2377. begin
  2378. { get a reasonable output at least }
  2379. s:=GetStr(expr);
  2380. GetValue(s);
  2381. p:=StrNew(Debugger^.GetError);
  2382. end;
  2383. Debugger^.got_error:=false;
  2384. { We should try here to find the expr in parent
  2385. procedure if there are
  2386. I will implement this as I added a
  2387. parent_ebp pseudo local var to local procedure
  2388. in stabs debug info PM }
  2389. { But there are some pitfalls like
  2390. locals redefined in other sublocals that call the function }
  2391. if curframe<>startframe then
  2392. Debugger^.set_current_frame(startframe);
  2393. q:=nil;
  2394. if assigned(p) and (p[0]='$') then
  2395. q:=StrPos(p,'=');
  2396. if not assigned(q) then
  2397. q:=p;
  2398. if assigned(q) then
  2399. i:=strlen(q)
  2400. else
  2401. i:=0;
  2402. if (i>0) and (q[i-1]=#10) then
  2403. begin
  2404. while (i>1) and ((q[i-2]=' ') or (q[i-2]=#9)) do
  2405. dec(i);
  2406. last_removed:=q[i-1];
  2407. q[i-1]:=#0;
  2408. end
  2409. else
  2410. last_removed:=#0;
  2411. if assigned(q) then
  2412. current_value:=strnew(q)
  2413. else
  2414. current_value:=strnew('');
  2415. if last_removed<>#0 then
  2416. q[i-1]:=last_removed;
  2417. strdispose(p);
  2418. GDBRunCount:=Debugger^.RunCount;
  2419. end;
  2420. procedure TWatch.Force_new_value;
  2421. begin
  2422. GDBRunCount:=-1;
  2423. Get_new_value;
  2424. end;
  2425. destructor TWatch.Done;
  2426. begin
  2427. if assigned(expr) then
  2428. disposestr(expr);
  2429. if assigned(last_value) then
  2430. strdispose(last_value);
  2431. if assigned(current_value) then
  2432. strdispose(current_value);
  2433. inherited done;
  2434. end;
  2435. {****************************************************************************
  2436. TWatchesCollection
  2437. ****************************************************************************}
  2438. constructor TWatchesCollection.Init;
  2439. begin
  2440. inherited Init(10,10);
  2441. end;
  2442. procedure TWatchesCollection.Insert(Item: Pointer);
  2443. begin
  2444. PWatch(Item)^.Get_new_value;
  2445. Inherited Insert(Item);
  2446. Update;
  2447. end;
  2448. procedure TWatchesCollection.Update;
  2449. var
  2450. W,W1 : integer;
  2451. procedure GetMax(P : PWatch);
  2452. begin
  2453. if assigned(P^.Current_value) then
  2454. W1:=StrLen(P^.Current_value)+3+Length(GetStr(P^.expr))
  2455. else
  2456. W1:=2+Length(GetStr(P^.expr));
  2457. if W1>W then
  2458. W:=W1;
  2459. end;
  2460. begin
  2461. W:=0;
  2462. ForEach(@GetMax);
  2463. MaxW:=W;
  2464. If assigned(WatchesWindow) then
  2465. WatchesWindow^.WLB^.Update(MaxW);
  2466. end;
  2467. function TWatchesCollection.At(Index: Integer): PWatch;
  2468. begin
  2469. At:=Inherited At(Index);
  2470. end;
  2471. {****************************************************************************
  2472. TWatchesListBox
  2473. ****************************************************************************}
  2474. constructor TWatchesListBox.Init(var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar);
  2475. begin
  2476. inherited Init(Bounds,1,AHScrollBar,AVScrollBar);
  2477. If assigned(List) then
  2478. dispose(list,done);
  2479. List:=WatchesCollection;
  2480. end;
  2481. procedure TWatchesListBox.Update(AMaxWidth : integer);
  2482. var R : TRect;
  2483. begin
  2484. GetExtent(R);
  2485. MaxWidth:=AMaxWidth;
  2486. if (HScrollBar<>nil) and (R.B.X-R.A.X<MaxWidth) then
  2487. HScrollBar^.SetRange(0,MaxWidth-(R.B.X-R.A.X))
  2488. else
  2489. HScrollBar^.SetRange(0,0);
  2490. if R.B.X-R.A.X>MaxWidth then
  2491. HScrollBar^.Hide
  2492. else
  2493. HScrollBar^.Show;
  2494. SetRange(List^.Count+1);
  2495. if R.B.Y-R.A.Y>Range then
  2496. VScrollBar^.Hide
  2497. else
  2498. VScrollBar^.Show;
  2499. {if Focused=List^.Count-1-1 then
  2500. FocusItem(List^.Count-1);
  2501. What was that for ?? PM }
  2502. DrawView;
  2503. end;
  2504. function TWatchesListBox.GetIndentedText(Item,Indent,MaxLen: Sw_Integer;var Modified : boolean): String;
  2505. var
  2506. PW : PWatch;
  2507. ValOffset : Sw_integer;
  2508. S : String;
  2509. begin
  2510. Modified:=false;
  2511. if Item>=WatchesCollection^.Count then
  2512. begin
  2513. GetIndentedText:='';
  2514. exit;
  2515. end;
  2516. PW:=WatchesCollection^.At(Item);
  2517. ValOffset:=Length(GetStr(PW^.Expr))+2;
  2518. if not assigned(PW^.expr) then
  2519. GetIndentedText:=''
  2520. else if Indent<ValOffset then
  2521. begin
  2522. S:=GetStr(PW^.Expr);
  2523. if Indent=0 then
  2524. S:=' '+S
  2525. else
  2526. S:=Copy(S,Indent,High(S));
  2527. if not assigned(PW^.current_value) then
  2528. S:=S+' <Unknown value>'
  2529. else
  2530. S:=S+' '+GetPChar(PW^.Current_value);
  2531. GetIndentedText:=Copy(S,1,MaxLen);
  2532. end
  2533. else
  2534. begin
  2535. if not assigned(PW^.Current_value) or
  2536. (StrLen(PW^.Current_value)<Indent-Valoffset) then
  2537. S:=''
  2538. else
  2539. S:=GetPchar(@(PW^.Current_Value[Indent-Valoffset]));
  2540. GetIndentedText:=Copy(S,1,MaxLen);
  2541. end;
  2542. if assigned(PW^.current_value) and
  2543. assigned(PW^.last_value) and
  2544. (strcomp(PW^.Last_value,PW^.Current_value)<>0) then
  2545. Modified:=true;
  2546. end;
  2547. procedure TWatchesListBox.EditCurrent;
  2548. var
  2549. P: PWatch;
  2550. begin
  2551. if Range=0 then Exit;
  2552. if Focused<WatchesCollection^.Count then
  2553. P:=WatchesCollection^.At(Focused)
  2554. else
  2555. P:=New(PWatch,Init(''));
  2556. Application^.ExecuteDialog(New(PWatchItemDialog,Init(P)),nil);
  2557. WatchesCollection^.Update;
  2558. end;
  2559. function TWatchesListBox.GetText (Item: Sw_Integer; MaxLen: Sw_Integer): String;
  2560. var
  2561. Dummy_Modified : boolean;
  2562. begin
  2563. GetText:=GetIndentedText(Item, 0, MaxLen, Dummy_Modified);
  2564. end;
  2565. procedure TWatchesListBox.DeleteCurrent;
  2566. var
  2567. P: PWatch;
  2568. begin
  2569. if (Range=0) or
  2570. (Focused>=WatchesCollection^.Count) then
  2571. exit;
  2572. P:=WatchesCollection^.At(Focused);
  2573. WatchesCollection^.free(P);
  2574. WatchesCollection^.Update;
  2575. end;
  2576. procedure TWatchesListBox.EditNew;
  2577. var
  2578. P: PWatch;
  2579. S : string;
  2580. begin
  2581. if Focused<WatchesCollection^.Count then
  2582. begin
  2583. P:=WatchesCollection^.At(Focused);
  2584. S:=GetStr(P^.expr);
  2585. end
  2586. else
  2587. S:='';
  2588. P:=New(PWatch,Init(S));
  2589. if Application^.ExecuteDialog(New(PWatchItemDialog,Init(P)),nil)<>cmCancel then
  2590. begin
  2591. WatchesCollection^.AtInsert(Focused,P);
  2592. WatchesCollection^.Update;
  2593. end
  2594. else
  2595. dispose(P,Done);
  2596. end;
  2597. procedure TWatchesListBox.Draw;
  2598. var
  2599. I, J, Item: Sw_Integer;
  2600. NormalColor, SelectedColor, FocusedColor, Color: Word;
  2601. ColWidth, CurCol, Indent: Integer;
  2602. B: TDrawBuffer;
  2603. Modified : boolean;
  2604. Text: String;
  2605. SCOff: Byte;
  2606. TC: byte;
  2607. procedure MT(var C: word);
  2608. begin
  2609. if TC<>0 then C:=(C and $ff0f) or (TC and $f0);
  2610. end;
  2611. begin
  2612. if (Owner<>nil) then TC:=ord(Owner^.GetColor(6)) else TC:=0;
  2613. if State and (sfSelected + sfActive) = (sfSelected + sfActive) then
  2614. begin
  2615. NormalColor := GetColor(1);
  2616. FocusedColor := GetColor(3);
  2617. SelectedColor := GetColor(4);
  2618. end else
  2619. begin
  2620. NormalColor := GetColor(2);
  2621. SelectedColor := GetColor(4);
  2622. end;
  2623. if Transparent then
  2624. begin MT(NormalColor); MT(SelectedColor); end;
  2625. (* if NoSelection then
  2626. SelectedColor:=NormalColor;*)
  2627. if HScrollBar <> nil then Indent := HScrollBar^.Value
  2628. else Indent := 0;
  2629. ColWidth := Size.X div NumCols + 1;
  2630. for I := 0 to Size.Y - 1 do
  2631. begin
  2632. for J := 0 to NumCols-1 do
  2633. begin
  2634. Item := J*Size.Y + I + TopItem;
  2635. CurCol := J*ColWidth;
  2636. if (State and (sfSelected + sfActive) = (sfSelected + sfActive)) and
  2637. (Focused = Item) and (Range > 0) then
  2638. begin
  2639. Color := FocusedColor;
  2640. SetCursor(CurCol+1,I);
  2641. SCOff := 0;
  2642. end
  2643. else if (Item < Range) and IsSelected(Item) then
  2644. begin
  2645. Color := SelectedColor;
  2646. SCOff := 2;
  2647. end
  2648. else
  2649. begin
  2650. Color := NormalColor;
  2651. SCOff := 4;
  2652. end;
  2653. MoveChar(B[CurCol], ' ', Color, ColWidth);
  2654. if Item < Range then
  2655. begin
  2656. (* Text := GetText(Item, ColWidth + Indent);
  2657. Text := Copy(Text,Indent,ColWidth); *)
  2658. Text:=GetIndentedText(Item,Indent,ColWidth,Modified);
  2659. if modified then
  2660. begin
  2661. SCOff:=0;
  2662. Color:=(Color and $fff0) or Red;
  2663. end;
  2664. MoveStr(B[CurCol], Text, Color);
  2665. if {ShowMarkers or } Modified then
  2666. begin
  2667. WordRec(B[CurCol]).Lo := Byte(SpecialChars[SCOff]);
  2668. WordRec(B[CurCol+ColWidth-2]).Lo := Byte(SpecialChars[SCOff+1]);
  2669. WordRec(B[CurCol+ColWidth-2]).Hi := Color and $ff;
  2670. end;
  2671. end;
  2672. MoveChar(B[CurCol+ColWidth-1], #179, GetColor(5), 1);
  2673. end;
  2674. WriteLine(0, I, Size.X, 1, B);
  2675. end;
  2676. end;
  2677. function TWatchesListBox.GetLocalMenu: PMenu;
  2678. var M: PMenu;
  2679. begin
  2680. if (Owner<>nil) and (Owner^.GetState(sfModal)) then M:=nil else
  2681. M:=NewMenu(
  2682. NewItem(menu_watchlocal_edit,'',kbNoKey,cmEdit,hcNoContext,
  2683. NewItem(menu_watchlocal_new,'',kbNoKey,cmNew,hcNoContext,
  2684. NewItem(menu_watchlocal_delete,'',kbNoKey,cmDelete,hcNoContext,
  2685. NewLine(
  2686. NewItem(menu_msglocal_saveas,'',kbNoKey,cmSaveAs,hcSaveAs,
  2687. nil))))));
  2688. GetLocalMenu:=M;
  2689. end;
  2690. procedure TWatchesListBox.HandleEvent(var Event: TEvent);
  2691. var DontClear: boolean;
  2692. begin
  2693. case Event.What of
  2694. evKeyDown :
  2695. begin
  2696. DontClear:=false;
  2697. case Event.KeyCode of
  2698. kbEnter :
  2699. Message(@Self,evCommand,cmEdit,nil);
  2700. kbIns :
  2701. Message(@Self,evCommand,cmNew,nil);
  2702. kbDel :
  2703. Message(@Self,evCommand,cmDelete,nil);
  2704. else
  2705. DontClear:=true;
  2706. end;
  2707. if not DontClear then
  2708. ClearEvent(Event);
  2709. end;
  2710. evBroadcast :
  2711. case Event.Command of
  2712. cmListItemSelected :
  2713. if Event.InfoPtr=@Self then
  2714. Message(@Self,evCommand,cmEdit,nil);
  2715. end;
  2716. evCommand :
  2717. begin
  2718. DontClear:=false;
  2719. case Event.Command of
  2720. cmEdit :
  2721. EditCurrent;
  2722. cmDelete :
  2723. DeleteCurrent;
  2724. cmNew :
  2725. EditNew;
  2726. else
  2727. DontClear:=true;
  2728. end;
  2729. if not DontClear then
  2730. ClearEvent(Event);
  2731. end;
  2732. end;
  2733. inherited HandleEvent(Event);
  2734. end;
  2735. constructor TWatchesListBox.Load(var S: TStream);
  2736. begin
  2737. inherited Load(S);
  2738. If assigned(List) then
  2739. dispose(list,done);
  2740. List:=WatchesCollection;
  2741. { we must set Range PM }
  2742. SetRange(List^.count+1);
  2743. end;
  2744. procedure TWatchesListBox.Store(var S: TStream);
  2745. var OL: PCollection;
  2746. OldRange : Sw_integer;
  2747. begin
  2748. OL:=List;
  2749. OldRange:=Range;
  2750. Range:=0;
  2751. New(List, Init(1,1));
  2752. inherited Store(S);
  2753. Dispose(List, Done);
  2754. List:=OL;
  2755. { ^^^ nasty trick - has anyone a better idea how to avoid storing the
  2756. collection? Pasting here a modified version of TListBox.Store+
  2757. TAdvancedListBox.Store isn't a better solution, since by eventually
  2758. changing the obj-hierarchy you'll always have to modify this, too - BG }
  2759. SetRange(OldRange);
  2760. end;
  2761. destructor TWatchesListBox.Done;
  2762. begin
  2763. List:=nil;
  2764. inherited Done;
  2765. end;
  2766. {****************************************************************************
  2767. TWatchesWindow
  2768. ****************************************************************************}
  2769. Constructor TWatchesWindow.Init;
  2770. var
  2771. HSB,VSB: PScrollBar;
  2772. R,R2 : trect;
  2773. begin
  2774. Desktop^.GetExtent(R);
  2775. R.A.Y:=R.B.Y-7;
  2776. inherited Init(R, dialog_watches,SearchFreeWindowNo);
  2777. Palette:=wpCyanWindow;
  2778. GetExtent(R);
  2779. HelpCtx:=hcWatchesWindow;
  2780. R.Grow(-1,-1);
  2781. R2.Copy(R);
  2782. Inc(R2.B.Y);
  2783. R2.A.Y:=R2.B.Y-1;
  2784. New(HSB, Init(R2));
  2785. HSB^.GrowMode:=gfGrowLoY+gfGrowHiY+gfGrowHiX;
  2786. HSB^.SetStep(R.B.X-R.A.X,1);
  2787. Insert(HSB);
  2788. R2.Copy(R);
  2789. Inc(R2.B.X);
  2790. R2.A.X:=R2.B.X-1;
  2791. New(VSB, Init(R2));
  2792. VSB^.GrowMode:=gfGrowLoX+gfGrowHiX+gfGrowHiY;
  2793. Insert(VSB);
  2794. New(WLB,Init(R,HSB,VSB));
  2795. WLB^.GrowMode:=gfGrowHiX+gfGrowHiY;
  2796. WLB^.Transparent:=true;
  2797. Insert(WLB);
  2798. If assigned(WatchesWindow) then
  2799. dispose(WatchesWindow,done);
  2800. WatchesWindow:=@Self;
  2801. Update;
  2802. end;
  2803. procedure TWatchesWindow.Update;
  2804. begin
  2805. WatchesCollection^.Update;
  2806. Draw;
  2807. end;
  2808. constructor TWatchesWindow.Load(var S: TStream);
  2809. begin
  2810. inherited Load(S);
  2811. GetSubViewPtr(S,WLB);
  2812. If assigned(WatchesWindow) then
  2813. dispose(WatchesWindow,done);
  2814. WatchesWindow:=@Self;
  2815. end;
  2816. procedure TWatchesWindow.Store(var S: TStream);
  2817. begin
  2818. inherited Store(S);
  2819. PutSubViewPtr(S,WLB);
  2820. end;
  2821. Destructor TWatchesWindow.Done;
  2822. begin
  2823. WatchesWindow:=nil;
  2824. Dispose(WLB,done);
  2825. inherited done;
  2826. end;
  2827. {****************************************************************************
  2828. TWatchItemDialog
  2829. ****************************************************************************}
  2830. constructor TWatchItemDialog.Init(AWatch: PWatch);
  2831. var R,R2: TRect;
  2832. begin
  2833. R.Assign(0,0,50,10);
  2834. inherited Init(R,'Edit Watch');
  2835. Watch:=AWatch;
  2836. GetExtent(R); R.Grow(-3,-2);
  2837. Inc(R.A.Y); R.B.Y:=R.A.Y+1; R.B.X:=R.A.X+36;
  2838. New(NameIL, Init(R, 255)); Insert(NameIL);
  2839. R2.Copy(R); R2.A.X:=R2.B.X; R2.B.X:=R2.A.X+3;
  2840. Insert(New(PHistory, Init(R2, NameIL, hidWatchDialog)));
  2841. R2.Copy(R); R2.Move(-1,-1);
  2842. Insert(New(PLabel, Init(R2, label_watch_expressiontowatch, NameIL)));
  2843. GetExtent(R);
  2844. R.Grow(-3,-1);
  2845. R.A.Y:=R.A.Y+3;
  2846. TextST:=New(PAdvancedStaticText, Init(R, label_watch_values));
  2847. Insert(TextST);
  2848. InsertButtons(@Self);
  2849. NameIL^.Select;
  2850. end;
  2851. function TWatchItemDialog.Execute: Word;
  2852. var R: word;
  2853. S1,S2: string;
  2854. begin
  2855. S1:=GetStr(Watch^.expr);
  2856. NameIL^.SetData(S1);
  2857. S1:=GetPChar(Watch^.Current_value);
  2858. S2:=GetPChar(Watch^.Last_value);
  2859. ClearFormatParams;
  2860. AddFormatParamStr(S1);
  2861. AddFormatParamStr(S2);
  2862. if assigned(Watch^.Last_value) and
  2863. assigned(Watch^.Current_value) and
  2864. (strcomp(Watch^.Last_value,Watch^.Current_value)=0) then
  2865. S1:=FormatStrF(msg_watch_currentvalue,FormatParams)
  2866. else
  2867. S1:=FormatStrF(msg_watch_currentandpreviousvalue,FormatParams);
  2868. TextST^.SetText(S1);
  2869. if assigned(FirstEditorWindow) then
  2870. FindReplaceEditor:=FirstEditorWindow^.Editor;
  2871. R:=inherited Execute;
  2872. FindReplaceEditor:=nil;
  2873. if R=cmOK then
  2874. begin
  2875. NameIL^.GetData(S1);
  2876. Watch^.Rename(S1);
  2877. If assigned(Debugger) then
  2878. Debugger^.ReadWatches;
  2879. end;
  2880. Execute:=R;
  2881. end;
  2882. {****************************************************************************
  2883. TStackWindow
  2884. ****************************************************************************}
  2885. constructor TFramesListBox.Init(var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar);
  2886. begin
  2887. Inherited Init(Bounds,AHScrollBar,AVScrollBar);
  2888. end;
  2889. procedure TFramesListBox.Update;
  2890. var i : longint;
  2891. W : PSourceWindow;
  2892. begin
  2893. { call backtrace command }
  2894. If not assigned(Debugger) then
  2895. exit;
  2896. {$ifndef NODEBUG}
  2897. DeskTop^.Lock;
  2898. Clear;
  2899. { forget all old frames }
  2900. Debugger^.clear_frames;
  2901. if Debugger^.WindowWidth<>-1 then
  2902. Debugger^.Command('set width 0xffffffff');
  2903. Debugger^.Command('backtrace');
  2904. { generate list }
  2905. { all is in tframeentry }
  2906. for i:=0 to Debugger^.frame_count-1 do
  2907. begin
  2908. with Debugger^.frames[i]^ do
  2909. begin
  2910. if assigned(file_name) then
  2911. AddItem(new(PMessageItem,init(0,GetPChar(function_name)+GetPChar(args),
  2912. AddModuleName(GetPChar(file_name)),line_number,1)))
  2913. else
  2914. AddItem(new(PMessageItem,init(0,HexStr(address,8)+' '+GetPChar(function_name)+GetPChar(args),
  2915. AddModuleName(''),line_number,1)));
  2916. W:=SearchOnDesktop(GetPChar(file_name),false);
  2917. { First reset all Debugger rows }
  2918. If assigned(W) then
  2919. begin
  2920. W^.Editor^.SetLineFlagExclusive(lfDebuggerRow,-1);
  2921. W^.Editor^.DebuggerRow:=-1;
  2922. end;
  2923. end;
  2924. end;
  2925. { Now set all Debugger rows }
  2926. for i:=0 to Debugger^.frame_count-1 do
  2927. begin
  2928. with Debugger^.frames[i]^ do
  2929. begin
  2930. W:=SearchOnDesktop(GetPChar(file_name),false);
  2931. If assigned(W) then
  2932. begin
  2933. If W^.Editor^.DebuggerRow=-1 then
  2934. begin
  2935. W^.Editor^.SetLineFlagState(line_number-1,lfDebuggerRow,true);
  2936. W^.Editor^.DebuggerRow:=line_number-1;
  2937. end;
  2938. end;
  2939. end;
  2940. end;
  2941. if Assigned(list) and (List^.Count > 0) then
  2942. FocusItem(0);
  2943. if Debugger^.WindowWidth<>-1 then
  2944. Debugger^.Command('set width '+IntToStr(Debugger^.WindowWidth));
  2945. DeskTop^.Unlock;
  2946. {$endif}
  2947. end;
  2948. function TFramesListBox.GetLocalMenu: PMenu;
  2949. begin
  2950. GetLocalMenu:=Inherited GetLocalMenu;
  2951. end;
  2952. procedure TFramesListBox.GotoSource;
  2953. begin
  2954. { select frame for watches }
  2955. If not assigned(Debugger) then
  2956. exit;
  2957. {$ifndef NODEBUG}
  2958. Debugger^.Command('f '+IntToStr(Focused));
  2959. { for local vars }
  2960. Debugger^.RereadWatches;
  2961. {$endif}
  2962. { goto source }
  2963. inherited GotoSource;
  2964. end;
  2965. procedure TFramesListBox.GotoAssembly;
  2966. begin
  2967. { select frame for watches }
  2968. If not assigned(Debugger) then
  2969. exit;
  2970. {$ifndef NODEBUG}
  2971. Debugger^.Command('f '+IntToStr(Focused));
  2972. { for local vars }
  2973. Debugger^.RereadWatches;
  2974. {$endif}
  2975. { goto source/assembly mixture }
  2976. InitDisassemblyWindow;
  2977. DisassemblyWindow^.LoadFunction('');
  2978. DisassemblyWindow^.SetCurAddress(Debugger^.frames[Focused]^.address);
  2979. DisassemblyWindow^.SelectInDebugSession;
  2980. end;
  2981. procedure TFramesListBox.HandleEvent(var Event: TEvent);
  2982. begin
  2983. if ((Event.What=EvKeyDown) and (Event.CharCode='i')) or
  2984. ((Event.What=EvCommand) and (Event.Command=cmDisassemble)) then
  2985. GotoAssembly;
  2986. inherited HandleEvent(Event);
  2987. end;
  2988. destructor TFramesListBox.Done;
  2989. begin
  2990. Inherited Done;
  2991. end;
  2992. Constructor TStackWindow.Init;
  2993. var
  2994. HSB,VSB: PScrollBar;
  2995. R,R2 : trect;
  2996. begin
  2997. Desktop^.GetExtent(R);
  2998. R.A.Y:=R.B.Y-5;
  2999. inherited Init(R, dialog_callstack, wnNoNumber);
  3000. Palette:=wpCyanWindow;
  3001. GetExtent(R);
  3002. HelpCtx:=hcStackWindow;
  3003. R.Grow(-1,-1);
  3004. R2.Copy(R);
  3005. Inc(R2.B.Y);
  3006. R2.A.Y:=R2.B.Y-1;
  3007. New(HSB, Init(R2));
  3008. HSB^.GrowMode:=gfGrowLoY+gfGrowHiY+gfGrowHiX;
  3009. Insert(HSB);
  3010. R2.Copy(R);
  3011. Inc(R2.B.X);
  3012. R2.A.X:=R2.B.X-1;
  3013. New(VSB, Init(R2));
  3014. VSB^.GrowMode:=gfGrowLoX+gfGrowHiX+gfGrowHiY;
  3015. Insert(VSB);
  3016. New(FLB,Init(R,HSB,VSB));
  3017. FLB^.GrowMode:=gfGrowHiX+gfGrowHiY;
  3018. Insert(FLB);
  3019. If assigned(StackWindow) then
  3020. dispose(StackWindow,done);
  3021. StackWindow:=@Self;
  3022. Update;
  3023. end;
  3024. procedure TStackWindow.Update;
  3025. begin
  3026. FLB^.Update;
  3027. DrawView;
  3028. end;
  3029. constructor TStackWindow.Load(var S: TStream);
  3030. begin
  3031. inherited Load(S);
  3032. GetSubViewPtr(S,FLB);
  3033. If assigned(StackWindow) then
  3034. dispose(StackWindow,done);
  3035. StackWindow:=@Self;
  3036. end;
  3037. procedure TStackWindow.Store(var S: TStream);
  3038. begin
  3039. inherited Store(S);
  3040. PutSubViewPtr(S,FLB);
  3041. end;
  3042. Destructor TStackWindow.Done;
  3043. begin
  3044. StackWindow:=nil;
  3045. Dispose(FLB,done);
  3046. inherited done;
  3047. end;
  3048. {****************************************************************************
  3049. Init/Final
  3050. ****************************************************************************}
  3051. function GetGDBTargetShortName : string;
  3052. begin
  3053. {$ifdef SUPPORT_REMOTE}
  3054. GetGDBTargetShortName:='linux';
  3055. {$else not SUPPORT_REMOTE}
  3056. {$ifdef COMPILER_1_0}
  3057. GetGDBTargetShortName:=source_os.shortname
  3058. {$else}
  3059. GetGDBTargetShortName:=source_info.shortname
  3060. {$endif}
  3061. {$endif not SUPPORT_REMOTE}
  3062. end;
  3063. procedure InitDebugger;
  3064. {$ifdef DEBUG}
  3065. var s : string;
  3066. i,p : longint;
  3067. {$endif DEBUG}
  3068. var
  3069. NeedRecompileExe : boolean;
  3070. cm : longint;
  3071. begin
  3072. {$ifdef DEBUG}
  3073. if not use_gdb_file then
  3074. begin
  3075. Assign(gdb_file,GDBOutFileName);
  3076. {$I-}
  3077. Rewrite(gdb_file);
  3078. if InOutRes<>0 then
  3079. begin
  3080. s:=GDBOutFileName;
  3081. p:=pos('.',s);
  3082. if p>1 then
  3083. for i:=0 to 9 do
  3084. begin
  3085. s:=copy(s,1,p-2)+chr(i+ord('0'))+copy(s,p,length(s));
  3086. InOutRes:=0;
  3087. Assign(gdb_file,s);
  3088. rewrite(gdb_file);
  3089. if InOutRes=0 then
  3090. break;
  3091. end;
  3092. end;
  3093. if IOResult=0 then
  3094. Use_gdb_file:=true;
  3095. end;
  3096. {$I+}
  3097. {$endif}
  3098. NeedRecompileExe:=false;
  3099. if TargetSwitches^.GetCurrSelParam<>GetGDBTargetShortName then
  3100. begin
  3101. ClearFormatParams;
  3102. AddFormatParamStr(TargetSwitches^.GetCurrSelParam);
  3103. AddFormatParamStr(GetGDBTargetShortName);
  3104. cm:=ConfirmBox(msg_cantdebugchangetargetto,@FormatParams,true);
  3105. if cm=cmCancel then
  3106. Exit;
  3107. if cm=cmYes then
  3108. begin
  3109. { force recompilation }
  3110. PrevMainFile:='';
  3111. NeedRecompileExe:=true;
  3112. TargetSwitches^.SetCurrSelParam(GetGDBTargetShortName);
  3113. If DebugInfoSwitches^.GetCurrSelParam='-' then
  3114. DebugInfoSwitches^.SetCurrSelParam('l');
  3115. IDEApp.UpdateTarget;
  3116. end;
  3117. end;
  3118. if not NeedRecompileExe then
  3119. NeedRecompileExe:=(not ExistsFile(ExeFile)) or (CompilationPhase<>cpDone) or
  3120. (PrevMainFile<>MainFile) or NeedRecompile(cRun,false);
  3121. if Not NeedRecompileExe and Not MainHasDebugInfo then
  3122. begin
  3123. ClearFormatParams;
  3124. cm:=ConfirmBox(msg_compiledwithoutdebuginforecompile,nil,true);
  3125. if cm=cmCancel then
  3126. Exit;
  3127. if cm=cmYes then
  3128. begin
  3129. { force recompilation }
  3130. PrevMainFile:='';
  3131. NeedRecompileExe:=true;
  3132. DebugInfoSwitches^.SetCurrSelParam('l');
  3133. end;
  3134. end;
  3135. if NeedRecompileExe then
  3136. DoCompile(cRun);
  3137. if CompilationPhase<>cpDone then
  3138. Exit;
  3139. if (EXEFile='') then
  3140. begin
  3141. ErrorBox(msg_nothingtodebug,nil);
  3142. Exit;
  3143. end;
  3144. { init debugcontroller }
  3145. if not assigned(Debugger) then
  3146. begin
  3147. PushStatus(msg_startingdebugger);
  3148. new(Debugger,Init);
  3149. PopStatus;
  3150. end;
  3151. Debugger^.SetExe(ExeFile);
  3152. {$ifdef GDBWINDOW}
  3153. InitGDBWindow;
  3154. {$endif def GDBWINDOW}
  3155. end;
  3156. procedure DoneDebugger;
  3157. begin
  3158. {$ifdef DEBUG}
  3159. If IDEApp.IsRunning then
  3160. PushStatus('Closing debugger');
  3161. {$endif}
  3162. if assigned(Debugger) then
  3163. dispose(Debugger,Done);
  3164. Debugger:=nil;
  3165. {$ifdef DOS}
  3166. If assigned(UserScreen) then
  3167. PDosScreen(UserScreen)^.FreeGraphBuffer;
  3168. {$endif DOS}
  3169. {$ifdef DEBUG}
  3170. If Use_gdb_file then
  3171. begin
  3172. Use_gdb_file:=false;
  3173. Close(GDB_file);
  3174. end;
  3175. If IDEApp.IsRunning then
  3176. PopStatus;
  3177. {$endif DEBUG}
  3178. end;
  3179. procedure InitGDBWindow;
  3180. var
  3181. R : TRect;
  3182. begin
  3183. if GDBWindow=nil then
  3184. begin
  3185. DeskTop^.GetExtent(R);
  3186. new(GDBWindow,init(R));
  3187. DeskTop^.Insert(GDBWindow);
  3188. end;
  3189. end;
  3190. procedure DoneGDBWindow;
  3191. begin
  3192. If IDEApp.IsRunning and
  3193. assigned(GDBWindow) then
  3194. begin
  3195. DeskTop^.Delete(GDBWindow);
  3196. end;
  3197. GDBWindow:=nil;
  3198. end;
  3199. procedure InitDisassemblyWindow;
  3200. var
  3201. R : TRect;
  3202. begin
  3203. if DisassemblyWindow=nil then
  3204. begin
  3205. DeskTop^.GetExtent(R);
  3206. new(DisassemblyWindow,init(R));
  3207. DeskTop^.Insert(DisassemblyWindow);
  3208. end;
  3209. end;
  3210. procedure DoneDisassemblyWindow;
  3211. begin
  3212. if assigned(DisassemblyWindow) then
  3213. begin
  3214. DeskTop^.Delete(DisassemblyWindow);
  3215. Dispose(DisassemblyWindow,Done);
  3216. DisassemblyWindow:=nil;
  3217. end;
  3218. end;
  3219. procedure InitStackWindow;
  3220. begin
  3221. if StackWindow=nil then
  3222. begin
  3223. new(StackWindow,init);
  3224. DeskTop^.Insert(StackWindow);
  3225. end;
  3226. end;
  3227. procedure DoneStackWindow;
  3228. begin
  3229. if assigned(StackWindow) then
  3230. begin
  3231. DeskTop^.Delete(StackWindow);
  3232. StackWindow:=nil;
  3233. end;
  3234. end;
  3235. procedure InitBreakpoints;
  3236. begin
  3237. New(BreakpointsCollection,init(10,10));
  3238. end;
  3239. procedure DoneBreakpoints;
  3240. begin
  3241. Dispose(BreakpointsCollection,Done);
  3242. BreakpointsCollection:=nil;
  3243. end;
  3244. procedure InitWatches;
  3245. begin
  3246. New(WatchesCollection,init);
  3247. end;
  3248. procedure DoneWatches;
  3249. begin
  3250. Dispose(WatchesCollection,Done);
  3251. WatchesCollection:=nil;
  3252. end;
  3253. procedure RegisterFPDebugViews;
  3254. begin
  3255. RegisterType(RWatchesWindow);
  3256. RegisterType(RBreakpointsWindow);
  3257. RegisterType(RWatchesListBox);
  3258. RegisterType(RBreakpointsListBox);
  3259. RegisterType(RStackWindow);
  3260. RegisterType(RFramesListBox);
  3261. RegisterType(RBreakpoint);
  3262. RegisterType(RWatch);
  3263. RegisterType(RBreakpointCollection);
  3264. RegisterType(RWatchesCollection);
  3265. end;
  3266. end.
  3267. {
  3268. $Log$
  3269. Revision 1.40 2002-02-09 02:04:46 pierre
  3270. * fix problem with disable all invalid breakpoints
  3271. Revision 1.39 2002/12/12 00:05:57 pierre
  3272. * add code for breakpoint moves + registers in fprags.pas unit
  3273. Revision 1.38 2002/11/30 01:56:52 pierre
  3274. + powerpc cpu support started
  3275. Revision 1.37 2002/11/28 13:00:25 pierre
  3276. + remote support
  3277. Revision 1.36 2002/11/21 17:52:28 pierre
  3278. * some crossgdb infos added
  3279. Revision 1.35 2002/11/21 15:48:39 pierre
  3280. * fix several problems related to remote cross debugging
  3281. Revision 1.34 2002/11/21 00:37:56 pierre
  3282. + some cross gdb enhancements
  3283. Revision 1.33 2002/09/21 22:23:49 pierre
  3284. * restore text mode on reset for Dos apps
  3285. Revision 1.32 2002/09/17 21:58:45 pierre
  3286. * correct last fpu patch so 'info all' is called only once
  3287. Revision 1.31 2002/09/17 21:48:41 pierre
  3288. * allow fpu window to be resized
  3289. Revision 1.30 2002/09/17 21:20:07 pierre
  3290. * fix infinite recursion if GDB window and register window open
  3291. Revision 1.29 2002/09/13 22:30:50 pierre
  3292. * only fpc uses video unit
  3293. Revision 1.28 2002/09/13 08:13:07 pierre
  3294. * avoid RTE 201 in hexstr calls
  3295. Revision 1.27 2002/09/07 21:04:41 carl
  3296. * fix range check errors for version 1.1 compilation
  3297. Revision 1.26 2002/09/07 15:40:42 peter
  3298. * old logs removed and tabs fixed
  3299. Revision 1.25 2002/09/03 13:59:47 pierre
  3300. + added history for watches and breakpoints
  3301. Revision 1.24 2002/09/02 10:18:09 pierre
  3302. * fix problems with breakpoint lists
  3303. Revision 1.23 2002/08/13 08:59:12 pierre
  3304. + Run menu changes depending on wether the debuggee is running or not
  3305. Revision 1.22 2002/08/13 07:15:02 pierre
  3306. + Disable all invalid breakpoints feature added
  3307. Revision 1.21 2002/06/10 19:26:48 pierre
  3308. * check if DebuggeTTY is a valid terminal
  3309. Revision 1.20 2002/06/06 14:11:25 pierre
  3310. * handle win32 Ctrl-C change for graphic version
  3311. Revision 1.19 2002/06/06 08:16:18 pierre
  3312. * avoid crashes if quitting while debuggee is running
  3313. Revision 1.18 2002/04/25 13:33:31 pierre
  3314. * fix the problem with dirs containing asterisks
  3315. Revision 1.17 2002/04/17 11:11:54 pierre
  3316. * avoid problems for ClassVariable in Watches window
  3317. Revision 1.16 2002/04/11 06:41:13 pierre
  3318. * fix problem of TWatchesListBox with fvision
  3319. Revision 1.15 2002/04/03 06:18:30 pierre
  3320. * fix some win32 GDB filename problems
  3321. Revision 1.14 2002/04/02 15:09:38 pierre
  3322. * fixed wrong exit without unlock
  3323. Revision 1.13 2002/04/02 13:23:54 pierre
  3324. * Use StrToCard and HexToCard functions to avoid signed/unsigned overflows
  3325. Revision 1.12 2002/04/02 12:20:58 pierre
  3326. * fix problem with breakpoints in subdirs
  3327. Revision 1.11 2002/04/02 11:10:29 pierre
  3328. * fix FPC_BREAK_ERROR problem and avoid blinking J
  3329. Revision 1.10 2002/03/27 11:24:09 pierre
  3330. * fix several problems related to long file nmze support for win32 exes
  3331. Revision 1.9 2002/02/06 14:45:00 pierre
  3332. + handle signals
  3333. }