1{ $Id$ } 2{ ---------------------------------------------- 3 breakpointsdlg.pp - Overview of breakpoints 4 ---------------------------------------------- 5 6 @created(Fri Dec 14st WET 2001) 7 @lastmod($Date$) 8 @author(Shane Miller) 9 @author(Marc Weustink <marc@@dommelstein.net>) 10 11 This unit contains the Breakpoint dialog. 12 13 14 *************************************************************************** 15 * * 16 * This source is free software; you can redistribute it and/or modify * 17 * it under the terms of the GNU General Public License as published by * 18 * the Free Software Foundation; either version 2 of the License, or * 19 * (at your option) any later version. * 20 * * 21 * This code is distributed in the hope that it will be useful, but * 22 * WITHOUT ANY WARRANTY; without even the implied warranty of * 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 24 * General Public License for more details. * 25 * * 26 * A copy of the GNU General Public License is available on the World * 27 * Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also * 28 * obtain it by writing to the Free Software Foundation, * 29 * Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA. * 30 * * 31 *************************************************************************** 32} 33 34unit BreakPointsDlg; 35 36{$mode objfpc}{$H+} 37 38interface 39 40uses 41 Classes, SysUtils, LazFileUtils, Forms, Controls, Dialogs, 42 IDEWindowIntf, DebuggerStrConst, Menus, ComCtrls, Debugger, DebuggerDlg, ActnList, MainBase, 43 IDEImagesIntf, DbgIntfDebuggerBase, DbgIntfMiscClasses, SourceEditor, MainIntf; 44 45type 46 TBreakPointsDlgState = ( 47 bpdsItemsNeedUpdate 48 ); 49 TBreakPointsDlgStates = set of TBreakPointsDlgState; 50 51 { TBreakPointsDlg } 52 53 TBreakPointsDlg = class(TDebuggerDlg) 54 actAddSourceBP: TAction; 55 actAddAddressBP: TAction; 56 actAddWatchPoint: TAction; 57 actGroupSetNone: TAction; 58 actGroupSetNew: TAction; 59 actShow: TAction; 60 actProperties: TAction; 61 actToggleCurrentEnable: TAction; 62 actDeleteAllInSrc: TAction; 63 actEnableSelected: TAction; 64 actDisableSelected: TAction; 65 actDeleteSelected: TAction; 66 actEnableAll: TAction; 67 actDisableAll: TAction; 68 actDeleteAll: TAction; 69 actEnableAllInSrc: TAction; 70 actDisableAllInSrc: TAction; 71 ActionList1: TActionList; 72 lvBreakPoints: TListView; 73 popGroupSep: TMenuItem; 74 popGroupSetNew: TMenuItem; 75 popGroupSetNone: TMenuItem; 76 popGroup: TMenuItem; 77 popAddWatchPoint: TMenuItem; 78 popAddAddressBP: TMenuItem; 79 N0: TMenuItem; 80 popShow: TMenuItem; 81 mnuPopup: TPopupMenu; 82 popAdd: TMenuItem; 83 popAddSourceBP: TMenuItem; 84 N1: TMenuItem; //-------------- 85 popProperties: TMenuItem; 86 popEnabled: TMenuItem; 87 popDelete: TMenuItem; 88 N2: TMenuItem; //-------------- 89 popDisableAll: TMenuItem; 90 popEnableAll: TMenuItem; 91 popDeleteAll: TMenuItem; 92 N3: TMenuItem; //-------------- 93 popDisableAllSameSource: TMenuItem; 94 popEnableAllSameSource: TMenuItem; 95 popDeleteAllSameSource: TMenuItem; 96 ToolBar1: TToolBar; 97 ToolButtonAdd: TToolButton; 98 ToolButtonProperties: TToolButton; 99 ToolSep2: TToolButton; 100 ToolButtonEnable: TToolButton; 101 ToolButtonDisable: TToolButton; 102 ToolButtonTrash: TToolButton; 103 ToolSep1: TToolButton; 104 ToolButtonEnableAll: TToolButton; 105 ToolButtonDisableAll: TToolButton; 106 ToolButtonTrashAll: TToolButton; 107 procedure actAddAddressBPExecute(Sender: TObject); 108 procedure actAddSourceBPExecute(Sender: TObject); 109 procedure actAddWatchPointExecute(Sender: TObject); 110 procedure actDisableSelectedExecute(Sender: TObject); 111 procedure actEnableSelectedExecute(Sender: TObject); 112 procedure actGroupSetNoneExecute(Sender: TObject); 113 procedure actGroupSetNewExecute(Sender: TObject); 114 procedure actShowExecute(Sender: TObject); 115 procedure BreakpointsDlgCREATE(Sender: TObject); 116 procedure lvBreakPointsClick(Sender: TObject); 117 procedure lvBreakPointsDBLCLICK(Sender: TObject); 118 procedure lvBreakPointsSelectItem(Sender: TObject; {%H-}Item: TListItem; {%H-}Selected: Boolean); 119 procedure mnuPopupPopup(Sender: TObject); 120 procedure popDeleteAllSameSourceCLICK(Sender: TObject); 121 procedure popDisableAllSameSourceCLICK(Sender: TObject); 122 procedure popEnableAllSameSourceCLICK(Sender: TObject); 123 procedure popPropertiesClick(Sender: TObject); 124 procedure popEnabledClick(Sender: TObject); 125 procedure popDeleteClick(Sender: TObject); 126 procedure popDisableAllClick(Sender: TObject); 127 procedure popEnableAllClick(Sender: TObject); 128 procedure popDeleteAllClick(Sender: TObject); 129 private 130 FBaseDirectory: string; 131 FStates: TBreakPointsDlgStates; 132 FLockActionUpdate: Integer; 133 procedure BreakPointAdd(const {%H-}ASender: TIDEBreakPoints; 134 const ABreakpoint: TIDEBreakPoint); 135 procedure BreakPointUpdate(const ASender: TIDEBreakPoints; 136 const ABreakpoint: TIDEBreakPoint); 137 procedure BreakPointRemove(const {%H-}ASender: TIDEBreakPoints; 138 const ABreakpoint: TIDEBreakPoint); 139 procedure SetBaseDirectory(const AValue: string); 140 procedure popSetGroupItemClick(Sender: TObject); 141 procedure SetGroup(const NewGroup: TIDEBreakPointGroup); 142 143 procedure UpdateItem(const AnItem: TListItem; 144 const ABreakpoint: TIDEBreakPoint); 145 procedure UpdateAll; 146 147 procedure DeleteSelectedBreakpoints; 148 procedure JumpToCurrentBreakPoint; 149 procedure ShowProperties; 150 protected 151 procedure DoBreakPointsChanged; override; 152 procedure DoBeginUpdate; override; 153 procedure DoEndUpdate; override; 154 procedure DisableAllActions; 155 function ColSizeGetter(AColId: Integer; var ASize: Integer): Boolean; 156 procedure ColSizeSetter(AColId: Integer; ASize: Integer); 157 public 158 constructor Create(AOwner: TComponent); override; 159 public 160 property BaseDirectory: string read FBaseDirectory write SetBaseDirectory; 161 property BreakPoints; 162 end; 163 164function GetBreakPointStateDescription(ABreakpoint: TBaseBreakpoint): string; 165function GetBreakPointActionsDescription(ABreakpoint: TBaseBreakpoint): string; 166 167 168implementation 169 170{$R *.lfm} 171uses 172 LazarusIDEStrConsts, BaseDebugManager; 173 174var 175 BreakPointDlgWindowCreator: TIDEWindowCreator; 176 177const 178 COL_BREAK_STATE = 1; 179 COL_BREAK_FILE = 2; 180 COL_BREAK_LINE = 3; 181 COL_BREAK_CONDITION = 4; 182 COL_BREAK_ACTION = 5; 183 COL_BREAK_PASS = 6; 184 COL_BREAK_GROUP = 7; 185 COL_WIDTHS: Array[0..6] of integer = ( 50, 150, 100, 75, 150, 100, 80); 186 187function BreakPointDlgColSizeGetter(AForm: TCustomForm; AColId: Integer; var ASize: Integer): Boolean; 188begin 189 Result := AForm is TBreakPointsDlg; 190 if Result then 191 Result := TBreakPointsDlg(AForm).ColSizeGetter(AColId, ASize); 192end; 193 194procedure BreakPointDlgColSizeSetter(AForm: TCustomForm; AColId: Integer; ASize: Integer); 195begin 196 if AForm is TBreakPointsDlg then 197 TBreakPointsDlg(AForm).ColSizeSetter(AColId, ASize); 198end; 199 200function GetBreakPointStateDescription(ABreakpoint: TBaseBreakpoint): string; 201var 202 DEBUG_STATE: array[Boolean, TValidState] of ShortString; 203begin 204 DEBUG_STATE[false, vsUnknown]:=lisOff; 205 DEBUG_STATE[false, vsValid]:=lisBPSDisabled; 206 DEBUG_STATE[false, vsInvalid]:=lisInvalidOff; 207 DEBUG_STATE[false, vsPending]:=lisInvalidOff; 208 DEBUG_STATE[true, vsUnknown]:=lisOn; 209 DEBUG_STATE[true, vsValid]:=lisBPSEnabled; 210 DEBUG_STATE[true, vsInvalid]:=lisInvalidOn; 211 DEBUG_STATE[true, vsPending]:=lisPendingOn; 212 Result:=DEBUG_STATE[ABreakpoint.Enabled,ABreakpoint.Valid]; 213end; 214 215function GetBreakPointActionsDescription(ABreakpoint: TBaseBreakpoint): string; 216var 217 DEBUG_ACTION: array[TIDEBreakPointAction] of ShortString; 218 CurBreakPoint: TIDEBreakPoint; 219 Action: TIDEBreakPointAction; 220begin 221 Result := ''; 222 223 DEBUG_ACTION[bpaStop]:=lisBreak; 224 DEBUG_ACTION[bpaEnableGroup]:=lisEnableGroups; 225 DEBUG_ACTION[bpaDisableGroup]:=lisDisableGroups; 226 DEBUG_ACTION[bpaLogMessage]:=lisLogMessage; 227 DEBUG_ACTION[bpaEValExpression]:=lisLogEvalExpression; 228 DEBUG_ACTION[bpaLogCallStack]:=lisLogCallStack; 229 DEBUG_ACTION[bpaTakeSnapshot]:=lisTakeSnapshot; 230 231 if ABreakpoint is TIDEBreakPoint then begin 232 CurBreakPoint:=TIDEBreakPoint(ABreakpoint); 233 for Action := Low(TIDEBreakPointAction) to High(TIDEBreakPointAction) do 234 if Action in CurBreakpoint.Actions 235 then begin 236 if Result <> '' then Result := Result + ', '; 237 Result := Result + DEBUG_ACTION[Action] 238 end; 239 end; 240end; 241 242procedure TBreakPointsDlg.BreakPointAdd(const ASender: TIDEBreakPoints; 243 const ABreakpoint: TIDEBreakPoint); 244var 245 Item: TListItem; 246 n: Integer; 247begin 248 Item := lvBreakPoints.Items.FindData(ABreakpoint); 249 if Item = nil 250 then begin 251 Item := lvBreakPoints.Items.Add; 252 Item.Data := ABreakPoint; 253 for n := 0 to 5 do 254 Item.SubItems.Add(''); 255 end; 256 257 UpdateItem(Item, ABreakPoint); 258end; 259 260procedure TBreakPointsDlg.BreakPointUpdate(const ASender: TIDEBreakPoints; 261 const ABreakpoint: TIDEBreakPoint); 262var 263 Item: TListItem; 264begin 265 if ABreakpoint = nil then Exit; 266 267 Item := lvBreakPoints.Items.FindData(ABreakpoint); 268 if Item = nil 269 then BreakPointAdd(ASender, ABreakPoint) 270 else begin 271 if UpdateCount>0 then begin 272 Include(FStates,bpdsItemsNeedUpdate); 273 exit; 274 end; 275 UpdateItem(Item, ABreakPoint); 276 end; 277end; 278 279procedure TBreakPointsDlg.BreakPointRemove(const ASender: TIDEBreakPoints; 280 const ABreakpoint: TIDEBreakPoint); 281begin 282 lvBreakPoints.Items.FindData(ABreakpoint).Free; 283end; 284 285procedure TBreakPointsDlg.SetBaseDirectory(const AValue: string); 286begin 287 if FBaseDirectory=AValue then exit; 288 FBaseDirectory:=AValue; 289 UpdateAll; 290end; 291 292procedure TBreakPointsDlg.SetGroup(const NewGroup: TIDEBreakPointGroup); 293var 294 OldGroup: TIDEBreakPointGroup; 295 OldGroups: TList; 296 i: Integer; 297 PrevChoice: TModalResult; 298begin 299 PrevChoice := mrNone; 300 OldGroups := TList.Create; 301 try 302 for i := 0 to lvBreakPoints.Items.Count - 1 do 303 if lvBreakPoints.Items[i].Selected then 304 begin 305 OldGroup := TIDEBreakPoint(lvBreakPoints.Items[i].Data).Group; 306 TIDEBreakPoint(lvBreakPoints.Items[i].Data).Group := NewGroup; 307 if (OldGroup <> nil) and (OldGroup.Count = 0) and (OldGroups.IndexOf(OldGroup) < 0) then 308 OldGroups.Add(OldGroup); 309 end; 310 finally 311 while OldGroups.Count > 0 do begin 312 OldGroup := TIDEBreakPointGroup(OldGroups[0]); 313 OldGroups.Delete(0); 314 if not (PrevChoice in [mrYesToAll, mrNoToAll]) then 315 begin 316 if OldGroups.Count > 0 then 317 PrevChoice := MessageDlg(Caption, Format(lisGroupEmptyDelete + lisGroupEmptyDeleteMore, 318 [OldGroup.Name, LineEnding, OldGroups.Count]), 319 mtConfirmation, mbYesNo + [mbYesToAll, mbNoToAll], 0) 320 else 321 PrevChoice := MessageDlg(Caption, Format(lisGroupEmptyDelete, 322 [OldGroup.Name]), mtConfirmation, mbYesNo, 0); 323 end; 324 if PrevChoice in [mrYes, mrYesToAll] then 325 OldGroup.Free; 326 end; 327 OldGroups.Free; 328 end; 329end; 330 331constructor TBreakPointsDlg.Create(AOwner: TComponent); 332var 333 i: Integer; 334begin 335 inherited; 336 Name:='BreakPointsDlg'; 337 BreakpointsNotification.OnAdd := @BreakPointAdd; 338 BreakpointsNotification.OnUpdate := @BreakPointUpdate; 339 BreakpointsNotification.OnRemove := @BreakPointRemove; 340 341 ActionList1.Images := IDEImages.Images_16; 342 ToolBar1.Images := IDEImages.Images_16; 343 mnuPopup.Images := IDEImages.Images_16; 344 lvBreakPoints.SmallImages := IDEImages.Images_16; 345 346 ToolButtonAdd.ImageIndex := IDEImages.LoadImage('laz_add'); 347 348 actEnableSelected.Caption := lisDbgItemEnable; 349 actEnableSelected.Hint := lisDbgItemEnableHint; 350 actEnableSelected.ImageIndex := IDEImages.LoadImage('debugger_enable'); 351 352 actDisableSelected.Caption := lisDbgItemDisable; 353 actDisableSelected.Hint := lisDbgItemDisableHint; 354 actDisableSelected.ImageIndex := IDEImages.LoadImage('debugger_disable'); 355 356 actDeleteSelected.Caption := lisBtnDelete; 357 actDeleteSelected.Hint := lisDbgItemDeleteHint; 358 actDeleteSelected.ImageIndex := IDEImages.LoadImage('laz_delete'); 359 360 actEnableAll.Caption := lisEnableAll; 361 actEnableAll.Hint := lisDbgAllItemEnableHint; 362 actEnableAll.ImageIndex := IDEImages.LoadImage('debugger_enable_all'); 363 364 actDisableAll.Caption := liswlDIsableAll; 365 actDisableAll.Hint := lisDbgAllItemDisableHint; 366 actDisableAll.ImageIndex := IDEImages.LoadImage('debugger_disable_all'); 367 368 actDeleteAll.Caption := lisDeleteAll; 369 actDeleteAll.Hint := lisDbgAllItemDeleteHint; 370 actDeleteAll.ImageIndex := IDEImages.LoadImage('menu_clean'); 371 372 actProperties.Caption:= liswlProperties; 373 actProperties.Hint := lisDbgBreakpointPropertiesHint; 374 actProperties.ImageIndex := IDEImages.LoadImage('menu_environment_options'); 375 376 actToggleCurrentEnable.Caption:= lisBtnEnabled; 377 378 actEnableAllInSrc.Caption:= lisEnableAllInSameSource; 379 actDisableAllInSrc.Caption:= lisDisableAllInSameSource; 380 actDeleteAllInSrc.Caption:= lisDeleteAllInSameSource; 381 for i := low(COL_WIDTHS) to high(COL_WIDTHS) do 382 lvBreakPoints.Column[i].Width := COL_WIDTHS[i]; 383 384 FLockActionUpdate := 0; 385end; 386 387procedure TBreakPointsDlg.BreakpointsDlgCREATE(Sender: TObject); 388begin 389 Caption:= lisMenuViewBreakPoints; 390 lvBreakPoints.Align:=alClient; 391 lvBreakPoints.Columns[0].Caption:= lisOIPState; 392 lvBreakPoints.Columns[1].Caption:= lisFilenameAddress; 393 lvBreakPoints.Columns[2].Caption:= lisLineLength; 394 lvBreakPoints.Columns[3].Caption:= lisCondition; 395 lvBreakPoints.Columns[4].Caption:= lisLazBuildABOAction; 396 lvBreakPoints.Columns[5].Caption:= lisPassCount; 397 lvBreakPoints.Columns[6].Caption:= lisGroup; 398 actShow.Caption := lisViewSource; 399 popAdd.Caption:= lisAdd; 400 actAddSourceBP.Caption := lisSourceBreakpoint; 401 actAddAddressBP.Caption := lisAddressBreakpoint; 402 actAddWatchPoint.Caption := lisWatchPoint; 403 popGroup.Caption := lisGroup; 404 actGroupSetNew.Caption := lisGroupSetNew; 405 actGroupSetNone.Caption := lisGroupSetNone; 406end; 407 408procedure TBreakPointsDlg.actEnableSelectedExecute(Sender: TObject); 409var 410 n: Integer; 411 Item: TListItem; 412begin 413 try 414 DisableAllActions; 415 for n := 0 to lvBreakPoints.Items.Count -1 do 416 begin 417 Item := lvBreakPoints.Items[n]; 418 if Item.Selected then 419 TIDEBreakPoint(Item.Data).Enabled := True; 420 end; 421 finally 422 lvBreakPointsSelectItem(nil, nil, False); 423 end; 424end; 425 426procedure TBreakPointsDlg.actGroupSetNewExecute(Sender: TObject); 427var 428 GroupName: String; 429 NewGroup: TIDEBreakPointGroup; 430begin 431 GroupName := ''; 432 if not InputQuery(Caption, lisGroupNameInput, GroupName) then Exit; 433 if GroupName = '' then 434 begin 435 if MessageDlg(Caption, lisGroupNameEmptyClearInstead, 436 mtConfirmation, mbYesNo, 0) = mrYes then Exit; 437 NewGroup := nil; 438 end 439 else begin 440 NewGroup := DebugBoss.BreakPointGroups.GetGroupByName(GroupName); 441 if NewGroup = nil then 442 begin 443 if not TIDEBreakPointGroup.CheckName(GroupName) then 444 begin 445 MessageDlg(Caption, lisGroupNameInvalid, mtError, [mbOk], 0); 446 Exit; 447 end; 448 NewGroup := TIDEBreakPointGroup(DebugBoss.BreakPointGroups.Add); 449 try 450 NewGroup.Name := GroupName; 451 except 452 NewGroup.Free; 453 raise; 454 end; 455 end 456 else if MessageDlg(Caption, Format(lisGroupAssignExisting, 457 [GroupName]), mtConfirmation, mbYesNo, 0) <> mrYes 458 then 459 Exit; 460 end; 461 462 SetGroup(NewGroup); 463end; 464 465procedure TBreakPointsDlg.actGroupSetNoneExecute(Sender: TObject); 466begin 467 SetGroup(nil); 468end; 469 470procedure TBreakPointsDlg.popSetGroupItemClick(Sender: TObject); 471var 472 Group: TIDEBreakPointGroup; 473begin 474 Group := DebugBoss.BreakPointGroups.GetGroupByName((Sender as TMenuItem).Caption); 475 if Group = nil then 476 raise Exception.CreateFmt('Group %s not found', [(Sender as TMenuItem).Caption]); 477 SetGroup(Group); 478end; 479 480procedure TBreakPointsDlg.actShowExecute(Sender: TObject); 481begin 482 JumpToCurrentBreakPoint; 483end; 484 485procedure TBreakPointsDlg.actDisableSelectedExecute(Sender: TObject); 486var 487 n: Integer; 488 Item: TListItem; 489begin 490 try 491 DisableAllActions; 492 for n := 0 to lvBreakPoints.Items.Count -1 do 493 begin 494 Item := lvBreakPoints.Items[n]; 495 if Item.Selected then 496 TIDEBreakPoint(Item.Data).Enabled := False; 497 end; 498 finally 499 lvBreakPointsSelectItem(nil, nil, False); 500 end; 501end; 502 503procedure TBreakPointsDlg.actAddSourceBPExecute(Sender: TObject); 504var 505 NewBreakpoint: TIDEBreakPoint; 506 SrcEdit: TSourceEditor; 507begin 508 SrcEdit := SourceEditorManager.GetActiveSE; 509 if SrcEdit <> nil then 510 NewBreakpoint := BreakPoints.Add(SrcEdit.FileName, SrcEdit.CurrentCursorYLine, True) 511 else 512 NewBreakpoint := BreakPoints.Add('', 0, True); 513 if DebugBoss.ShowBreakPointProperties(NewBreakpoint) = mrOk then begin 514 NewBreakpoint.EndUpdate; 515 UpdateAll; 516 end 517 else 518 ReleaseRefAndNil(NewBreakpoint); 519end; 520 521procedure TBreakPointsDlg.actAddWatchPointExecute(Sender: TObject); 522var 523 NewBreakpoint: TIDEBreakPoint; 524begin 525 NewBreakpoint := BreakPoints.Add('', wpsGlobal, wpkWrite, True); 526 if DebugBoss.ShowBreakPointProperties(NewBreakpoint) = mrOk then begin 527 NewBreakpoint.EndUpdate; 528 UpdateAll; 529 end 530 else 531 ReleaseRefAndNil(NewBreakpoint); 532end; 533 534procedure TBreakPointsDlg.actAddAddressBPExecute(Sender: TObject); 535var 536 NewBreakpoint: TIDEBreakPoint; 537begin 538 NewBreakpoint := BreakPoints.Add(0, True); 539 if DebugBoss.ShowBreakPointProperties(NewBreakpoint) = mrOk then begin 540 NewBreakpoint.EndUpdate; 541 UpdateAll; 542 end 543 else 544 ReleaseRefAndNil(NewBreakpoint); 545end; 546 547procedure TBreakPointsDlg.lvBreakPointsClick(Sender: TObject); 548begin 549 lvBreakPointsSelectItem(nil, nil, False); 550end; 551 552procedure TBreakPointsDlg.lvBreakPointsDBLCLICK(Sender: TObject); 553begin 554 lvBreakPointsSelectItem(nil, nil, False); 555 JumpToCurrentBreakPoint; 556end; 557 558procedure TBreakPointsDlg.lvBreakPointsSelectItem(Sender: TObject; Item: TListItem; 559 Selected: Boolean); 560var 561 ItemSelected: Boolean; 562 SelCanEnable, SelCanDisable: Boolean; 563 AllCanEnable, AllCanDisable: Boolean; 564 CurBreakPoint: TIDEBreakPoint; 565 i: Integer; 566begin 567 if FLockActionUpdate > 0 then exit; 568 569 ItemSelected := lvBreakPoints.Selected <> nil; 570 if ItemSelected then 571 CurBreakPoint := TIDEBreakPoint(lvBreakPoints.Selected.Data) 572 else 573 CurBreakPoint := nil; 574 SelCanEnable := False; 575 SelCanDisable := False; 576 AllCanEnable := False; 577 allCanDisable := False; 578 for i := 0 to lvBreakPoints.Items.Count - 1 do begin 579 if lvBreakPoints.Items[i].Data = nil then 580 continue; 581 if lvBreakPoints.Items[i].Selected then begin 582 SelCanEnable := SelCanEnable or not TIDEBreakPoint(lvBreakPoints.Items[i].Data).Enabled; 583 SelCanDisable := SelCanDisable or TIDEBreakPoint(lvBreakPoints.Items[i].Data).Enabled; 584 end; 585 AllCanEnable := AllCanEnable or not TIDEBreakPoint(lvBreakPoints.Items[i].Data).Enabled; 586 AllCanDisable := AllCanDisable or TIDEBreakPoint(lvBreakPoints.Items[i].Data).Enabled; 587 end; 588 589 actToggleCurrentEnable.Enabled := ItemSelected; 590 actToggleCurrentEnable.Checked := (CurBreakPoint <> nil) and CurBreakPoint.Enabled; 591 592 actEnableSelected.Enabled := SelCanEnable; 593 actDisableSelected.Enabled := SelCanDisable; 594 actDeleteSelected.Enabled := ItemSelected; 595 596 actEnableAll.Enabled := AllCanEnable; 597 actDisableAll.Enabled := AllCanDisable; 598 actDeleteAll.Enabled := lvBreakPoints.Items.Count > 0; 599 600 actEnableAllInSrc.Enabled := ItemSelected; 601 actDisableAllInSrc.Enabled := ItemSelected; 602 actDeleteAllInSrc.Enabled := ItemSelected; 603 604 actProperties.Enabled := ItemSelected; 605 actShow.Enabled := ItemSelected; 606 607 popGroup.Enabled := ItemSelected; 608 actGroupSetNew.Enabled := ItemSelected; 609 actGroupSetNone.Enabled := ItemSelected; 610end; 611 612procedure TBreakPointsDlg.mnuPopupPopup(Sender: TObject); 613var 614 i: Integer; 615 MenuItem: TMenuItem; 616begin 617 for i := popGroup.Count - 1 downto popGroup.IndexOf(popGroupSep) +1 do 618 popGroup.Items[i].Free; 619 for i := 0 to DebugBoss.BreakPointGroups.Count - 1 do 620 begin 621 MenuItem := TMenuItem.Create(popGroup); 622 MenuItem.Caption := DebugBoss.BreakPointGroups[i].Name; 623 MenuItem.OnClick := @popSetGroupItemClick; 624 popGroup.Add(MenuItem); 625 end; 626 popGroupSep.Visible := DebugBoss.BreakPointGroups.Count <> 0; 627end; 628 629procedure TBreakPointsDlg.popDeleteAllSameSourceCLICK(Sender: TObject); 630var 631 n: Integer; 632 Item: TListItem; 633 CurItem: TListItem; 634 CurBreakPoint: TIDEBreakPoint; 635 Filename: String; 636begin 637 try 638 DisableAllActions; 639 CurItem:=lvBreakPoints.Selected; 640 if (CurItem=nil) then exit; 641 Filename:=TIDEBreakpoint(CurItem.Data).Source; 642 if MessageDlg(lisDeleteAllBreakpoints, 643 Format(lisDeleteAllBreakpoints2, [Filename]), 644 mtConfirmation,[mbYes,mbCancel],0)<>mrYes 645 then exit; 646 for n := lvBreakPoints.Items.Count - 1 downto 0 do 647 begin 648 Item := lvBreakPoints.Items[n]; 649 CurBreakPoint:=TIDEBreakPoint(Item.Data); 650 if CompareFilenames(CurBreakPoint.Source,Filename)=0 651 then ReleaseRefAndNil(CurBreakPoint); 652 end; 653 finally 654 lvBreakPointsSelectItem(nil, nil, False); 655 end; 656end; 657 658procedure TBreakPointsDlg.popDisableAllSameSourceCLICK(Sender: TObject); 659var 660 n: Integer; 661 Item: TListItem; 662 CurItem: TListItem; 663 CurBreakPoint: TIDEBreakPoint; 664 Filename: String; 665begin 666 try 667 DisableAllActions; 668 CurItem:=lvBreakPoints.Selected; 669 if (CurItem=nil) then exit; 670 Filename:=TIDEBreakpoint(CurItem.Data).Source; 671 for n := 0 to lvBreakPoints.Items.Count - 1 do 672 begin 673 Item := lvBreakPoints.Items[n]; 674 CurBreakPoint:=TIDEBreakPoint(Item.Data); 675 if CompareFilenames(CurBreakPoint.Source,Filename)=0 676 then CurBreakPoint.Enabled := False; 677 end; 678 finally 679 lvBreakPointsSelectItem(nil, nil, False); 680 end; 681end; 682 683procedure TBreakPointsDlg.popEnableAllSameSourceCLICK(Sender: TObject); 684var 685 n: Integer; 686 Item: TListItem; 687 CurItem: TListItem; 688 CurBreakPoint: TIDEBreakPoint; 689 Filename: String; 690begin 691 try 692 DisableAllActions; 693 CurItem:=lvBreakPoints.Selected; 694 if (CurItem=nil) then exit; 695 Filename:=TIDEBreakpoint(CurItem.Data).Source; 696 for n := 0 to lvBreakPoints.Items.Count - 1 do 697 begin 698 Item := lvBreakPoints.Items[n]; 699 CurBreakPoint:=TIDEBreakPoint(Item.Data); 700 if CompareFilenames(CurBreakPoint.Source,Filename)=0 701 then CurBreakPoint.Enabled := True; 702 end; 703 finally 704 lvBreakPointsSelectItem(nil, nil, False); 705 end; 706end; 707 708procedure TBreakPointsDlg.popDeleteAllClick(Sender: TObject); 709var 710 n: Integer; 711begin 712 try 713 DisableAllActions; 714 if MessageDlg(lisDeleteAllBreakpoints, 715 lisDeleteAllBreakpoints, 716 mtConfirmation,[mbYes,mbCancel],0)<>mrYes 717 then exit; 718 lvBreakPoints.BeginUpdate; 719 try 720 for n := lvBreakPoints.Items.Count - 1 downto 0 do 721 TIDEBreakPoint(lvBreakPoints.Items[n].Data).ReleaseReference; 722 finally 723 lvBreakPoints.EndUpdate; 724 end; 725 finally 726 lvBreakPointsSelectItem(nil, nil, False); 727 end; 728end; 729 730procedure TBreakPointsDlg.popDeleteClick(Sender: TObject); 731begin 732 try 733 DisableAllActions; 734 DeleteSelectedBreakpoints; 735 finally 736 lvBreakPointsSelectItem(nil, nil, False); 737 end; 738end; 739 740procedure TBreakPointsDlg.popDisableAllClick(Sender: TObject); 741var 742 n: Integer; 743 Item: TListItem; 744begin 745 try 746 DisableAllActions; 747 for n := 0 to lvBreakPoints.Items.Count - 1 do 748 begin 749 Item := lvBreakPoints.Items[n]; 750 if Item.Data <> nil 751 then TIDEBreakPoint(Item.Data).Enabled := False; 752 end; 753 finally 754 lvBreakPointsSelectItem(nil, nil, False); 755 end; 756end; 757 758procedure TBreakPointsDlg.popEnableAllClick(Sender: TObject); 759var 760 n: Integer; 761 Item: TListItem; 762begin 763 try 764 DisableAllActions; 765 for n := 0 to lvBreakPoints.Items.Count - 1 do 766 begin 767 Item := lvBreakPoints.Items[n]; 768 if Item.Data <> nil 769 then TIDEBreakPoint(Item.Data).Enabled := True; 770 end; 771 finally 772 lvBreakPointsSelectItem(nil, nil, False); 773 end; 774end; 775 776procedure TBreakPointsDlg.popEnabledClick(Sender: TObject); 777var 778 n: Integer; 779 Item: TListItem; 780 Enable: Boolean; 781begin 782 try 783 DisableAllActions; 784 Item:=lvBreakPoints.Selected; 785 if (Item=nil) then exit; 786 787 Enable := not TIDEBreakPoint(Item.Data).Enabled; 788 789 if lvBreakPoints.SelCount > 1 790 then begin 791 for n := 0 to lvBreakPoints.Items.Count -1 do 792 begin 793 Item := lvBreakPoints.Items[n]; 794 if Item.Selected then 795 TIDEBreakPoint(Item.Data).Enabled := Enable; 796 end; 797 end 798 else begin 799 TIDEBreakPoint(Item.Data).Enabled:= Enable; 800 end; 801 finally 802 lvBreakPointsSelectItem(nil, nil, False); 803 end; 804end; 805 806procedure TBreakPointsDlg.popPropertiesClick(Sender: TObject); 807begin 808 try 809 DisableAllActions; 810 ShowProperties; 811 finally 812 lvBreakPointsSelectItem(nil, nil, False); 813 end; 814end; 815 816procedure TBreakPointsDlg.DoEndUpdate; 817begin 818 inherited DoEndUpdate; 819 if bpdsItemsNeedUpdate in FStates then UpdateAll; 820 lvBreakPointsSelectItem(nil, nil, False); 821end; 822 823procedure TBreakPointsDlg.DisableAllActions; 824var 825 i: Integer; 826begin 827 for i := 0 to ActionList1.ActionCount - 1 do 828 (ActionList1.Actions[i] as TAction).Enabled := False; 829 actAddSourceBP.Enabled := True; 830 actAddAddressBP.Enabled := True; 831 actAddWatchPoint.Enabled := True; 832end; 833 834function TBreakPointsDlg.ColSizeGetter(AColId: Integer; var ASize: Integer): Boolean; 835begin 836 if (AColId - 1 >= 0) and (AColId - 1 < lvBreakPoints.ColumnCount) then begin 837 ASize := lvBreakPoints.Column[AColId - 1].Width; 838 Result := ASize <> COL_WIDTHS[AColId - 1]; 839 end 840 else 841 Result := False; 842end; 843 844procedure TBreakPointsDlg.ColSizeSetter(AColId: Integer; ASize: Integer); 845begin 846 case AColId of 847 COL_BREAK_STATE: lvBreakPoints.Column[0].Width := ASize; 848 COL_BREAK_FILE: lvBreakPoints.Column[1].Width := ASize; 849 COL_BREAK_LINE: lvBreakPoints.Column[2].Width := ASize; 850 COL_BREAK_CONDITION: lvBreakPoints.Column[3].Width := ASize; 851 COL_BREAK_ACTION: lvBreakPoints.Column[4].Width := ASize; 852 COL_BREAK_PASS: lvBreakPoints.Column[5].Width := ASize; 853 COL_BREAK_GROUP: lvBreakPoints.Column[6].Width := ASize; 854 end; 855end; 856 857procedure TBreakPointsDlg.UpdateItem(const AnItem: TListItem; 858 const ABreakpoint: TIDEBreakPoint); 859var 860 s, Filename: String; 861begin 862 // Filename/Address 863 // Line/Length 864 // Condition 865 // Action 866 // Pass Count 867 // Group 868 869 // state 870 AnItem.Caption := GetBreakPointStateDescription(ABreakpoint); 871 AnItem.ImageIndex := GetBreakPointImageIndex(ABreakpoint); 872 873 // filename/address 874 case ABreakpoint.Kind of 875 bpkSource: 876 begin 877 Filename:=ABreakpoint.Source; 878 if BaseDirectory<>'' then 879 Filename:=CreateRelativePath(Filename,BaseDirectory); 880 AnItem.SubItems[0] := Filename; 881 // line 882 if ABreakpoint.Line > 0 883 then AnItem.SubItems[1] := IntToStr(ABreakpoint.Line) 884 else AnItem.SubItems[1] := ''; 885 end; 886 bpkAddress: 887 begin 888 // todo: how to define digits count? 8 or 16 depends on gdb pointer size for platform 889 AnItem.SubItems[0] := '$' + IntToHex(ABreakpoint.Address, 8); 890 end; 891 bpkData: 892 begin 893 AnItem.SubItems[0] := ABreakpoint.WatchData; 894 case ABreakpoint.WatchScope of 895 wpsGlobal: s:= lisWatchScopeGlobal; 896 wpsLocal: s:= lisWatchScopeLocal; 897 else s := ''; 898 end; 899 s := s +' / '; 900 case ABreakpoint.WatchKind of 901 wpkRead: s := s + lisWatchKindRead; 902 wpkReadWrite: s := s + lisWatchKindReadWrite; 903 wpkWrite: s := s + lisWatchKindWrite; 904 end; 905 AnItem.SubItems[1] := s; 906 end; 907 end; 908 909 // expression 910 AnItem.SubItems[2] := ABreakpoint.Expression; 911 912 // actions 913 AnItem.SubItems[3] := GetBreakPointActionsDescription(ABreakpoint); 914 915 // hitcount 916 AnItem.SubItems[4] := IntToStr(ABreakpoint.HitCount); 917 918 // group 919 if ABreakpoint.Group = nil 920 then AnItem.SubItems[5] := '' 921 else AnItem.SubItems[5] := ABreakpoint.Group.Name; 922 923 lvBreakPointsSelectItem(nil, nil, False); 924end; 925 926procedure TBreakPointsDlg.UpdateAll; 927var 928 i: Integer; 929 CurItem: TListItem; 930begin 931 if UpdateCount>0 then begin 932 Include(FStates,bpdsItemsNeedUpdate); 933 exit; 934 end; 935 Exclude(FStates,bpdsItemsNeedUpdate); 936 inc(FLockActionUpdate); 937 for i:=0 to lvBreakPoints.Items.Count-1 do begin 938 CurItem:=lvBreakPoints.Items[i]; 939 UpdateItem(CurItem,TIDEBreakPoint(CurItem.Data)); 940 end; 941 dec(FLockActionUpdate); 942 lvBreakPointsSelectItem(nil, nil, False); 943end; 944 945procedure TBreakPointsDlg.DeleteSelectedBreakpoints; 946var 947 Item: TListItem; 948 CurBreakPoint: TIDEBreakPoint; 949 Msg: String; 950 List: TList; 951 n, Idx: Integer; 952begin 953 Idx := lvBreakPoints.ItemIndex; 954 Item:=lvBreakPoints.Selected; 955 if Item = nil then exit; 956 957 if lvBreakPoints.SelCount = 1 then 958 begin 959 CurBreakPoint:=TIDEBreakPoint(Item.Data); 960 case CurBreakPoint.Kind of 961 bpkSource: Msg := Format(lisDeleteBreakpointAtLine, 962 [LineEnding, CurBreakPoint.Source, CurBreakPoint.Line]); 963 bpkAddress: Msg := Format(lisDeleteBreakpointForAddress, ['$' + IntToHex(CurBreakPoint.Address, 8)]); 964 bpkData: Msg := Format(lisDeleteBreakpointForWatch, [CurBreakPoint.WatchData]); 965 end; 966 end 967 else 968 Msg := lisDeleteAllSelectedBreakpoints; 969 if MessageDlg(Msg, mtConfirmation, [mbYes,mbCancel],0) <> mrYes then exit; 970 971 if lvBreakPoints.SelCount = 1 972 then begin 973 TBaseBreakPoint(Item.Data).ReleaseReference; 974 end 975 else begin 976 List := TList.Create; 977 for n := 0 to lvBreakPoints.Items.Count - 1 do 978 begin 979 Item := lvBreakPoints.Items[n]; 980 if Item.Selected 981 then List.Add(Item.Data); 982 end; 983 984 lvBreakPoints.BeginUpdate; 985 try 986 for n := 0 to List.Count - 1 do 987 TBaseBreakPoint(List[n]).ReleaseReference; 988 finally 989 lvBreakPoints.EndUpdate; 990 end; 991 List.Free; 992 end; 993 if Idx > lvBreakPoints.Items.Count - 1 then 994 Idx := lvBreakPoints.Items.Count - 1; 995 if Idx >= 0 then 996 lvBreakPoints.ItemIndex := Idx; 997end; 998 999procedure TBreakPointsDlg.JumpToCurrentBreakPoint; 1000var 1001 CurItem: TListItem; 1002 CurBreakPoint: TIDEBreakPoint; 1003begin 1004 CurItem:=lvBreakPoints.Selected; 1005 if CurItem=nil then exit; 1006 CurBreakPoint:=TIDEBreakPoint(CurItem.Data); 1007 if CurBreakPoint.Kind = bpkSource then 1008 MainIDE.DoJumpToSourcePosition(CurBreakPoint.Source, 0, CurBreakPoint.Line, 0, 1009 [jfAddJumpPoint, jfFocusEditor, jfMarkLine, jfSearchVirtualFullPath]); 1010end; 1011 1012procedure TBreakPointsDlg.ShowProperties; 1013var 1014 Item: TListItem; 1015 CurBreakPoint: TIDEBreakPoint; 1016begin 1017 Item:=lvBreakPoints.Selected; 1018 if Item = nil then exit; 1019 1020 CurBreakPoint:=TIDEBreakPoint(Item.Data); 1021 1022 DebugBoss.ShowBreakPointProperties(CurBreakPoint); 1023end; 1024 1025procedure TBreakPointsDlg.DoBreakPointsChanged; 1026var 1027 i: Integer; 1028begin 1029 lvBreakPoints.Items.Clear; 1030 if BreakPoints <> nil 1031 then begin 1032 for i:=0 to BreakPoints.Count-1 do 1033 BreakPointUpdate(BreakPoints, BreakPoints.Items[i]); 1034 end; 1035end; 1036 1037procedure TBreakPointsDlg.DoBeginUpdate; 1038begin 1039 inherited DoBeginUpdate; 1040 DisableAllActions; 1041end; 1042 1043initialization 1044 1045 BreakPointDlgWindowCreator := IDEWindowCreators.Add(DebugDialogNames[ddtBreakpoints]); 1046 BreakPointDlgWindowCreator.OnCreateFormProc := @CreateDebugDialog; 1047 BreakPointDlgWindowCreator.OnSetDividerSize := @BreakPointDlgColSizeSetter; 1048 BreakPointDlgWindowCreator.OnGetDividerSize := @BreakPointDlgColSizeGetter; 1049 BreakPointDlgWindowCreator.DividerTemplate.Add('ColumnBreakState', COL_BREAK_STATE, @drsColWidthState); 1050 BreakPointDlgWindowCreator.DividerTemplate.Add('ColumnBreakFile', COL_BREAK_FILE, @drsBreakPointColWidthFile); 1051 BreakPointDlgWindowCreator.DividerTemplate.Add('ColumnBreakLine', COL_BREAK_LINE, @drsBreakPointColWidthLine); 1052 BreakPointDlgWindowCreator.DividerTemplate.Add('ColumnBreakCondition', COL_BREAK_CONDITION, @drsBreakPointColWidthCondition); 1053 BreakPointDlgWindowCreator.DividerTemplate.Add('ColumnBreakAction', COL_BREAK_ACTION, @drsBreakPointColWidthAction); 1054 BreakPointDlgWindowCreator.DividerTemplate.Add('ColumnBreakPassCnt', COL_BREAK_PASS, @drsBreakPointColWidthPassCount); 1055 BreakPointDlgWindowCreator.DividerTemplate.Add('ColumnBreakGroup', COL_BREAK_GROUP, @drsBreakPointColWidthGroup); 1056 BreakPointDlgWindowCreator.CreateSimpleLayout; 1057 1058end. 1059 1060