* Added breakpont properties dialog. Modified patch by Benito van der Zander (issue #12882)

git-svn-id: trunk@18115 -
This commit is contained in:
marc 2009-01-04 19:57:56 +00:00
parent 8d632ac72b
commit c569ccca33
13 changed files with 923 additions and 212 deletions

3
.gitattributes vendored
View File

@ -1601,6 +1601,9 @@ debugger/assemblerdlg.pp svneol=native#text/pascal
debugger/breakpointsdlg.lfm svneol=native#text/plain
debugger/breakpointsdlg.lrs svneol=native#text/pascal
debugger/breakpointsdlg.pp svneol=native#text/pascal
debugger/breakpropertydlg.lfm svneol=native#text/pascal
debugger/breakpropertydlg.lrs svneol=native#text/pascal
debugger/breakpropertydlg.pas svneol=native#text/pascal
debugger/callstackdlg.lfm svneol=native#text/plain
debugger/callstackdlg.lrs svneol=native#text/pascal
debugger/callstackdlg.pp svneol=native#text/pascal

View File

@ -123,7 +123,7 @@ function GetBreakPointActionsDescription(ABreakpoint: TBaseBreakpoint): string;
implementation
uses
LazarusIDEStrConsts;
LazarusIDEStrConsts, BaseDebugManager;
function GetBreakPointStateDescription(ABreakpoint: TBaseBreakpoint): string;
const
// enabled valid
@ -634,8 +634,16 @@ begin
end;
procedure TBreakPointsDlg.ShowProperties;
var
Item: TListItem;
CurBreakPoint: TIDEBreakPoint;
begin
ShowMessage(lisNotImplementedYet2);
Item:=lvBreakPoints.Selected;
if Item = nil then exit;
CurBreakPoint:=TIDEBreakPoint(Item.Data);
DebugBoss.ShowBreakPointProperties(CurBreakPoint);
end;

View File

@ -0,0 +1,310 @@
inherited BreakPropertyDlg: TBreakPropertyDlg
Left = 329
Height = 367
Top = 288
Width = 387
HorzScrollBar.Page = 382
HorzScrollBar.Range = 392
HorzScrollBar.Visible = True
VertScrollBar.Page = 188
VertScrollBar.Range = 209
VertScrollBar.Visible = True
AutoScroll = False
Caption = 'Breakpoint Properties'
ClientHeight = 367
ClientWidth = 387
object lblFileName: TLabel[0]
AnchorSideTop.Side = asrCenter
Left = 8
Height = 13
Top = 14
Width = 55
Caption = 'Filename:'
ParentColor = False
end
object lblLine: TLabel[1]
AnchorSideLeft.Control = lblFileName
AnchorSideTop.Side = asrCenter
Left = 8
Height = 13
Top = 41
Width = 28
Caption = 'Line:'
ParentColor = False
end
object lblCondition: TLabel[2]
AnchorSideLeft.Control = lblFileName
AnchorSideTop.Side = asrCenter
Left = 8
Height = 13
Top = 68
Width = 57
Caption = 'Condition:'
ParentColor = False
end
object lblHitCount: TLabel[3]
AnchorSideLeft.Control = lblFileName
AnchorSideTop.Side = asrCenter
Left = 8
Height = 13
Top = 95
Width = 61
Caption = 'Hitcounter:'
ParentColor = False
end
object lblGroup: TLabel[4]
AnchorSideLeft.Control = lblFileName
AnchorSideTop.Side = asrCenter
Left = 8
Height = 13
Top = 152
Width = 38
Caption = 'Group:'
ParentColor = False
end
object lblAutoContinue: TLabel[5]
Left = 9
Height = 13
Top = 124
Width = 106
Caption = 'Auto continue (ms)'
ParentColor = False
end
object edtAutocontinueMS: TEdit[6]
AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom
Left = 137
Height = 23
Top = 117
Width = 251
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Around = 4
TabOrder = 0
Text = 'edtAutocontinueMS'
end
object edtCounter: TEdit[7]
AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom
Left = 137
Height = 23
Top = 90
Width = 251
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Top = 4
BorderSpacing.Around = 4
TabOrder = 1
Text = 'edtCounter'
end
object edtCondition: TEdit[8]
AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom
Left = 137
Height = 23
Top = 63
Width = 251
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Top = 4
BorderSpacing.Around = 4
TabOrder = 2
Text = 'edtCondition'
end
object edtLine: TEdit[9]
AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom
Left = 137
Height = 23
Top = 36
Width = 251
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Top = 4
BorderSpacing.Around = 4
Color = clBtnFace
ReadOnly = True
TabOrder = 3
Text = 'edtLine'
end
object edtFilename: TEdit[10]
AnchorSideTop.Side = asrCenter
AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom
Left = 137
Height = 24
Top = 8
Width = 247
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Right = 4
BorderSpacing.Around = 4
Color = clBtnFace
ReadOnly = True
TabOrder = 4
Text = 'edtFilename'
end
object cmbGroup: TComboBox[11]
AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom
Left = 137
Height = 25
Top = 144
Width = 251
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Around = 4
TabOrder = 5
Text = 'cmbGroup'
end
object gbActions: TGroupBox[12]
AnchorSideLeft.Control = Owner
AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom
Left = 4
Height = 149
Top = 176
Width = 384
Anchors = [akTop, akLeft, akRight]
BorderSpacing.Around = 4
Caption = 'Actions'
ClientHeight = 132
ClientWidth = 380
TabOrder = 6
object chkActionBreak: TCheckBox
Left = 6
Height = 20
Top = 5
Width = 56
Caption = 'Break'
TabOrder = 0
end
object chkEnableGroups: TCheckBox
Left = 6
Height = 20
Top = 29
Width = 101
Caption = 'Enable goups'
TabOrder = 1
end
object chkDisableGroups: TCheckBox
Left = 6
Height = 20
Top = 53
Width = 108
Caption = 'Disable groups'
TabOrder = 2
end
object edtEnableGroups: TEditButton
Left = 130
Height = 23
Top = 29
Width = 221
Anchors = [akTop, akLeft, akRight]
ButtonWidth = 23
Enabled = False
NumGlyphs = 1
OnButtonClick = edtEnableGroupsButtonClick
TabOrder = 3
end
object edtDisableGroups: TEditButton
Left = 130
Height = 23
Top = 53
Width = 221
Anchors = [akTop, akLeft, akRight]
ButtonWidth = 23
Enabled = False
NumGlyphs = 1
OnButtonClick = edtDisableGroupsButtonClick
TabOrder = 4
end
object chkEvalExpression: TCheckBox
Left = 6
Height = 20
Top = 77
Width = 113
Caption = 'Eval expression'
Enabled = False
TabOrder = 5
end
object chkLogMessage: TCheckBox
Left = 6
Height = 20
Top = 101
Width = 98
Caption = 'Log message'
Enabled = False
TabOrder = 6
end
object edtEvalExpression: TEdit
Left = 130
Height = 23
Top = 77
Width = 244
Anchors = [akTop, akLeft, akRight]
Enabled = False
TabOrder = 7
Text = 'edtEvalExpression'
end
object edtLogMessage: TEdit
Left = 130
Height = 23
Top = 101
Width = 244
Anchors = [akTop, akLeft, akRight]
Enabled = False
TabOrder = 8
Text = 'Edit1'
end
end
object btnHelp: TBitBtn[13]
AnchorSideLeft.Control = Owner
AnchorSideBottom.Control = Owner
AnchorSideBottom.Side = asrBottom
Left = 6
Height = 26
Top = 335
Width = 35
Anchors = [akLeft, akBottom]
AutoSize = True
BorderSpacing.Around = 6
Caption = 'Help'
NumGlyphs = 0
OnClick = btnHelpClick
TabOrder = 7
end
object btnOK: TBitBtn[14]
AnchorSideRight.Control = btnCancel
AnchorSideBottom.Control = Owner
AnchorSideBottom.Side = asrBottom
Left = 304
Height = 26
Top = 335
Width = 27
Anchors = [akRight, akBottom]
AutoSize = True
BorderSpacing.Around = 6
Caption = 'OK'
Default = True
ModalResult = 1
NumGlyphs = 0
OnClick = btnOKClick
TabOrder = 8
end
object btnCancel: TBitBtn[15]
AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom
AnchorSideBottom.Control = Owner
AnchorSideBottom.Side = asrBottom
Left = 337
Height = 26
Top = 335
Width = 49
Anchors = [akRight, akBottom]
AutoSize = True
BorderSpacing.Around = 6
Cancel = True
Caption = 'Cancel'
ModalResult = 2
NumGlyphs = 0
TabOrder = 9
end
end

View File

@ -0,0 +1,96 @@
{ This is an automatically generated lazarus resource file }
LazarusResources.Add('TBreakPropertyDlg','FORMDATA',[
'TPF0'#241#17'TBreakPropertyDlg'#16'BreakPropertyDlg'#4'Left'#3'I'#1#6'Height'
+#3'o'#1#3'Top'#3' '#1#5'Width'#3#131#1#18'HorzScrollBar.Page'#3'~'#1#19'Horz'
+'ScrollBar.Range'#3#136#1#21'HorzScrollBar.Visible'#9#18'VertScrollBar.Page'
+#3#188#0#19'VertScrollBar.Range'#3#209#0#21'VertScrollBar.Visible'#9#10'Auto'
+'Scroll'#8#7'Caption'#6#21'Breakpoint Properties'#12'ClientHeight'#3'o'#1#11
+'ClientWidth'#3#131#1#0#242#2#0#6'TLabel'#11'lblFileName'#18'AnchorSideTop.S'
+'ide'#7#9'asrCenter'#4'Left'#2#8#6'Height'#2#13#3'Top'#2#14#5'Width'#2'7'#7
+'Caption'#6#9'Filename:'#11'ParentColor'#8#0#0#242#2#1#6'TLabel'#7'lblLine'
+#22'AnchorSideLeft.Control'#7#11'lblFileName'#18'AnchorSideTop.Side'#7#9'asr'
+'Center'#4'Left'#2#8#6'Height'#2#13#3'Top'#2')'#5'Width'#2#28#7'Caption'#6#5
+'Line:'#11'ParentColor'#8#0#0#242#2#2#6'TLabel'#12'lblCondition'#22'AnchorSi'
+'deLeft.Control'#7#11'lblFileName'#18'AnchorSideTop.Side'#7#9'asrCenter'#4'L'
+'eft'#2#8#6'Height'#2#13#3'Top'#2'D'#5'Width'#2'9'#7'Caption'#6#10'Condition'
+':'#11'ParentColor'#8#0#0#242#2#3#6'TLabel'#11'lblHitCount'#22'AnchorSideLef'
+'t.Control'#7#11'lblFileName'#18'AnchorSideTop.Side'#7#9'asrCenter'#4'Left'#2
+#8#6'Height'#2#13#3'Top'#2'_'#5'Width'#2'='#7'Caption'#6#11'Hitcounter:'#11
+'ParentColor'#8#0#0#242#2#4#6'TLabel'#8'lblGroup'#22'AnchorSideLeft.Control'
+#7#11'lblFileName'#18'AnchorSideTop.Side'#7#9'asrCenter'#4'Left'#2#8#6'Heigh'
+'t'#2#13#3'Top'#3#152#0#5'Width'#2'&'#7'Caption'#6#6'Group:'#11'ParentColor'
+#8#0#0#242#2#5#6'TLabel'#15'lblAutoContinue'#4'Left'#2#9#6'Height'#2#13#3'To'
+'p'#2'|'#5'Width'#2'j'#7'Caption'#6#18'Auto continue (ms)'#11'ParentColor'#8
+#0#0#242#2#6#5'TEdit'#17'edtAutocontinueMS'#23'AnchorSideRight.Control'#7#5
+'Owner'#20'AnchorSideRight.Side'#7#9'asrBottom'#4'Left'#3#137#0#6'Height'#2
+#23#3'Top'#2'u'#5'Width'#3#251#0#7'Anchors'#11#5'akTop'#6'akLeft'#7'akRight'
+#0#20'BorderSpacing.Around'#2#4#8'TabOrder'#2#0#4'Text'#6#17'edtAutocontinue'
+'MS'#0#0#242#2#7#5'TEdit'#10'edtCounter'#18'AnchorSideTop.Side'#7#9'asrBotto'
+'m'#23'AnchorSideRight.Control'#7#5'Owner'#20'AnchorSideRight.Side'#7#9'asrB'
+'ottom'#4'Left'#3#137#0#6'Height'#2#23#3'Top'#2'Z'#5'Width'#3#251#0#7'Anchor'
+'s'#11#5'akTop'#6'akLeft'#7'akRight'#0#17'BorderSpacing.Top'#2#4#20'BorderSp'
+'acing.Around'#2#4#8'TabOrder'#2#1#4'Text'#6#10'edtCounter'#0#0#242#2#8#5'TE'
+'dit'#12'edtCondition'#18'AnchorSideTop.Side'#7#9'asrBottom'#23'AnchorSideRi'
+'ght.Control'#7#5'Owner'#20'AnchorSideRight.Side'#7#9'asrBottom'#4'Left'#3
+#137#0#6'Height'#2#23#3'Top'#2'?'#5'Width'#3#251#0#7'Anchors'#11#5'akTop'#6
+'akLeft'#7'akRight'#0#17'BorderSpacing.Top'#2#4#20'BorderSpacing.Around'#2#4
+#8'TabOrder'#2#2#4'Text'#6#12'edtCondition'#0#0#242#2#9#5'TEdit'#7'edtLine'
+#18'AnchorSideTop.Side'#7#9'asrBottom'#23'AnchorSideRight.Control'#7#5'Owner'
+#20'AnchorSideRight.Side'#7#9'asrBottom'#4'Left'#3#137#0#6'Height'#2#23#3'To'
+'p'#2'$'#5'Width'#3#251#0#7'Anchors'#11#5'akTop'#6'akLeft'#7'akRight'#0#17'B'
+'orderSpacing.Top'#2#4#20'BorderSpacing.Around'#2#4#5'Color'#7#9'clBtnFace'#8
+'ReadOnly'#9#8'TabOrder'#2#3#4'Text'#6#7'edtLine'#0#0#242#2#10#5'TEdit'#11'e'
+'dtFilename'#18'AnchorSideTop.Side'#7#9'asrCenter'#23'AnchorSideRight.Contro'
+'l'#7#5'Owner'#20'AnchorSideRight.Side'#7#9'asrBottom'#4'Left'#3#137#0#6'Hei'
+'ght'#2#24#3'Top'#2#8#5'Width'#3#247#0#7'Anchors'#11#5'akTop'#6'akLeft'#7'ak'
+'Right'#0#19'BorderSpacing.Right'#2#4#20'BorderSpacing.Around'#2#4#5'Color'#7
+#9'clBtnFace'#8'ReadOnly'#9#8'TabOrder'#2#4#4'Text'#6#11'edtFilename'#0#0#242
+#2#11#9'TComboBox'#8'cmbGroup'#23'AnchorSideRight.Control'#7#5'Owner'#20'Anc'
+'horSideRight.Side'#7#9'asrBottom'#4'Left'#3#137#0#6'Height'#2#25#3'Top'#3
+#144#0#5'Width'#3#251#0#7'Anchors'#11#5'akTop'#6'akLeft'#7'akRight'#0#20'Bor'
+'derSpacing.Around'#2#4#8'TabOrder'#2#5#4'Text'#6#8'cmbGroup'#0#0#242#2#12#9
+'TGroupBox'#9'gbActions'#22'AnchorSideLeft.Control'#7#5'Owner'#23'AnchorSide'
+'Right.Control'#7#5'Owner'#20'AnchorSideRight.Side'#7#9'asrBottom'#4'Left'#2
+#4#6'Height'#3#149#0#3'Top'#3#176#0#5'Width'#3#128#1#7'Anchors'#11#5'akTop'#6
+'akLeft'#7'akRight'#0#20'BorderSpacing.Around'#2#4#7'Caption'#6#7'Actions'#12
+'ClientHeight'#3#132#0#11'ClientWidth'#3'|'#1#8'TabOrder'#2#6#0#9'TCheckBox'
+#14'chkActionBreak'#4'Left'#2#6#6'Height'#2#20#3'Top'#2#5#5'Width'#2'8'#7'Ca'
+'ption'#6#5'Break'#8'TabOrder'#2#0#0#0#9'TCheckBox'#15'chkEnableGroups'#4'Le'
+'ft'#2#6#6'Height'#2#20#3'Top'#2#29#5'Width'#2'e'#7'Caption'#6#12'Enable gou'
+'ps'#8'TabOrder'#2#1#0#0#9'TCheckBox'#16'chkDisableGroups'#4'Left'#2#6#6'Hei'
+'ght'#2#20#3'Top'#2'5'#5'Width'#2'l'#7'Caption'#6#14'Disable groups'#8'TabOr'
+'der'#2#2#0#0#11'TEditButton'#15'edtEnableGroups'#4'Left'#3#130#0#6'Height'#2
+#23#3'Top'#2#29#5'Width'#3#221#0#7'Anchors'#11#5'akTop'#6'akLeft'#7'akRight'
+#0#11'ButtonWidth'#2#23#7'Enabled'#8#9'NumGlyphs'#2#1#13'OnButtonClick'#7#26
+'edtEnableGroupsButtonClick'#8'TabOrder'#2#3#0#0#11'TEditButton'#16'edtDisab'
+'leGroups'#4'Left'#3#130#0#6'Height'#2#23#3'Top'#2'5'#5'Width'#3#221#0#7'Anc'
,'hors'#11#5'akTop'#6'akLeft'#7'akRight'#0#11'ButtonWidth'#2#23#7'Enabled'#8#9
+'NumGlyphs'#2#1#13'OnButtonClick'#7#27'edtDisableGroupsButtonClick'#8'TabOrd'
+'er'#2#4#0#0#9'TCheckBox'#17'chkEvalExpression'#4'Left'#2#6#6'Height'#2#20#3
+'Top'#2'M'#5'Width'#2'q'#7'Caption'#6#15'Eval expression'#7'Enabled'#8#8'Tab'
+'Order'#2#5#0#0#9'TCheckBox'#13'chkLogMessage'#4'Left'#2#6#6'Height'#2#20#3
+'Top'#2'e'#5'Width'#2'b'#7'Caption'#6#11'Log message'#7'Enabled'#8#8'TabOrde'
+'r'#2#6#0#0#5'TEdit'#17'edtEvalExpression'#4'Left'#3#130#0#6'Height'#2#23#3
+'Top'#2'M'#5'Width'#3#244#0#7'Anchors'#11#5'akTop'#6'akLeft'#7'akRight'#0#7
+'Enabled'#8#8'TabOrder'#2#7#4'Text'#6#17'edtEvalExpression'#0#0#5'TEdit'#13
+'edtLogMessage'#4'Left'#3#130#0#6'Height'#2#23#3'Top'#2'e'#5'Width'#3#244#0#7
+'Anchors'#11#5'akTop'#6'akLeft'#7'akRight'#0#7'Enabled'#8#8'TabOrder'#2#8#4
+'Text'#6#5'Edit1'#0#0#0#242#2#13#7'TBitBtn'#7'btnHelp'#22'AnchorSideLeft.Con'
+'trol'#7#5'Owner'#24'AnchorSideBottom.Control'#7#5'Owner'#21'AnchorSideBotto'
+'m.Side'#7#9'asrBottom'#4'Left'#2#6#6'Height'#2#26#3'Top'#3'O'#1#5'Width'#2
+'#'#7'Anchors'#11#6'akLeft'#8'akBottom'#0#8'AutoSize'#9#20'BorderSpacing.Aro'
+'und'#2#6#7'Caption'#6#4'Help'#9'NumGlyphs'#2#0#7'OnClick'#7#12'btnHelpClick'
+#8'TabOrder'#2#7#0#0#242#2#14#7'TBitBtn'#5'btnOK'#23'AnchorSideRight.Control'
+#7#9'btnCancel'#24'AnchorSideBottom.Control'#7#5'Owner'#21'AnchorSideBottom.'
+'Side'#7#9'asrBottom'#4'Left'#3'0'#1#6'Height'#2#26#3'Top'#3'O'#1#5'Width'#2
+#27#7'Anchors'#11#7'akRight'#8'akBottom'#0#8'AutoSize'#9#20'BorderSpacing.Ar'
+'ound'#2#6#7'Caption'#6#2'OK'#7'Default'#9#11'ModalResult'#2#1#9'NumGlyphs'#2
+#0#7'OnClick'#7#10'btnOKClick'#8'TabOrder'#2#8#0#0#242#2#15#7'TBitBtn'#9'btn'
+'Cancel'#23'AnchorSideRight.Control'#7#5'Owner'#20'AnchorSideRight.Side'#7#9
+'asrBottom'#24'AnchorSideBottom.Control'#7#5'Owner'#21'AnchorSideBottom.Side'
+#7#9'asrBottom'#4'Left'#3'Q'#1#6'Height'#2#26#3'Top'#3'O'#1#5'Width'#2'1'#7
+'Anchors'#11#7'akRight'#8'akBottom'#0#8'AutoSize'#9#20'BorderSpacing.Around'
+#2#6#6'Cancel'#9#7'Caption'#6#6'Cancel'#11'ModalResult'#2#2#9'NumGlyphs'#2#0
+#8'TabOrder'#2#9#0#0#0
]);

View File

@ -0,0 +1,188 @@
unit BreakPropertyDlg;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
ExtCtrls, StdCtrls, Buttons, DebuggerDlg, Debugger, ButtonPanel, EditBtn,
BaseDebugManager, IDEContextHelpEdit;
type
{ TBreakPropertyDlg }
TBreakPropertyDlg = class(TDebuggerDlg)
btnCancel: TBitBtn;
btnHelp: TBitBtn;
btnOK: TBitBtn;
chkEnableGroups: TCheckBox;
chkDisableGroups: TCheckBox;
chkEvalExpression: TCheckBox;
chkLogMessage: TCheckBox;
chkActionBreak: TCheckBox;
cmbGroup: TComboBox;
edtEvalExpression: TEdit;
edtLogMessage: TEdit;
edtEnableGroups: TEditButton;
edtDisableGroups: TEditButton;
edtAutocontinueMS: TEdit;
edtCondition: TEdit;
edtCounter: TEdit;
edtFilename: TEdit;
edtLine: TEdit;
gbActions: TGroupBox;
lblFileName: TLabel;
lblLine: TLabel;
lblCondition: TLabel;
lblHitCount: TLabel;
lblGroup: TLabel;
lblAutoContinue: TLabel;
procedure btnHelpClick(Sender: TObject);
procedure btnOKClick(Sender: TObject);
procedure BreakPointRemove(const ASender: TIDEBreakPoints;
const ABreakpoint: TIDEBreakPoint);
procedure BreakPointUpdate(const ASender: TIDEBreakPoints;
const ABreakpoint: TIDEBreakPoint);
procedure edtDisableGroupsButtonClick(Sender: TObject);
procedure edtEnableGroupsButtonClick(Sender: TObject);
private
{ private declarations }
FBreakpointsNotification : TIDEBreakPointsNotification;
FBreakpoint: TIDEBreakPoint;
protected
procedure DoEndUpdate; override;
procedure UpdateInfo;
public
{ public declarations }
constructor Create(AOwner: TComponent; ABreakPoint: TIDEBreakPoint);overload;
destructor Destroy; override;
end;
implementation
{ TBreakPropertyDlg }
procedure TBreakPropertyDlg.BreakPointUpdate(
const ASender: TIDEBreakPoints; const ABreakpoint: TIDEBreakPoint);
begin
UpdateInfo;
end;
procedure TBreakPropertyDlg.btnHelpClick(Sender: TObject);
begin
ShowContextHelpForIDE(btnHelp);
end;
procedure TBreakPropertyDlg.BreakPointRemove(
const ASender: TIDEBreakPoints; const ABreakpoint: TIDEBreakPoint);
begin
if ABreakpoint = FBreakpoint
then ModalResult := mrCancel;
end;
procedure TBreakPropertyDlg.btnOKClick(Sender: TObject);
var
Actions: TIDEBreakPointActions;
begin
if FBreakpoint = nil then Exit;
FBreakpointsNotification.OnUpdate := nil;
// filename
// line
FBreakpoint.SetLocation(edtFilename.Text, StrToIntDef(edtLine.Text, 1));
// expression
FBreakpoint.Expression := edtCondition.Text;
// hitcount
FBreakpoint.BreakHitCount := StrToIntDef(edtCounter.Text, FBreakpoint.HitCount);
//auto continue
FBreakpoint.AutoContinueTime := StrToIntDef(edtAutocontinueMS.Text, FBreakpoint.AutoContinueTime);
// group
FBreakpoint.Group := DebugBoss.BreakPointGroups.GetGroupByName(cmbGroup.Text);
// actions
Actions := [];
if chkActionBreak.Checked then Include(Actions, bpaStop);
if chkDisableGroups.Checked then Include(Actions, bpaDisableGroup);
if chkEnableGroups.Checked then Include(Actions, bpaEnableGroup);
// if chkEvalExpression.Checked then Include(Actions, bpaEValExpression);
// if chkLogMessage.Checked then Include(Actions, bpaLogMessage);
FBreakpoint.Actions := Actions;
end;
procedure TBreakPropertyDlg.DoEndUpdate;
begin
inherited DoEndUpdate;
UpdateInfo;
end;
procedure TBreakPropertyDlg.edtDisableGroupsButtonClick(Sender: TObject);
begin
end;
procedure TBreakPropertyDlg.edtEnableGroupsButtonClick(Sender: TObject);
begin
end;
procedure TBreakPropertyDlg.UpdateInfo;
var
Actions: TIDEBreakPointActions;
begin
if FBreakpoint = nil then Exit;
// filename
edtFilename.text := FBreakpoint.Source;
// line
if FBreakpoint.Line > 0
then edtLine.Text := IntToStr(FBreakpoint.SourceLine)
else edtLine.Text := '';
// expression
edtCondition.Text := FBreakpoint.Expression;
// hitcount
edtCounter.Text := IntToStr(FBreakpoint.BreakHitCount);
// auto continue
edtAutocontinueMS.Text := IntToStr(FBreakpoint.AutoContinueTime);
// group
if FBreakpoint.Group = nil
then cmbGroup.Text := ''
else cmbGroup.Text := FBreakpoint.Group.Name;
// actions
Actions := FBreakpoint.Actions;
chkActionBreak.Checked := bpaStop in Actions;
chkDisableGroups.Checked := bpaDisableGroup in Actions;
chkEnableGroups.Checked := bpaEnableGroup in Actions;
// chkEvalExpression.Checked := bpaEValExpression in Actions;
// chkLogMessage.Checked := bpaLogMessage in Actions;
end;
constructor TBreakPropertyDlg.Create(AOwner: TComponent; ABreakPoint: TIDEBreakPoint);
begin
inherited Create(AOwner);
FBreakpoint := ABreakPoint;
FBreakpointsNotification := TIDEBreakPointsNotification.Create;
FBreakpointsNotification.AddReference;
FBreakpointsNotification.OnUpdate := @BreakPointUpdate;
FBreakpointsNotification.OnRemove := @BreakPointRemove;
UpdateInfo;
btnOK.LoadGlyphFromLazarusResource('btn_ok');
btnCancel.LoadGlyphFromLazarusResource('btn_cancel');
btnHelp.LoadGlyphFromLazarusResource('btn_help');
end;
destructor TBreakPropertyDlg.Destroy;
begin
FBreakpointsNotification.OnUpdate := nil;
FBreakpointsNotification.OnRemove := nil;
FBreakpointsNotification.ReleaseReference;
FBreakpointsNotification := nil;
inherited Destroy;
end;
initialization
{$I breakpropertydlg.lrs}
end.

View File

@ -68,7 +68,7 @@ type
dcDisassemble
);
TDBGCommands = set of TDBGCommand;
TDBGState = (
dsNone,
dsIdle,
@ -78,7 +78,7 @@ type
dsRun,
dsError
);
{
Debugger states
--------------------------------------------------------------------------
@ -143,7 +143,7 @@ type
destructor Destroy; override;
procedure ReleaseReference;
end;
TIDEBreakPoints = class;
TIDEBreakPointGroup = class;
@ -178,26 +178,30 @@ type
bpaDisableGroup
);
TIDEBreakPointActions = set of TIDEBreakPointAction;
{ TBaseBreakPoint }
TBaseBreakPoint = class(TDelayedUdateItem)
private
FEnabled: Boolean;
FExpression: String;
FHitCount: Integer;
FBreakHitCount: Integer;
FLine: Integer;
FSource: String;
FValid: TValidState;
FInitialEnabled: Boolean;
protected
procedure AssignTo(Dest: TPersistent); override;
procedure DoBreakHitCountChange; virtual;
procedure DoExpressionChange; virtual;
procedure DoEnableChange; virtual;
procedure DoHit(const ACount: Integer; var AContinue: Boolean); virtual;
procedure SetHitCount(const AValue: Integer);
procedure SetValid(const AValue: TValidState);
protected
// virtual properties
function GetBreakHitCount: Integer; virtual;
function GetEnabled: Boolean; virtual;
function GetExpression: String; virtual;
function GetHitCount: Integer; virtual;
@ -206,12 +210,14 @@ type
function GetSourceLine: Integer; virtual;
function GetValid: TValidState; virtual;
procedure SetBreakHitCount(const AValue: Integer); virtual;
procedure SetEnabled(const AValue: Boolean); virtual;
procedure SetExpression(const AValue: String); virtual;
procedure SetInitialEnabled(const AValue: Boolean); virtual;
public
constructor Create(ACollection: TCollection); override;
procedure SetLocation(const ASource: String; const ALine: Integer); virtual;// PublicProtectedFix ide/debugmanager.pas(867,32) Error: identifier idents no member "SetLocation"
property BreakHitCount: Integer read GetBreakHitCount write SetBreakHitCount;
property Enabled: Boolean read GetEnabled write SetEnabled;
property Expression: String read GetExpression write SetExpression;
property HitCount: Integer read GetHitCount;
@ -227,6 +233,7 @@ type
TIDEBreakPoint = class(TBaseBreakPoint)
private
FAutoContinueTime: Cardinal;
FActions: TIDEBreakPointActions;
FDisableGroupList: TList;
FEnableGroupList: TList;
@ -246,8 +253,10 @@ type
// virtual properties
function GetActions: TIDEBreakPointActions; virtual;
function GetGroup: TIDEBreakPointGroup; virtual;
function GetAutoContinueTime: Cardinal; virtual;
procedure SetActions(const AValue: TIDEBreakPointActions); virtual;
procedure SetGroup(const AValue: TIDEBreakPointGroup); virtual;
procedure SetAutoContinueTime(const AValue: Cardinal); virtual;
public
constructor Create(ACollection: TCollection); override;
destructor Destroy; override;
@ -262,11 +271,14 @@ type
const OnSaveFilename: TOnSaveFilenameToConfig); virtual;
public
property Actions: TIDEBreakPointActions read GetActions write SetActions;
property AutoContinueTime: Cardinal read GetAutoContinueTime write SetAutoContinueTime;
property Group: TIDEBreakPointGroup read GetGroup write SetGroup;
property Loading: Boolean read FLoading;
end;
TIDEBreakPointClass = class of TIDEBreakPoint;
{ TDBGBreakPoint }
TDBGBreakPoint = class(TBaseBreakPoint)
private
FSlave: TBaseBreakPoint;
@ -280,6 +292,7 @@ type
constructor Create(ACollection: TCollection); override;
destructor Destroy; override;
function GetSourceLine: integer; override;
procedure Hit(var ACanContinue: Boolean);
property Slave: TBaseBreakPoint read FSlave write SetSlave;
end;
TDBGBreakPointClass = class of TDBGBreakPoint;
@ -337,7 +350,7 @@ type
property Items[const AnIndex: Integer]: TIDEBreakPoint read GetItem
write SetItem; default;
end;
TDBGBreakPoints = class(TBaseBreakPoints)
private
FDebugger: TDebugger; // reference to our debugger
@ -419,8 +432,8 @@ type
property Items[const AnIndex: Integer]: TIDEBreakPointGroup
read GetItem write SetItem; default;
end;
(******************************************************************************)
(******************************************************************************)
(** **)
@ -442,7 +455,7 @@ type
procedure DoEnableChange; virtual;
procedure DoExpressionChange; virtual;
procedure SetValid(const AValue: TValidState);
protected
// virtual properties
function GetExpression: String; virtual;
@ -460,7 +473,7 @@ type
property Value: String read GetValue;
end;
TBaseWatchClass = class of TBaseWatch;
TIDEWatch = class(TBaseWatch)
private
protected
@ -498,7 +511,7 @@ type
TIDEWatchesEvent =
procedure(const ASender: TIDEWatches; const AWatch: TIDEWatch) of object;
TIDEWatchesNotification = class(TDebuggerNotification)
private
FOnAdd: TIDEWatchesEvent;
@ -519,7 +532,7 @@ type
function Find(const AExpression: String): TBaseWatch;
// no items property needed, it is "overridden" anyhow
end;
TIDEWatches = class(TBaseWatches)
private
FNotificationList: TList;
@ -568,7 +581,7 @@ type
write SetItem; default;
property OnChange: TNotifyEvent read FOnChange write FOnChange;
end;
(******************************************************************************)
(******************************************************************************)
(** **)
@ -630,8 +643,8 @@ type
constructor Create(const ADebugger: TDebugger);
property OnChange: TNotifyEvent read FOnChange write FOnChange;
end;
(******************************************************************************)
(******************************************************************************)
(** **)
@ -722,7 +735,7 @@ type
FLine: Integer;
FArguments: TStrings;
FSource: String;
function GetArgumentCount: Integer;
function GetArgumentCount: Integer;
function GetArgumentName(const AnIndex: Integer): String;
function GetArgumentValue(const AnIndex: Integer): String;
function GetCurrent: Boolean;
@ -743,7 +756,7 @@ type
property Line: Integer read FLine;
property Source: String read FSource;
end;
{ TBaseCallStack }
TBaseCallStack = class(TObject)
@ -765,7 +778,7 @@ type
property Current: TCallStackEntry read GetCurrent write SetCurrent;
property Entries[AIndex: Integer]: TCallStackEntry read GetEntry;
end;
{ TIDECallStackNotification }
@ -854,9 +867,9 @@ type
property ResumeHandled: Boolean read FResumeHandled write SetResumeHandled;
end;
TBaseSignalClass = class of TBaseSignal;
{ TDBGSignal }
TDBGSignal = class(TBaseSignal)
private
function GetDebugger: TDebugger;
@ -865,7 +878,7 @@ type
public
end;
TDBGSignalClass = class of TDBGSignal;
TIDESignal = class(TBaseSignal)
private
protected
@ -906,7 +919,7 @@ type
end;
{ TIDESignals }
TIDESignals = class(TBaseSignals)
private
function GetItem(const AIndex: Integer): TIDESignal;
@ -1028,6 +1041,8 @@ type
TDebuggerStateChangedEvent = procedure(ADebugger: TDebugger;
AOldState: TDBGState) of object;
TDebuggerBreakPointHitEvent = procedure(ADebugger: TDebugger; ABreakPoint: TBaseBreakPoint;
var ACanContinue: Boolean) of object;
TDBGOutputEvent = procedure(Sender: TObject; const AText: String) of object;
TDBGCurrentLineEvent = procedure(Sender: TObject;
const ALocation: TDBGLocationRec) of object;
@ -1064,6 +1079,7 @@ type
FOnOutput: TDBGOutputEvent;
FOnDbgOutput: TDBGOutputEvent;
FOnState: TDebuggerStateChangedEvent;
FOnBreakPointHit: TDebuggerBreakPointHitEvent;
FWorkingDir: String;
procedure DebuggerEnvironmentChanged(Sender: TObject);
procedure EnvironmentChanged(Sender: TObject);
@ -1085,6 +1101,7 @@ type
procedure DoDbgOutput(const AText: String);
procedure DoException(const AExceptionClass: String; const AExceptionText: String);
procedure DoOutput(const AText: String);
procedure DoBreakpointHit(const ABreakPoint: TBaseBreakPoint; var ACanContinue: Boolean);
procedure DoState(const OldState: TDBGState); virtual;
function ChangeFileName: Boolean; virtual;
function GetCommands: TDBGCommands;
@ -1153,9 +1170,10 @@ type
property OnException: TDBGExceptionEvent read FOnException write FOnException; // Fires when the debugger received an exeption
property OnOutput: TDBGOutputEvent read FOnOutput write FOnOutput; // Passes all output of the debugged target
property OnState: TDebuggerStateChangedEvent read FOnState write FOnState; // Fires when the current state of the debugger changes
property OnBreakPointHit: TDebuggerBreakPointHitEvent read FOnBreakPointHit write FOnBreakPointHit; // Fires when the program is paused at a breakpoint
end;
TDebuggerClass = class of TDebugger;
const
DBGCommandNames: array[TDBGCommand] of string = (
'Run',
@ -1174,7 +1192,7 @@ const
'SetStackFrame',
'Disassemble'
);
DBGStateNames: array[TDBGState] of string = (
'None',
'Idle',
@ -1184,13 +1202,13 @@ const
'Run',
'Error'
);
DBGBreakPointActionNames: array[TIDEBreakPointAction] of string = (
'Stop',
'EnableGroup',
'DisableGroup'
);
function DBGCommandNameToCommand(const s: string): TDBGCommand;
function DBGStateNameToState(const s: string): TDBGState;
function DBGBreakPointActionNameToAction(const s: string): TIDEBreakPointAction;
@ -1217,7 +1235,7 @@ const
{dsRun } [dcPause, dcStop, dcBreak, dcWatch, dcEnvironment],
{dsError} [dcStop]
);
var
MDebuggerPropertiesList: TStringlist;
@ -1334,7 +1352,7 @@ begin
Result := TDBGBreakPoints.Create(Self, TDBGBreakPoint);
end;
function TDebugger.CreateCallStack: TDBGCallStack;
function TDebugger.CreateCallStack: TDBGCallStack;
begin
Result := TDBGCallStack.Create(Self);
end;
@ -1349,7 +1367,7 @@ begin
Result := TDBGLocals.Create(Self);
end;
class function TDebugger.CreateProperties: TDebuggerProperties;
class function TDebugger.CreateProperties: TDebuggerProperties;
begin
Result := TDebuggerProperties.Create;
end;
@ -1421,7 +1439,7 @@ begin
end;
procedure TDebugger.DoDbgOutput(const AText: String);
begin
begin
// WriteLN(' [TDebugger] ', AText);
if Assigned(FOnDbgOutput) then FOnDbgOutput(Self, AText);
end;
@ -1438,6 +1456,12 @@ begin
if Assigned(FOnOutput) then FOnOutput(Self, AText);
end;
procedure TDebugger.DoBreakpointHit(const ABreakPoint: TBaseBreakPoint; var ACanContinue: Boolean);
begin
if Assigned(FOnBreakpointHit)
then FOnBreakpointHit(Self, ABreakPoint, ACanContinue);
end;
procedure TDebugger.DoState(const OldState: TDBGState);
begin
if State in INTERNAL_STATES then Exit;
@ -1469,7 +1493,7 @@ begin
then Env.Delete(idx);
end;
end;
// Set the remaining
for n := 0 to Env.Count - 1 do
begin
@ -1567,7 +1591,7 @@ function TDebugger.ReqCmd(const ACommand: TDBGCommand;
const AParams: array of const): Boolean;
begin
if FState = dsNone then Init;
if ACommand in Commands
if ACommand in Commands
then begin
Result := RequestCommand(ACommand, AParams);
if not Result then begin
@ -1618,7 +1642,7 @@ begin
if FState <> dsStop
then SetState(dsError);
end;
if FState = dsStop
then begin
// Reset state
@ -1651,7 +1675,7 @@ var
begin
if AValue <> FState
then begin
OldState := FState;
OldState := FState;
FState := AValue;
FBreakpoints.DoStateChange(OldState);
FLocals.DoStateChange(OldState);
@ -1694,12 +1718,12 @@ end;
procedure TBaseBreakPoint.AssignTo(Dest: TPersistent);
var
DestBreakPoint: TBaseBreakPoint;
DestBreakPoint: TBaseBreakPoint absolute Dest;
begin
// updatelock is set in source.assignto
if Dest is TBaseBreakPoint
then begin
DestBreakPoint:=TBaseBreakPoint(Dest);
DestBreakPoint.SetBreakHitCount(FBreakHitCount);
DestBreakPoint.SetLocation(FSource, FLine);
DestBreakPoint.SetExpression(FExpression);
DestBreakPoint.SetEnabled(FEnabled);
@ -1715,11 +1739,17 @@ begin
FValid := vsUnknown;
FEnabled := False;
FHitCount := 0;
FBreakHitCount := 0;
FExpression := '';
FInitialEnabled := False;
inherited Create(ACollection);
end;
procedure TBaseBreakPoint.DoBreakHitCountChange;
begin
Changed;
end;
procedure TBaseBreakPoint.DoEnableChange;
begin
Changed;
@ -1735,6 +1765,11 @@ begin
SetHitCount(ACount);
end;
function TBaseBreakPoint.GetBreakHitCount: Integer;
begin
Result := FBreakHitCount;
end;
function TBaseBreakPoint.GetEnabled: Boolean;
begin
Result := FEnabled;
@ -1770,6 +1805,15 @@ begin
Result := FValid;
end;
procedure TBaseBreakPoint.SetBreakHitCount(const AValue: Integer);
begin
if FBreakHitCount <> AValue
then begin
FBreakHitCount := AValue;
DoBreakHitCountChange;
end;
end;
procedure TBaseBreakPoint.SetEnabled (const AValue: Boolean );
begin
if FEnabled <> AValue
@ -1840,12 +1884,25 @@ begin
Changed;
end;
function TIDEBreakPoint.GetAutoContinueTime: Cardinal;
begin
Result := FAutoContinueTime;
end;
procedure TIDEBreakPoint.SetAutoContinueTime(const AValue: Cardinal);
begin
if FAutoContinueTime = AValue then Exit;
FAutoContinueTime := AValue;
Changed;
end;
procedure TIDEBreakPoint.AssignTo(Dest: TPersistent);
begin
inherited;
if Dest is TIDEBreakPoint
then begin
TIDEBreakPoint(Dest).Actions := FActions;
TIDEBreakPoint(Dest).AutoContinueTime := FAutoContinueTime;
end;
end;
@ -1967,6 +2024,8 @@ begin
GroupName:=XMLConfig.GetValue(Path+'Group/Name','');
Group:=OnGetGroup(GroupName);
Expression:=XMLConfig.GetValue(Path+'Expression/Value','');
AutoContinueTime:=XMLConfig.GetValue(Path+'AutoContinueTime/Value',0);
BreakHitCount := XMLConfig.GetValue(Path+'BreakHitCount/Value',0);
Filename:=XMLConfig.GetValue(Path+'Source/Value','');
if Assigned(OnLoadFilename) then OnLoadFilename(Filename);
FSource:=Filename;
@ -2008,7 +2067,7 @@ end;
procedure TIDEBreakPoint.SaveToXMLConfig(const AConfig: TXMLConfig;
const APath: string; const OnSaveFilename: TOnSaveFilenameToConfig);
procedure SaveGroupList(const AList: TList; const AListPath: string);
var
i: Integer;
@ -2022,19 +2081,21 @@ procedure TIDEBreakPoint.SaveToXMLConfig(const AConfig: TXMLConfig;
CurGroup.Name, '');
end;
end;
var
Filename: String;
CurAction: TIDEBreakPointAction;
begin
if Group <> nil
then AConfig.SetDeleteValue(APath+'Group/Name',Group.Name,'');
AConfig.SetDeleteValue(APath+'Expression/Value',Expression,'');
AConfig.SetDeleteValue(APath+'AutoContinueTime/Value',AutoContinueTime,0);
AConfig.SetDeleteValue(APath+'BreakHitCount/Value',BreakHitCount,0);
Filename := Source;
if Assigned(OnSaveFilename) then OnSaveFilename(Filename);
AConfig.SetDeleteValue(APath+'Source/Value',Filename,'');
AConfig.SetDeleteValue(APath+'InitialEnabled/Value',InitialEnabled,true);
AConfig.SetDeleteValue(APath+'Line/Value',Line,-1);
@ -2134,6 +2195,17 @@ begin
Result:=inherited GetSourceLine;
end;
procedure TDBGBreakPoint.Hit(var ACanContinue: Boolean);
var
cnt: Integer;
begin
cnt := HitCount + 1;
if BreakHitcount > 0
then ACanContinue := cnt < BreakHitcount;
DoHit(cnt, ACanContinue);
Debugger.DoBreakpointHit(Self, ACanContinue)
end;
procedure TDBGBreakPoint.DoChanged;
begin
inherited DoChanged;
@ -2270,13 +2342,13 @@ begin
LoadBreakPoint := TIDEBreakPoint.Create(nil);
LoadBreakPoint.LoadFromXMLConfig(XMLConfig,
Path+'Item'+IntToStr(i+1)+'/',OnLoadFilename,OnGetGroup);
BreakPoint := Find(LoadBreakPoint.Source, LoadBreakPoint.Line, LoadBreakPoint);
if BreakPoint = nil
then BreakPoint := Add(LoadBreakPoint.Source, LoadBreakPoint.Line);
BreakPoint.Assign(LoadBreakPoint);
FreeAndNil(LoadBreakPoint)
end;
end;
@ -2674,7 +2746,7 @@ begin
end;
function TBaseWatch.GetValue: String;
begin
begin
if not Enabled
then Result := '<disabled>'
else begin
@ -2942,7 +3014,7 @@ begin
begin
Notification := TIDEWatchesNotification(FNotificationList[n]);
if not Assigned(Notification.FOnUpdate) then Continue;
if Item = nil
then begin
for m := 0 to Count - 1 do
@ -3254,7 +3326,7 @@ constructor TCallStackEntry.Create(const AIndex: Integer;
const AnAdress: TDbgPtr; const AnArguments: TStrings;
const AFunctionName: String; const ASource: String; const ALine: Integer);
begin
inherited Create;
inherited Create;
FIndex := AIndex;
FAdress := AnAdress;
FArguments := TStringlist.Create;
@ -3287,7 +3359,7 @@ begin
end;
function TCallStackEntry.GetArgumentValue(const AnIndex: Integer): String;
begin
begin
Result := FArguments[AnIndex];
Result := GetPart('=', '', Result);
end;
@ -3301,7 +3373,7 @@ procedure TCallStackEntry.SetCurrent(const AValue: Boolean);
begin
if FOwner = nil then Exit;
if GetCurrent = AValue then Exit;
if AValue
then FOwner.SetCurrent(self)
else FOwner.SetCurrent(nil);
@ -3502,12 +3574,12 @@ begin
Changed;
end
else begin
if (AOldState = dsPause) or (AOldState = dsNone) { Force clear on initialisation }
then begin
if (AOldState = dsPause) or (AOldState = dsNone) { Force clear on initialisation }
then begin
Clear;
if Assigned(FOnClear) then FOnClear(Self);
end;
end;
end;
end;
function TDBGCallStack.InternalGetEntry(AIndex: Integer): TCallStackEntry;
@ -3790,7 +3862,7 @@ end;
procedure TBaseException.SetName(const AValue: String);
begin
if FName = AValue then exit;
if TBaseExceptions(GetOwner).Find(AValue) <> nil
then raise EDBGExceptions.Create('Duplicate name: ' + AValue);

View File

@ -1,16 +1,16 @@
{ $Id$ }
{ ----------------------------------------
{ ----------------------------------------
DebuggerDlg.pp - Base class for all
debugger related forms
----------------------------------------
----------------------------------------
@created(Wed Mar 16st WET 2001)
@lastmod($Date$)
@author(Marc Weustink <marc@@dommelstein.net>)
@author(Marc Weustink <marc@@dommelstein.net>)
This unit contains the base class for all debugger related dialogs.
This unit contains the base class for all debugger related dialogs.
All common info needed for the IDE is found in this class
***************************************************************************
* *
* This source is free software; you can redistribute it and/or modify *
@ -37,15 +37,15 @@ unit DebuggerDlg;
interface
uses
Classes, Forms, Controls, IDEProcs, Debugger, EnvironmentOpts;
Classes, Forms, Controls, IDEProcs, Debugger, EnvironmentOpts, IDEOptionDefs;
type
TDebuggerDlgClass = class of TDebuggerDlg;
TDebuggerDlg = class(TForm)
private
FUpdateCount: integer;
protected
protected
procedure DoClose(var CloseAction: TCloseAction); override;
procedure DoBeginUpdate; virtual;
procedure DoEndUpdate; virtual;
@ -55,10 +55,10 @@ type
function UpdateCount: integer;
end;
implementation
{ TDebuggerDlg }
implementation
{ TDebuggerDlg }
procedure TDebuggerDlg.BeginUpdate;
begin
Inc(FUpdateCount);
@ -80,24 +80,25 @@ end;
(*
procedure TDebuggerDlg.SetDebugger(const ADebugger: TDebugger);
begin
FDebugger := ADebugger;
FDebugger := ADebugger;
end;
*)
procedure TDebuggerDlg.DoClose(var CloseAction: TCloseAction);
var
Layout: TIDEWindowLayout;
begin
CloseAction := caFree; // we default to free
inherited DoClose(CloseAction);
EnvironmentOptions.IDEWindowLayoutList.ItemByFormID(Name).GetCurrentPosition;
Layout := EnvironmentOptions.IDEWindowLayoutList.ItemByFormID(Name);
if Layout <> nil then Layout.GetCurrentPosition;
end;
procedure TDebuggerDlg.DoBeginUpdate;
begin
end;
procedure TDebuggerDlg.DoEndUpdate;
begin
end;
end.

View File

@ -67,7 +67,7 @@ type
// some MI functions return normal output
// some normal functions return MI output
);
TGDBMIExecResult = record
State: TDBGState;
Values: String;
@ -198,13 +198,13 @@ type
class function CreateProperties: TDebuggerProperties; override; // Creates debuggerproperties
class function Caption: String; override;
class function ExePaths: String; override;
constructor Create(const AExternalDebugger: String); override;
destructor Destroy; override;
procedure Init; override; // Initializes external debugger
procedure Done; override; // Kills external debugger
// internal testing
procedure TestCmd(const ACommand: String); override;
end;
@ -268,7 +268,6 @@ type
public
constructor Create(ACollection: TCollection); override;
destructor Destroy; override;
procedure Hit(var ACanContinue: Boolean);
procedure SetLocation(const ASource: String; const ALine: Integer); override;
end;
@ -334,7 +333,7 @@ type
constructor Create(ACollection: TCollection); override;
procedure Invalidate;
end;
{ TDBGWatches }
{ TGDBMIWatches }
@ -345,7 +344,7 @@ type
procedure Changed;
public
end;
{ TGDBMICallStack }
TGDBMICallStack = class(TDBGCallStack)
@ -363,7 +362,7 @@ type
TGDBMIExpression = class(TObject)
private
FDebugger: TGDBMIDebugger;
FDebugger: TGDBMIDebugger;
FOperator: String;
FLeft: TGDBMIExpression;
FRight: TGDBMIExpression;
@ -375,7 +374,7 @@ type
function DumpExpression: String;
function GetExpression(var AResult: String): Boolean;
end;
{ TGDBMIType }
TGDBMIType = class(TGDBType)
@ -661,11 +660,11 @@ var
procedure InitWin32;
var
hMod: THandle;
begin
begin
// Check if we already are initialized
if DebugBreakAddr <> nil then Exit;
// normally you would load a lib, but since kernel32 is
// normally you would load a lib, but since kernel32 is
// always loaded we can use this (and we don't have to free it
hMod := GetModuleHandle(kernel32);
if hMod = 0 then Exit; //????
@ -673,7 +672,7 @@ begin
DebugBreakAddr := GetProcAddress(hMod, 'DebugBreak');
Pointer(_CreateRemoteThread) := GetProcAddress(hMod, 'CreateRemoteThread');
end;
{$ENDIF}
{$ENDIF}
{ =========================================================================== }
{ Helpers }
@ -685,14 +684,14 @@ begin
Result := APath;
// no need to process empty filename
if Result='' then exit;
{$WARNINGS off}
if DirectorySeparator <> '/' then
Result := StringReplace(Result, DirectorySeparator, '/', [rfReplaceAll]);
{$WARNINGS on}
Result := '"' + Result + '"';
end;
end;
{ =========================================================================== }
{ TGDBMIDebuggerProperties }
{ =========================================================================== }
@ -713,7 +712,7 @@ begin
if FCurrentStackFrame = AIndex then Exit;
FCurrentStackFrame := AIndex;
SelectStackFrame(FCurrentStackFrame);
TGDBMICallstack(CallStack).CurrentChanged;
TGDBMILocals(Locals).Changed;
TGDBMIWatches(Watches).Changed;
@ -737,14 +736,14 @@ var
List: TGDBMINameValueList;
begin
Result := False;
//Cleanup our own breakpoints
ClearBreakpoint(FExceptionBreakID);
ClearBreakpoint(FBreakErrorBreakID);
ClearBreakpoint(FRunErrorBreakID);
S := ConvertToGDBPath(UTF8ToSys(FileName));
S := ConvertToGDBPath(UTF8ToSys(FileName));
if not ExecuteCommand('-file-exec-and-symbols %s', [S], [cfIgnoreError], R) then Exit;
if (R.State = dsError)
and (FileName <> '')
@ -757,12 +756,12 @@ begin
end;
if not (inherited ChangeFileName) then Exit;
if State = dsError then Exit;
if FileName = ''
if FileName = ''
then begin
Result := True;
Exit;
end;
if tfHasSymbols in FTargetFlags
then begin
// Force setting language
@ -796,7 +795,7 @@ begin
{$IFdef MSWindows}
InitWin32;
{$ENDIF}
{$ENDIF}
inherited;
end;
@ -806,7 +805,7 @@ begin
Result := TDBGBreakPoints.Create(Self, TGDBMIBreakPoint);
end;
function TGDBMIDebugger.CreateCallStack: TDBGCallStack;
function TGDBMIDebugger.CreateCallStack: TDBGCallStack;
begin
Result := TGDBMICallStack.Create(Self);
end;
@ -938,7 +937,7 @@ begin
ExecResult.Values := '';
ExecResult.State := dsNone;
ExecResult.Flags := [];
Cmd := FCommandQueue[0];
CmdInfo := PGDBMICmdInfo(FCommandQueue.Objects[0]);
SendCmdLn(Cmd);
@ -980,7 +979,7 @@ begin
finally
Dec(FInExecuteCount);
end;
if FCommandQueue.Count = 0
then begin
if (FInExecuteCount = 0)
@ -1080,7 +1079,7 @@ begin
end;
end;
function PosSetEx(const ASubStrSet, AString: string;
function PosSetEx(const ASubStrSet, AString: string;
const Offset: integer): integer;
begin
for Result := Offset to Length(AString) do
@ -1309,7 +1308,7 @@ begin
if State = dsRun
then GDBPause(True);
if ASet then
if ASet then
begin
S := EscapeGDBCommand(AVariable);
ExecuteCommand('-gdb-set env %s', [S], [cfIgnoreState, cfExternal]);
@ -1321,7 +1320,7 @@ end;
function TGDBMIDebugger.GDBEvaluate(const AExpression: String;
var AResult: String): Boolean;
function MakePrintable(const AString: String): String;
var
n: Integer;
@ -1353,7 +1352,7 @@ function TGDBMIDebugger.GDBEvaluate(const AExpression: String;
if InString
then Result := Result + '''';
end;
var
R: TGDBMIExecResult;
S: String;
@ -1541,7 +1540,7 @@ function TGDBMIDebugger.GDBStop: Boolean;
begin
if State = dsError
then begin
// We don't know the state of the debugger,
// We don't know the state of the debugger,
// force a reinit. Let's hope this works.
DebugProcess.Terminate(0);
Done;
@ -1733,14 +1732,14 @@ begin
idx := 8; // the char after ' times>'
len := Length(S);
if v <= 1 then Continue;
// limit the amount of repeats
if v > 1000
then begin
Trailor := Trailor + Format('###(repeat truncated: %u -> 1000)###', [v]);
v := 1000;
end;
// make sure result has some room
SetLength(Result, Length(Result) + v - 1);
while v > 1 do begin
@ -1817,10 +1816,10 @@ procedure TGDBMIDebugger.Init;
FGDBVersion := '';
FGDBOS := '';
FGDBCPU := '';
if not ExecuteCommand('-gdb-version', [], [cfNoMiCommand], R) // No MI since the output is no MI
then Exit;
S := GetPart(['configured as \"'], ['\"'], R.Values, False, False);
if Pos('--target=', S) <> 0 then
S := GetPart('--target=', '', S);
@ -1830,11 +1829,11 @@ procedure TGDBMIDebugger.Init;
FGDBVersion := GetPart(['('], [')'], R.Values, False, False);
if FGDBVersion <> '' then Exit;
FGDBVersion := GetPart(['gdb '], [#10, #13], R.Values, True, False);
if FGDBVersion <> '' then Exit;
end;
procedure CheckGDBVersion;
begin
if FGDBVersion < '5.3'
@ -1851,20 +1850,20 @@ procedure TGDBMIDebugger.Init;
begin
FPauseWaitState := pwsNone;
FInExecuteCount := 0;
if CreateDebugProcess('-silent -i mi -nx')
then begin
if not ParseInitialization
then begin
SetState(dsError);
Exit;
Exit;
end;
ExecuteCommand('-gdb-set confirm off', []);
// for win32, turn off a new console otherwise breaking gdb will fail
// ignore the error on other platforms
ExecuteCommand('-gdb-set new-console off', [cfIgnoreError]);
ParseGDBVersion;
CheckGDBVersion;
@ -1887,12 +1886,12 @@ procedure TGDBMIDebugger.InterruptTarget;
ThreadID: Cardinal;
E: Integer;
Emsg: PChar;
begin
begin
Result := False;
hProcess := OpenProcess(PROCESS_CREATE_THREAD or PROCESS_QUERY_INFORMATION or PROCESS_VM_OPERATION or PROCESS_VM_WRITE or PROCESS_VM_READ, False, TargetPID);
if hProcess = 0 then Exit;
try
hThread := _CreateRemoteThread(hProcess, nil, 0, DebugBreakAddr, nil, 0, ThreadID);
if hThread = 0
@ -1925,9 +1924,9 @@ begin
// GenerateConsoleCtrlEvent is nice, but only works if both gdb and
// our target have a console. On win95 and family this is our only
// option, on NT4+ we have a choice. Since this is not likely that
// we have a console, we do it the hard way. On XP there exists
// we have a console, we do it the hard way. On XP there exists
// DebugBreakProcess, but it does efectively the same.
if (DebugBreakAddr = nil)
or not Assigned(_CreateRemoteThread)
or not TryNT
@ -1935,7 +1934,7 @@ begin
// We have no other choice than trying this
GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, TargetPID);
Exit;
end;
end;
{$ENDIF}
end;
@ -1955,7 +1954,7 @@ begin
// we're stopped in our thread
if FPauseWaitState = pwsInternal then Exit; // internal, dont care
S := '';
if not ExecuteCommand('-thread-list-ids', [cfIgnoreError], R) then Exit;
List := TGDBMINameValueList.Create(R);
@ -2019,12 +2018,12 @@ begin
Location.SrcLine := StrToIntDef(Frame.Values['line'], -1);
Frame.Free;
DoCurrent(Location);
end;
function TGDBMIDebugger.ProcessResult(var AResult: TGDBMIExecResult): Boolean;
function DoResultRecord(Line: String): Boolean;
var
ResultClass: String;
@ -2063,7 +2062,7 @@ function TGDBMIDebugger.ProcessResult(var AResult: TGDBMIExecResult): Boolean;
DebugLn('[WARNING] Debugger: Unknown result class: ', ResultClass);
end;
end;
procedure DoConsoleStream(Line: String);
var
len: Integer;
@ -2090,7 +2089,7 @@ function TGDBMIDebugger.ProcessResult(var AResult: TGDBMIExecResult): Boolean;
Line := Line + LineEnding;
end;
end;
AResult.Values := AResult.Values + Line;
end;
end;
@ -2256,7 +2255,7 @@ function TGDBMIDebugger.ProcessStopped(const AParams: String; const AIgnoreSigIn
Result.SrcFile := GetPart('\"', '\"', R.Values);
end;
end;
function GetExceptionInfo: TGDBMIExceptionInfo;
begin
if tfRTLUsesRegCall in FTargetFlags
@ -2274,7 +2273,7 @@ function TGDBMIDebugger.ProcessStopped(const AParams: String; const AIgnoreSigIn
procedure ProcessException(AInfo: TGDBMIExceptionInfo);
var
ExceptionMessage: String;
begin
begin
if dfImplicidTypes in FDebuggerFlags
then begin
ExceptionMessage := GetText('^Exception(%s)^.FMessage', [AInfo.ObjAddr]);
@ -2286,7 +2285,7 @@ function TGDBMIDebugger.ProcessStopped(const AParams: String; const AIgnoreSigIn
DoException(AInfo.Name, ExceptionMessage);
DoCurrent(GetLocation);
end;
procedure ProcessBreak;
var
ErrorNo: Integer;
@ -2299,7 +2298,7 @@ function TGDBMIDebugger.ProcessStopped(const AParams: String; const AIgnoreSigIn
DoException(Format('RunError(%d)', [ErrorNo]), '');
DoCurrent(GetLocation);
end;
procedure ProcessRunError;
var
ErrorNo: Integer;
@ -2329,10 +2328,10 @@ function TGDBMIDebugger.ProcessStopped(const AParams: String; const AIgnoreSigIn
if not AIgnoreSigIntState
or not SigInt
then SetState(dsPause);
if not SigInt
then DoException('External: ' + S, '');
if not AIgnoreSigIntState
or not SigInt
then ProcessFrame(AList.Values['frame']);
@ -2348,7 +2347,7 @@ var
begin
Result := True;
FCurrentStackFrame := 0;
List := TGDBMINameValueList.Create(AParams);
try
Reason := List.Values['reason'];
@ -2357,14 +2356,14 @@ begin
SetState(dsStop);
Exit;
end;
if Reason = 'exited'
then begin
SetExitCode(StrToIntDef(List.Values['exit-code'], 0));
SetState(dsStop);
Exit;
end;
if Reason = 'exited-signalled'
then begin
SetState(dsStop);
@ -2372,13 +2371,13 @@ begin
// ProcessFrame(List.Values['frame']);
Exit;
end;
if Reason = 'signal-received'
then begin
ProcessSignalReceived(List);
Exit;
end;
end;
if Reason = 'breakpoint-hit'
then begin
BreakID := StrToIntDef(List.Values['bkptno'], -1);
@ -2402,7 +2401,7 @@ begin
ProcessRunError;
Exit;
end;
if BreakID = FExceptionBreakID
then begin
ExceptionInfo := GetExceptionInfo;
@ -2416,7 +2415,7 @@ begin
end;
Exit;
end;
BreakPoint := TGDBMIBreakPoint(FindBreakpoint(BreakID));
if BreakPoint <> nil
then begin
@ -2433,33 +2432,33 @@ begin
end;
Exit;
end;
if Reason = 'function-finished'
then begin
SetState(dsPause);
ProcessFrame(List.Values['frame']);
Exit;
end;
if Reason = 'end-stepping-range'
then begin
SetState(dsPause);
ProcessFrame(List.Values['frame']);
Exit;
end;
if Reason = 'location-reached'
then begin
SetState(dsPause);
ProcessFrame(List.Values['frame']);
Exit;
end;
Result := False;
DebugLn('[WARNING] Debugger: Unknown stopped reason: ', Reason);
finally
List.Free;
end;
end;
end;
function TGDBMIDebugger.RequestCommand(const ACommand: TDBGCommand; const AParams: array of const): Boolean;
@ -2522,7 +2521,7 @@ function TGDBMIDebugger.StartDebugging(const AContinueCommand: String): Boolean;
ExecuteCommand('-data-evaluate-expression FPC_THREADVAR_RELOCATE_PROC', [cfIgnoreError], R);
if R.State <> dsError then Exit; // guessed right
// next attempt, posibly no symbols, try functions
if CheckFunction('FPC_CPUINIT') then Exit; // function present --> not 1.0
@ -2536,7 +2535,7 @@ function TGDBMIDebugger.StartDebugging(const AContinueCommand: String): Boolean;
// params are passes by stack
Exclude(FTargetFlags, tfRTLUsesRegCall);
end;
function InsertBreakPoint(const AName: String): Integer;
var
R: TGDBMIExecResult;
@ -2555,7 +2554,7 @@ function TGDBMIDebugger.StartDebugging(const AContinueCommand: String): Boolean;
// assume some defaults
FTargetPtrSize := 4;
FTargetIsBE := False;
case StringCase(AFileType, [
'efi-app-ia32', 'elf32-i386', 'pei-i386',
'elf64-x86-64',
@ -2643,7 +2642,7 @@ function TGDBMIDebugger.StartDebugging(const AContinueCommand: String): Boolean;
end;
end;
function SetTempMainBreak: Boolean;
var
R: TGDBMIExecResult;
@ -2672,7 +2671,7 @@ function TGDBMIDebugger.StartDebugging(const AContinueCommand: String): Boolean;
FMainAddr := StrToIntDef(ResultList.Values['addr'], 0);
ResultList.Free;
end;
var
R: TGDBMIExecResult;
FileType, EntryPoint: String;
@ -2705,7 +2704,7 @@ begin
// also call execute -exec-arguments if there are no arguments in this run
// so the possible arguments of a previous run are cleared
ExecuteCommand('-exec-arguments %s', [Arguments], [cfIgnoreError]);
if tfHasSymbols in FTargetFlags
then begin
// Make sure we are talking pascal
@ -2716,7 +2715,7 @@ begin
DebugLn('TGDBMIDebugger.StartDebugging Note: Target has no symbols');
TempInstalled := False;
end;
// try Insert Break breakpoint
// we might have rtl symbols
if FExceptionBreakID = -1
@ -2751,7 +2750,7 @@ begin
end;
SetTargetInfo(FileType);
if not TempInstalled and (EntryPoint <> '')
then begin
// We could not set our initial break to get info and allow stepping
@ -2760,9 +2759,9 @@ begin
ExecuteCommand('-break-insert -t *%u', [FMainAddr], [cfIgnoreError], R);
TempInstalled := R.State <> dsError;
end;
FTargetPID := 0;
// fire the first step
if TempInstalled
and ExecuteCommand('-exec-run', [], R)
@ -2807,7 +2806,7 @@ begin
else SetState(dsPause);
end
else SetState(R.State);
if State = dsPause
then ProcessFrame;
@ -2850,7 +2849,7 @@ end;
procedure TGDBMIBreakPoint.DoStateChange(const AOldState: TDBGState);
begin
inherited DoStateChange(AOldState);
case Debugger.State of
dsInit: begin
SetBreakpoint;
@ -2862,11 +2861,6 @@ begin
end;
end;
procedure TGDBMIBreakPoint.Hit(var ACanContinue: Boolean);
begin
DoHit(HitCount + 1, ACanContinue);
end;
procedure TGDBMIBreakPoint.SetBreakpoint;
begin
if Debugger = nil then Exit;
@ -2878,7 +2872,7 @@ begin
then TGDBMIDebugger(Debugger).GDBPause(True);
TGDBMIDebugger(Debugger).ExecuteCommand('-break-insert %s:%d',
[ExtractFileName(Source), Line], [cfIgnoreError], @SetBreakPointCallback, 0);
end;
procedure TGDBMIBreakPoint.SetBreakPointCallback(const AResult: TGDBMIExecResult; const ATag: Integer);
@ -2895,7 +2889,7 @@ begin
else SetValid(vsInvalid);
UpdateExpression;
UpdateEnable;
if (FBreakID <> 0)
and Enabled
and (TGDBMIDebugger(Debugger).FBreakAtMain = nil)
@ -2915,7 +2909,7 @@ procedure TGDBMIBreakPoint.ReleaseBreakPoint;
begin
if FBreakID = 0 then Exit;
if Debugger = nil then Exit;
if Debugger.State = dsRun
then TGDBMIDebugger(Debugger).GDBPause(True);
TGDBMIDebugger(Debugger).ExecuteCommand('-break-delete %d', [FBreakID], []);
@ -2933,7 +2927,7 @@ begin
end;
procedure TGDBMIBreakPoint.UpdateEnable;
const
const
// Use shortstring as fix for fpc 1.9.5 [2004/07/15]
CMD: array[Boolean] of ShortString = ('disable', 'enable');
begin
@ -3439,7 +3433,7 @@ begin
end;
function TGDBMICallStack.CreateStackEntry(AIndex: Integer): TCallStackEntry;
var
var
R: TGDBMIExecResult;
ArgList, FrameList: TGDBMINameValueList;
begin
@ -3453,7 +3447,7 @@ begin
then ArgList := TGDBMINameValueList.Create(R, ['stack-args', 'frame', 'args'])
else ArgList := nil;
TGDBMIDebugger(Debugger).ExecuteCommand('-stack-list-frames %0:d %0:d',
[AIndex], [cfIgnoreError], R);
@ -3767,9 +3761,9 @@ var
S: String;
List: TGDBMINameValueList;
GDBType: TGDBType;
begin
begin
Result := False;
if FLeft = nil
then AResult := ''
else begin
@ -3783,7 +3777,7 @@ begin
AResult := AResult + '(' + S + ')';
end
else if FOperator = '['
then begin
then begin
if not FRight.GetExpression(S) then Exit;
AResult := AResult + '[' + S + ']';
end
@ -3791,7 +3785,7 @@ begin
if (Length(FOperator) > 0)
and (FOperator[1] = '''')
then AResult := AResult + ConvertToCString(FOperator)
else begin
else begin
GDBType := FDebugger.GetGDBTypeInfo(FOperator);
if GDBType = nil
then begin
@ -3801,7 +3795,7 @@ begin
if not FDebugger.ExecuteCommand('ptype %s', [FOperator], [cfIgnoreError, cfNoMiCommand], R)
then Exit;
if R.State = dsError
then begin
// no type possible, use literal operator
@ -3829,7 +3823,7 @@ begin
AResult := AResult + S;
end;
end;
Result := True;
end;
@ -3843,5 +3837,5 @@ end;
initialization
RegisterDebugger(TGDBMIDebugger);
end.

View File

@ -62,6 +62,7 @@ type
FExceptions: TIDEExceptions;
FSignals: TIDESignals;
FBreakPoints: TIDEBreakPoints;
FBreakPointGroups: TIDEBreakPointGroups;
FLocals: TIDELocals;
FWatches: TIDEWatches;
FRegisters: TIDERegisters;
@ -120,6 +121,7 @@ type
property State: TDBGState read GetState; // The current state of the debugger
property BreakPoints: TIDEBreakPoints read FBreakpoints; // A list of breakpoints for the current project
property BreakPointGroups: TIDEBreakPointGroups read FBreakPointGroups;
property Exceptions: TIDEExceptions read FExceptions; // A list of exceptions we should ignore
property CallStack: TIDECallStack read FCallStack;
property Locals: TIDELocals read FLocals;

View File

@ -40,19 +40,19 @@ uses
{$IFDEF IDE_MEM_CHECK}
MemCheck,
{$ENDIF}
Classes, SysUtils, Forms, Controls, Dialogs, Menus, FileUtil, LCLProc,
Classes, SysUtils, Forms, Controls, Dialogs, Menus, ExtCtrls, FileUtil, LCLProc,
Laz_XMLCfg,
{ for Get/SetForegroundWindow }
LCLType, LCLIntf,
SynEdit, CodeCache, CodeToolManager,
MenuIntf, IDECommands, LazIDEIntf, ProjectIntf,
LazConf,
LazConf,
CompilerOptions, EditorOptions, EnvironmentOpts, ProjectOpts, KeyMapping, SourceEditor,
ProjectDefs, Project, IDEProcs, InputHistory, Debugger,
ProjectDefs, Project, IDEProcs, InputHistory, Debugger, CmdLineDebugger,
IDEOptionDefs, LazarusIDEStrConsts,
MainBar, MainIntf, MainBase, BaseBuildManager,
SourceMarks,
DebuggerDlg, Watchesdlg, BreakPointsdlg, LocalsDlg, WatchPropertyDlg,
DebuggerDlg, Watchesdlg, BreakPointsdlg, BreakPropertyDlg, LocalsDlg, WatchPropertyDlg,
CallStackDlg, EvaluateDlg, RegistersDlg, AssemblerDlg, DBGOutputForm,
GDBMIDebugger, SSHGDBMIDebugger, ProcessDebugger,
BaseDebugManager;
@ -73,6 +73,7 @@ type
{ TDebugManager }
TDebugManager = class(TBaseDebugManager)
procedure BreakAutoContinueTimer(Sender: TObject);
// Menu events
procedure mnuViewDebugDialogClick(Sender: TObject);
procedure mnuResetDebuggerClicked(Sender: TObject);
@ -81,6 +82,7 @@ type
function OnSrcNotebookAddWatchesAtCursor(Sender: TObject): boolean;
// Debugger events
procedure DebuggerBreakPointHit(ADebugger: TDebugger; ABreakPoint: TBaseBreakPoint; var ACanContinue: Boolean);
procedure DebuggerChangeState(ADebugger: TDebugger; OldState: TDBGState);
procedure DebuggerCurrentLine(Sender: TObject; const ALocation: TDBGLocationRec);
procedure DebuggerOutput(Sender: TObject; const AText: String);
@ -90,11 +92,13 @@ type
procedure DebugDialogDestroy(Sender: TObject);
private
FDebugger: TDebugger;
FBreakPointGroups: TIDEBreakPointGroups;
FDialogs: array[TDebugDialogType] of TDebuggerDlg;
FPrevShownWindow: HWND;
// keep track of the last reported location
FCurrentLocation: TDBGLocationRec;
// last hit breakpoint
FCurrentBreakpoint: TIDEBreakpoint;
FAutoContinueTimer: TTimer;
// When a source file is not found, the user can choose one
// here are all choices stored
@ -946,7 +950,7 @@ begin
else
AddMenuItem('Enable Breakpoint',true,@OnToggleEnableMenuItemClick);
AddMenuItem('Delete Breakpoint',true,@OnDeleteMenuItemClick);
AddMenuItem('View Breakpoint Properties',false,@OnViewPropertiesMenuItemClick);
AddMenuItem('View Breakpoint Properties',true,@OnViewPropertiesMenuItemClick);
// add separator
AddMenuItem('-',true,nil);
end;
@ -1176,6 +1180,23 @@ begin
end;
end;
procedure TDebugManager.BreakAutoContinueTimer(Sender: TObject);
begin
FAutoContinueTimer.Enabled := False;
FDebugger.Run;
end;
procedure TDebugManager.DebuggerBreakPointHit(ADebugger: TDebugger;
ABreakPoint: TBaseBreakPoint; var ACanContinue: Boolean);
begin
FCurrentBreakPoint := nil;
if FBreakPoints = nil then Exit;
if ABreakpoint = nil then Exit;
if ACanContinue then Exit;
FCurrentBreakPoint := FBreakPoints.Find(ABreakPoint.Source, ABreakPoint.SourceLine);
end;
procedure TDebugManager.mnuViewDebugDialogClick(Sender: TObject);
begin
ViewDebugDialog(TDebugDialogType((Sender as TIDEMenuItem).Tag));
@ -1286,20 +1307,27 @@ begin
if MainIDE.ToolStatus in [itNone,itDebugger]
then MainIDE.ToolStatus := TOOLSTATEMAP[FDebugger.State];
FAutoContinueTimer.Enabled := false;
if (FDebugger.State in [dsRun])
then begin
// hide IDE during run
if EnvironmentOptions.HideIDEOnRun
and (MainIDE.ToolStatus=itDebugger) then
MainIDE.HideIDE;
if EnvironmentOptions.HideIDEOnRun and (MainIDE.ToolStatus=itDebugger)
then MainIDE.HideIDE;
if FPrevShownWindow <> 0 then
begin
SetForegroundWindow(FPrevShownWindow);
FPrevShownWindow := 0;
end;
FCurrentBreakPoint := nil;
end
else begin
if (OldState in [dsRun]) then
if (FCurrentBreakPoint <> nil) and (FCurrentBreakPoint.AutoContinueTime > 0) then
begin
FAutoContinueTimer.Enabled := True;
FAutoContinueTimer.Interval := FCurrentBreakPoint.AutoContinueTime;
end
else if (OldState in [dsRun]) then
begin
MainIDE.UnhideIDE;
FPrevShownWindow := GetForegroundWindow;
@ -1308,8 +1336,7 @@ begin
end;
// unmark execution line
if (FDebugger.State <> dsPause)
and (SourceNotebook <> nil)
if (FDebugger.State <> dsPause) and (SourceNotebook <> nil)
then begin
Editor := SourceNotebook.GetActiveSE;
if Editor <> nil
@ -1329,10 +1356,10 @@ begin
dsStop: begin
if (OldState<>dsIdle)
then begin
if EnvironmentOptions.DebuggerShowStopMessage then begin
MessageDlg(lisExecutionStopped,
Format(lisExecutionStoppedOn, [#13#13]),
mtInformation, [mbOK],0);
if EnvironmentOptions.DebuggerShowStopMessage
then begin
MessageDlg(lisExecutionStopped,
Format(lisExecutionStoppedOn, [#13#13]), mtInformation, [mbOK],0);
end;
FDebugger.FileName := '';
@ -1355,6 +1382,7 @@ var
SrcLine: Integer;
i: Integer;
StackEntry: TCallStackEntry;
FocusEditor: Boolean;
begin
if (Sender<>FDebugger) or (Sender=nil) then exit;
if Destroying then exit;
@ -1417,9 +1445,9 @@ begin
SourceNotebook.ClearExecutionLines;
SourceNotebook.ClearErrorLines;
end;
// jump editor to execution line
if MainIDE.DoJumpToCodePos(nil,nil,NewSource,1,SrcLine,-1,true)<>mrOk
FocusEditor := (FCurrentBreakPoint = nil) or (FCurrentBreakPoint.AutoContinueTime = 0);
if MainIDE.DoJumpToCodePos(nil,nil,NewSource,1,SrcLine,-1,true, FocusEditor)<>mrOk
then exit;
// mark execution line
@ -1596,6 +1624,10 @@ begin
FUserSourceFiles := TStringList.Create;
FAutoContinueTimer := TTimer.Create(Self);
FAutoContinueTimer.Enabled := False;
FAutoContinueTimer.OnTimer := @BreakAutoContinueTimer;
inherited Create(TheOwner);
end;
@ -1603,7 +1635,9 @@ destructor TDebugManager.Destroy;
var
DialogType: TDebugDialogType;
begin
FDestroying:=true;
FDestroying := true;
FreeAndNil(FAutoContinueTimer);
for DialogType := Low(TDebugDialogType) to High(TDebugDialogType) do
DestroyDebugDialog(DialogType);
@ -1945,10 +1979,11 @@ begin
ClearDebugOutputLog;
FDebugger.OnState := @DebuggerChangeState;
FDebugger.OnCurrent := @DebuggerCurrentLine;
FDebugger.OnDbgOutput := @DebuggerOutput;
FDebugger.OnException := @DebuggerException;
FDebugger.OnBreakPointHit := @DebuggerBreakPointHit;
FDebugger.OnState := @DebuggerChangeState;
FDebugger.OnCurrent := @DebuggerCurrentLine;
FDebugger.OnDbgOutput := @DebuggerOutput;
FDebugger.OnException := @DebuggerException;
if FDebugger.State = dsNone
then begin
@ -2246,17 +2281,12 @@ end;
function TDebugManager.ShowBreakPointProperties(const ABreakpoint: TIDEBreakPoint): TModalresult;
begin
Result:=mrCancel;
// ToDo
Result := TBreakPropertyDlg.Create(Self, ABreakpoint).ShowModal;
end;
function TDebugManager.ShowWatchProperties(const AWatch: TIDEWatch): TModalresult;
begin
with TWatchPropertyDlg.Create(Self, AWatch) do
begin
Result := ShowModal;
Free;
end;
Result := TWatchPropertyDlg.Create(Self, AWatch).ShowModal;
end;
procedure TDebugManager.SetDebugger(const ADebugger: TDebugger);
@ -2286,3 +2316,4 @@ end;
end.

View File

@ -3850,6 +3850,7 @@ resourcestring
lisBreak = 'Break';
lisEnableGroup = 'Enable Group';
lisDisableGroup = 'Disable Group';
lisAutoContinue = 'Auto Continue';
lisDisabled = 'Disabled';
lisInvalidOff = 'Invalid (Off)';
lisInvalidOn = 'Invalid (On)';

View File

@ -849,7 +849,7 @@ type
ActiveSrcEdit: TSourceEditor;
ActiveUnitInfo: TUnitInfo;
NewSource: TCodeBuffer; NewX, NewY, NewTopLine: integer;
AddJumpPoint: boolean): TModalResult; override;
AddJumpPoint: boolean; FocusEditor: Boolean=True): TModalResult; override;
procedure DoJumpToCodeToolBossError; override;
procedure UpdateSourceNames;
procedure SaveSourceEditorChangesToCodeCache(PageIndex: integer); override;
@ -10770,6 +10770,7 @@ procedure TMainIDE.UpdateCaption;
var NewCaption: string;
begin
if MainIDEBar=nil then exit;
if ToolStatus = itExiting then exit;
NewCaption := Format(lisLazarusEditorV, [GetLazarusVersionString]);
if MainBarSubTitle<>'' then begin
NewCaption:=NewCaption+' - '+MainBarSubTitle;
@ -12185,7 +12186,7 @@ end;
function TMainIDE.DoJumpToCodePos(
ActiveSrcEdit: TSourceEditor; ActiveUnitInfo: TUnitInfo;
NewSource: TCodeBuffer; NewX, NewY, NewTopLine: integer;
AddJumpPoint: boolean): TModalResult;
AddJumpPoint: boolean; FocusEditor: boolean): TModalResult;
var
NewSrcEdit: TSourceEditor;
NewUnitInfo: TUnitInfo;
@ -12235,8 +12236,12 @@ begin
//DebugLn('TMainIDE.DoJumpToCodePos NewY=',dbgs(NewY),' ',dbgs(TopLine),' ',dbgs(NewTopLine));
LeftChar:=Max(NewX-CharsInWindow,1);
end;
SourceNoteBook.ShowOnTop;
SourceNotebook.FocusEditor;
if FocusEditor
then begin
SourceNoteBook.ShowOnTop;
SourceNotebook.FocusEditor;
end;
UpdateSourceNames;
Result:=mrOk;
end;

View File

@ -5,7 +5,7 @@
----------------------------------------
TMainIDEBase is the ancestor of TMainIDE. The various top level parts of the
IDE (called bosses/managers) access the TMainIDE via TMainIDEBase.
main.pp - TMainIDE = class(TMainIDEBase)
The highest manager/boss of the IDE. Only lazarus.pp uses
@ -115,7 +115,7 @@ type
procedure mnuWindowItemClick(Sender: TObject); virtual;
procedure mnuWindowSourceItemClick(Sender: TObject); virtual;
procedure OnMainBarDestroy(Sender: TObject); virtual;
procedure ConnectOutputFilter;
public
@ -165,15 +165,15 @@ type
ActiveSrcEdit: TSourceEditor;
ActiveUnitInfo: TUnitInfo;
NewSource: TCodeBuffer; NewX, NewY, NewTopLine: integer;
AddJumpPoint: boolean): TModalResult; virtual; abstract;
AddJumpPoint: boolean; FocusEditor: Boolean=True): TModalResult; virtual; abstract;
procedure FindInFilesPerDialog(AProject: TProject); override;
procedure FindInFiles(AProject: TProject; const FindText: string); override;
end;
var
MainIDE: TMainIDEBase = nil;
{ Normally the IDE builds itself with packages named in config files.
When the IDE should keep the packages installed in the current executable
set KeepInstalledPackages to true. }
@ -1018,10 +1018,10 @@ begin
if (AForm.Designer<>nil) and (WindowsList.IndexOf(AForm)<0) then
WindowsList.Add(AForm);
end;
// create menuitems
ItemCount := WindowsList.Count;
for i:=0 to WindowsList.Count-1 do
for i:=0 to WindowsList.Count-1 do
begin
CurMenuItem := GetMenuItem(i);
CurMenuItem.Caption:=TCustomForm(WindowsList[i]).Caption;
@ -1031,14 +1031,14 @@ begin
//create source page menuitems
if (SourceNotebook<>nil) and (SourceNotebook.Notebook<>nil) and not (nbcPageListPopup in SourceNotebook.Notebook.GetCapabilities) then
if (SourceNotebook<>nil) and (SourceNotebook.Notebook<>nil) and not (nbcPageListPopup in SourceNotebook.Notebook.GetCapabilities) then
begin
CurMenuItem := GetMenuItem(ItemCount);
CurMenuItem.OnClick:=nil;
CurMenuItem.Caption:='-';
inc(ItemCount);
for i := 0 to SourceNotebook.EditorCount-1 do
for i := 0 to SourceNotebook.EditorCount-1 do
begin
CurMenuItem := GetMenuItem(ItemCount);
CurMenuItem.Caption:=SourceNotebook.Editors[i].PageName;