mirror of
				https://gitlab.com/freepascal.org/lazarus/lazarus.git
				synced 2025-10-31 23:30:32 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			244 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			244 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
| { $Id$ }
 | |
| {               ----------------------------------------------  
 | |
|                  callstackdlg.pp  -  Overview of the callstack 
 | |
|                 ---------------------------------------------- 
 | |
|  
 | |
|  @created(Sun Apr 28th WET 2002)
 | |
|  @lastmod($Date$)
 | |
|  @author(Marc Weustink <marc@@dommelstein.net>)                       
 | |
| 
 | |
|  This unit contains the Call Stack debugger dialog.
 | |
|  
 | |
|  
 | |
|  ***************************************************************************
 | |
|  *                                                                         *
 | |
|  *   This source is free software; you can redistribute it and/or modify   *
 | |
|  *   it under the terms of the GNU General Public License as published by  *
 | |
|  *   the Free Software Foundation; either version 2 of the License, or     *
 | |
|  *   (at your option) any later version.                                   *
 | |
|  *                                                                         *
 | |
|  *   This code is distributed in the hope that it will be useful, but      *
 | |
|  *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
 | |
|  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
 | |
|  *   General Public License for more details.                              *
 | |
|  *                                                                         *
 | |
|  *   A copy of the GNU General Public License is available on the World    *
 | |
|  *   Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also      *
 | |
|  *   obtain it by writing to the Free Software Foundation,                 *
 | |
|  *   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.        *
 | |
|  *                                                                         *
 | |
|  ***************************************************************************
 | |
| }
 | |
| unit CallStackDlg;
 | |
| 
 | |
| {$mode objfpc}{$H+}
 | |
| 
 | |
| interface
 | |
| 
 | |
| uses
 | |
|   LResources, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 | |
|   ComCtrls, Debugger, DebuggerDlg, Menus, ClipBrd;
 | |
| 
 | |
| type
 | |
| 
 | |
|   { TCallStackDlg }
 | |
| 
 | |
|   TCallStackDlg = class(TDebuggerDlg)
 | |
|     lvCallStack: TListView;
 | |
|     popCopyAll: TMenuItem;
 | |
|     N1: TMenuItem;
 | |
|     popSetAsCurrent: TMenuItem;
 | |
|     popShow: TMenuItem;
 | |
|     mnuPopup: TPopupMenu;
 | |
|     procedure lvCallStackDBLCLICK(Sender: TObject);
 | |
|     procedure popCopyAllClick(Sender: TObject);
 | |
|     procedure popShowClick(Sender: TObject);
 | |
|   private
 | |
|     FCallStack: TIDECallStack;
 | |
|     FCallStackNotification: TIDECallStackNotification;
 | |
|     procedure CallStackChanged(Sender: TObject);
 | |
|     procedure SetCallStack(const AValue: TIDECallStack);
 | |
|     function GetFunction(const Entry: TCallStackEntry): string;
 | |
|     procedure JumpToSource;
 | |
|     procedure CopyToClipBoard;
 | |
|   protected
 | |
|     procedure DoBeginUpdate; override;
 | |
|     procedure DoEndUpdate; override;
 | |
|   public
 | |
|     constructor Create(AOwner: TComponent); override;
 | |
|     destructor Destroy; override;
 | |
| 
 | |
|     property CallStack: TIDECallStack read FCallStack write SetCallStack;
 | |
|   end;
 | |
| 
 | |
| 
 | |
| implementation
 | |
| 
 | |
| { TCallStackDlg }
 | |
| 
 | |
| constructor TCallStackDlg.Create(AOwner: TComponent);
 | |
| begin
 | |
|   inherited Create(AOwner);
 | |
|   FCallStackNotification := TIDECallStackNotification.Create;
 | |
|   FCallStackNotification.AddReference;
 | |
|   FCallStackNotification.OnChange := @CallStackChanged;
 | |
| end;
 | |
| 
 | |
| procedure TCallStackDlg.CallStackChanged(Sender: TObject);
 | |
| var
 | |
|   n: Integer;
 | |
|   Item: TListItem;
 | |
|   Entry: TCallStackEntry;
 | |
| begin       
 | |
|   BeginUpdate;
 | |
|   try
 | |
|     if CallStack = nil
 | |
|     then begin
 | |
|       lvCallStack.Items.Clear;
 | |
|       exit;
 | |
|     end;
 | |
| 
 | |
|     // Reuse entries, so add and remove only
 | |
|     // Remove unneded
 | |
|     for n := lvCallStack.Items.Count - 1 downto CallStack.Count do
 | |
|       lvCallStack.Items.Delete(n);
 | |
| 
 | |
|     // Add needed
 | |
|     for n := lvCallStack.Items.Count to CallStack.Count - 1 do
 | |
|     begin
 | |
|       Item := lvCallStack.Items.Add;
 | |
|       Item.SubItems.Add('');
 | |
|       Item.SubItems.Add('');
 | |
|     end;
 | |
| 
 | |
|     for n := 0 to lvCallStack.Items.Count - 1 do
 | |
|     begin
 | |
|       Item := lvCallStack.Items[n];
 | |
|       Entry := CallStack.Entries[n];
 | |
|       Item.Caption := Entry.Source;
 | |
|       Item.SubItems[0] := IntToStr(Entry.Line);
 | |
|       Item.SubItems[1] := GetFunction(Entry);
 | |
|     end;
 | |
|     
 | |
|   finally
 | |
|     EndUpdate;
 | |
|   end;
 | |
| end;
 | |
| 
 | |
| destructor TCallStackDlg.Destroy;
 | |
| begin
 | |
|   FCallStackNotification.OnChange := nil;
 | |
|   FCallStackNotification.ReleaseReference;
 | |
|   inherited Destroy;
 | |
| end;
 | |
| 
 | |
| procedure TCallStackDlg.DoBeginUpdate;
 | |
| begin
 | |
|   lvCallStack.BeginUpdate;
 | |
| end;
 | |
| 
 | |
| procedure TCallStackDlg.DoEndUpdate;
 | |
| begin
 | |
|   lvCallStack.EndUpdate;
 | |
| end;
 | |
| 
 | |
| procedure TCallStackDlg.JumpToSource;
 | |
| var
 | |
|   CurItem: TListItem;
 | |
|   Filename: String;
 | |
|   Line: Integer;
 | |
| begin
 | |
|   CurItem:=lvCallStack.Selected;
 | |
|   if CurItem=nil then exit;
 | |
|   Filename:=CurItem.Caption;
 | |
|   if DoGetFullDebugFilename(Filename,true)<>mrOk then exit;
 | |
|   Line:=StrToIntDef(CurItem.SubItems[0],0);
 | |
|   DoJumpToCodePos(Filename,Line,0);
 | |
| end;
 | |
| 
 | |
| procedure TCallStackDlg.CopyToClipBoard;
 | |
| var
 | |
|   n: integer;
 | |
|   Entry: TCallStackEntry;
 | |
|   EntryList: TStringList;
 | |
| begin
 | |
|   Clipboard.Clear;
 | |
|   
 | |
|   if (CallStack=nil) or (CallStack.Count=0) then exit;
 | |
|   
 | |
|   EntryList:=TStringList.Create;
 | |
|   try
 | |
|     EntryList.Capacity:=CallStack.Count;
 | |
|     for n:= 0 to CallStack.Count-1 do begin
 | |
|       Entry:=CallStack.Entries[n];
 | |
|       EntryList.Add(format('#%d %s at %s:%d',
 | |
|         [n, GetFunction(Entry), Entry.Source, Entry.Line]));
 | |
|     end;
 | |
|     ClipBoard.AsText := EntryList.Text;
 | |
|   finally
 | |
|     EntryList.Free;
 | |
|   end;
 | |
| end;
 | |
| 
 | |
| procedure TCallStackDlg.lvCallStackDBLCLICK(Sender: TObject);
 | |
| begin
 | |
|   JumpToSource;
 | |
| end;
 | |
| 
 | |
| procedure TCallStackDlg.popCopyAllClick(Sender: TObject);
 | |
| begin
 | |
|   CopyToClipBoard;
 | |
| end;
 | |
| 
 | |
| procedure TCallStackDlg.popShowClick(Sender: TObject);
 | |
| begin
 | |
|   JumpToSource;
 | |
| end;
 | |
| 
 | |
| procedure TCallStackDlg.SetCallStack(const AValue: TIDECallStack);
 | |
| begin
 | |
|   if FCallStack = AValue then Exit;
 | |
| 
 | |
|   BeginUpdate;
 | |
|   try
 | |
|     if FCallStack <> nil
 | |
|     then begin
 | |
|       FCallStack.RemoveNotification(FCallStackNotification);
 | |
|     end;
 | |
| 
 | |
|     FCallStack := AValue;
 | |
| 
 | |
|     if FCallStack <> nil
 | |
|     then begin
 | |
|       FCallStack.AddNotification(FCallStackNotification);
 | |
|     end;
 | |
| 
 | |
|     CallStackChanged(FCallStack);
 | |
|   finally
 | |
|     EndUpdate;
 | |
|   end;
 | |
| end;
 | |
| 
 | |
| function TCallStackDlg.GetFunction(const Entry: TCallStackEntry): string;
 | |
| var
 | |
|   S: String;
 | |
|   m: Integer;
 | |
| begin
 | |
|   S := '';
 | |
|   for m := 0 to Entry.ArgumentCount - 1 do
 | |
|   begin
 | |
|     if S <> '' then
 | |
|       S := S + ', ';
 | |
|     S := S + Entry.ArgumentValues[m];
 | |
|   end;
 | |
|   if S <> '' then
 | |
|     S := '(' + S + ')';
 | |
|   Result := Entry.FunctionName + S;
 | |
| end;
 | |
| 
 | |
| initialization
 | |
|   {$I callstackdlg.lrs}
 | |
| 
 | |
| end.
 | |
| 
 | 
