123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745 |
- {
- This file is part of the Free Pascal run time library.
- Copyright (c) 2003 by the Free Pascal development team
- Main form of GTK debugserver
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program 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.
- **********************************************************************}
- {$mode objfpc}
- {$h+}
- unit frmmain;
- Interface
- uses
- fpgtk,fpgtkext,glib,gtk,gdk,debugserverintf,sysutils,msgintf,classes,inifiles;
- Type
- TClientCList = Class(TFPGtkScrollClist)
- Protected
- FTabLabel : TFPgtkLabel;
- FClient : TClient;
- Public
- Constructor Create (AClient : TClient);
- Property Client : TClient Read FClient Write FClient;
- Property TabLabel : TFPgtkLabel Read FTabLabel Write FTabLabel;
- end;
- TMainForm = Class (TFPGtkWindow)
- Private
- // 'real' Variables
- FCreating,
- FPaused,
- FInsertNew,
- FCloseOnDisconnect,
- FLoadSinglePage,
- FSinglePage : Boolean;
- FIdleHandle : gint;
- FMsgImages : Array[-1..3] of PgdkPixmap;
- FMsgMasks : Array[-1..3] of Pgdkbitmap;
- // Widgets
- FVBox : TFPGtkVBox;
- FMainMenu : TFpGtkMenuBar;
- FFile, // File menu
- FFileClear,
- FFileSave,
- FFileExit,
- FFileClose,
- FOptions,
- FHelp, // Help menu
- FHelpAbout : TFPGtkMenuItem;
- FOptionsInsertNew,
- FOptionsSinglePage,
- FOptionsCloseOnDisconnect,
- FFilePause : TFPGtkCheckMenuItem;
- FConnectImage,
- FDisconnectImage,
- FInfoImage,
- FWarningImage,
- FErrorImage,
- FClearImage,
- FSaveImage,
- FCloseImage,
- FPauseImage,
- FRunImage,
- FRunButtonImage : TFPGtkPixmap;
- FMainToolbar : TFPGtkToolbar;
- FToolbarFrame : TFPGtkFrame;
- FPages : TfpGTKNotebook;
- FList : TClientCList;
- FRunButton : TFPgtkButton;
- FRunImages : Array[Boolean] of PgdkPixmap;
- FRunMasks : Array[Boolean] of Pgdkbitmap;
- Public
- // General
- Constructor Create;
- Procedure CreateWindow;
- Procedure LoadSettings;
- Procedure SaveSettings;
- Function SettingsFilename : String;
- Procedure SetupDebugServer;
- Procedure ShutdownDebugServer;
- // List/Client management
- Procedure SaveToFile(C : TClientCList; FN : String);
- Function NewList(Client : TClient) : TClientCList;
- Function GetList(Client : TClient) : TClientClist;
- Procedure HaveData(Handle : Gint);
- Procedure AddEventToList(Event : TDebugEvent);
- Function CheckForNewClient : TClient;
- Function CurrentList : TClientCList;
- Function GetClientPageIndex(Client : TClient) : Integer;
- Procedure ConnectionClosed(C : TCLient);
- Procedure SetRunButtonBitmaps;
- Function GetFileName(ATitle : String) : String;
- Procedure DialogSetFilename(Sender : TFPGtkWindow;Data : Pointer; Action : Integer;Initiator : TFPGtkObject);
- // User callbacks
- Procedure FileClearClick(Sender : TFPGtkObject; Data : Pointer);
- Procedure FileSaveClick(Sender : TFPGtkObject; Data : Pointer);
- Procedure FileCopyClick(Sender : TFPGtkObject; Data : Pointer);
- Procedure FilePauseClick(Sender : TFPGtkObject; Data : Pointer);
- Procedure FileCloseClick(Sender : TFPGtkObject; Data : Pointer);
- Procedure FileExitClick(Sender : TFPGtkObject; Data : Pointer);
- Procedure OptionsClick(Sender : TFPGtkObject; Data : Pointer);
- Procedure HelpAboutClick(Sender : TFPGtkObject; Data : Pointer);
- Function OnDeleteEvent(Sender:TFPgtkWidget; Event:PGdkEvent; data:pointer): boolean;
- end;
- Implementation
- uses frmabout,bitmapdata;
- ResourceString
- SCaption = 'FPC Debug server';
- SMenuFile = '_File';
- SMenuFileClear = 'Clea_r';
- SMenuFileSave = '_Save';
- SMenuFileCopy = '_Copy';
- SMenuFilePause = '_Pause';
- SMenuFileClose = 'C_lose';
- SMenuFileExit = 'E_xit';
- SMenuOptions = '_Options';
- SMenuOptionsInsertNew = '_New messages first';
- SMenuOptionsSinglePage = '_All clients on 1 page';
- SMenuOptionsCloseOnDisconnect = '_Close client on disconnect';
- SMenuHelp = '_Help';
- SMenuHelpAbout = '_About';
- SHintFileClear = 'Clear current list';
- SHintFileSave = 'Save current list to disk';
- SHintFilePause = 'Discard new messages';
- SHintFileClose = 'Close current list';
- SNewClient = 'New client';
- SMessageFrom = '[%s] : %s';
- SSaveFileTitle = 'Save list to file:';
- SNeedsRestart = 'Restart debugserver for this option to take effect.';
- Const
- SKeyParameters = 'Parameters';
- SKeySinglePage = 'SinglePage';
- SKeyCloseOnDisconnect = 'CloseOnDisconnect';
- SkeyInsertNew = 'InsertNewMessages';
- SConfigFile = 'debugserver.cnf';
- DefaultSinglePage = True;
- DefaultCloseOnConnect = False;
- DefaultInsertNew = True;
- Const
- DefaultTooltips = True;
- DefaultToolBarStyle = GTK_TOOLBAR_ICONS;
- DefaultToolbarRelief = GTK_RELIEF_NONE;
- { ---------------------------------------------------------------------
- TClientCList
- ---------------------------------------------------------------------}
- Constructor TClientCList.Create(Aclient : TClient);
- begin
- Inherited Create(3);
- FClient:=AClient;
- Clist.ShowTitles;
- CList.PassiveTitles;
- Clist.ColumnTitle[0]:='*';
- Clist.ColumnTitle[1]:='Time';
- Clist.ColumnTitle[2]:='Message';
- CLIST.SetColumnWidth(0,20);
- CList.SetColumnResizeable(0,False);
- CLIST.SetColumnWidth(1,120);
- end;
- { ---------------------------------------------------------------------
- MainForm - General
- ---------------------------------------------------------------------}
- // Cludge to go around TFPgtkBin.Child not being public...
- Type
- TMyBin = Class(TFPgtkBin)
- Public
- Property Child;
- end;
- Procedure TMainForm.CreateWindow;
- Var
- V : TFPGtkHBox;
- FAccelGroup: Integer;
- begin
- { File Menu }
- Title:=SCaption;
- FAccelGroup:=AccelGroupNew;
- FFileClear := NewMenuItem(SMenuFileClear ,'','',MakeAccelKeyDef(Self,FaccelGroup,GDK_L,[amcontrol]),@FileClearClick,Nil);
- FFileSave := NewMenuItem(SMenuFileSave ,'','',MakeAccelKeyDef(Self,FaccelGroup,GDK_S,[amcontrol]),@FileSaveClick,Nil);
- FFilePause := NewCheckMenuItem(SMenuFilePause ,'','',MakeAccelKeyDef(Self,FaccelGroup,GDK_P,[amcontrol]),@FilePauseClick,Nil);
- If Not FSinglePage then
- FFileClose := NewMenuItem(SMenuFileClose ,'','',MakeAccelKeyDef(Self,FaccelGroup,GDK_W,[amcontrol]),@FileCloseClick,Nil);
- FFileExit := NewMenuItem(SMenuFileExit ,'','',MakeAccelKeyDef(Self,FaccelGroup,GDK_Q,[amcontrol]),@FileExitClick,Nil);
- If FSinglePage then
- FFile := NewSubMenu(SMenuFile,'','',[FFileClear,FFileSave,FFilePause,NewLine,FFileExit])
- else
- FFile := NewSubMenu(SMenuFile,'','',[FFileClear,FFileSave,FFilePause,FFileClose,NewLine,FFileExit]);
- { Options menu }
- FOptionsInsertNew := NewCheckMenuItem(SMenuOptionsInsertNew,'','', @OptionsClick,@FInsertNew);
- FOptionsInsertNew.Active:=FInsertNew;
- FOptionsSinglePage := NewCheckMenuItem(SMenuOptionsSinglePage,'','', @OptionsClick,@FLoadSinglePage);
- FOptionsSinglePage.Active:=FSinglePage;
- FOptionsCloseOnDisconnect := NewCheckMenuItem(SMenuOptionsCloseOnDisconnect,'','', @OptionsClick,@FCloseOnDisconnect);
- FOptionsCloseOnDisconnect.active:=FCloseOnDisconnect;
- FOptions := NewSubMenu(SMenuOptions,'','',[FOptionsInsertNew,FOptionsSinglePage,FOptionsCloseOnDisconnect]);
- { Help Menu }
- FHelpAbout:=NewMenuItem(SMenuHelpAbout ,'','',@HelpAboutClick,Nil);
- FHelp := NewSubMenu(SMenuHelp,'','',[FHelpAbout]);
- { Menu bar }
- FMainMenu:=NewMenuBar([FFile,FOptions,FHelp]);
- { Toolbar images }
- FClearImage:=PixmapFromFile('clear');
- FPauseImage:=PixmapFromFile('pause');
- FRunImage:=PixmapFromFile('run');
- FCloseImage:=PixMapFromFile('close');
- FSaveImage:=PixmapFromFile('save');
- FRunButtonImage:=TFPGtkPixmap.Create;
- FRunImages[False]:=FPauseImage.PixMap;
- FRunMasks[False]:=FPauseImage.Mask;
- FRunImages[True]:=FRunImage.PixMap;
- FRunMasks[True]:=FRunImage.Mask;
- SetRunButtonBitmaps;
- { Message images }
- FConnectImage:=PixMapFromFile('connect');
- FDisConnectImage:=PixMapFromFile('disconnect');
- FinfoImage:=PixmapFromFile('info');
- FWarningImage:=PixmapFromFile('warning');
- FErrorImage:=PixmapFromFile('error');
- { Save references for quick lookup}
- FMsgImages[-1]:=FDisconnectImage.PixMap;
- FMsgImages[0]:=FinfoImage.PixMap;
- FMsgImages[1]:=FWarningImage.PixMap;
- FMsgImages[2]:=FErrorImage.PixMap;
- FMsgImages[3]:=FConnectImage.PixMap;
- FMsgMasks[-1]:=FDisconnectImage.Mask;
- FMsgMasks[0]:=FinfoImage.Mask;
- FMsgMasks[1]:=FWarningImage.Mask;
- FMsgMasks[2]:=FErrorImage.Mask;
- FMsgMasks[3]:=FConnectImage.Mask;
- { Toolbar }
- FMainToolBar:=TFPGtkToolbar.Create;
- With FMainToolbar do
- begin
- Style:=DefaultToolbarStyle;
- ButtonRelief:=DefaultToolbarRelief;
- EnableTooltips:=DefaultTooltips;
- AppendItem(SMenuFileClear,SHintFileClear,'',FClearImage,@FileClearClick,Nil);
- AppendItem(SMenuFileSave,SHintFileSave,'',FSaveImage,@FileSaveClick,Nil);
- FRunButton:=AppendItem(SMenuFilePause,SHintFilePause,'',FRunButtonImage,@FilePauseClick,Nil) as TFPgtkButton;
- AppendItem(SMenuFileClose,SHintFileClose,'',FCloseImage,@FileCloseClick,Nil);
- end;
- { place left aligned on frame }
- V:=TFPGtkHBox.Create;
- V.PackStart(FMainToolbar,False,False,2);
- FToolbarFrame:=TFPGtkFrame.Create;
- FtoolbarFrame.Add(V);
- { For Pages }
- // FPages:=TFPGtkNoteBook.Create;
- If FSinglePage then
- FList:=NewList(Nil)
- else
- FPages:=TFPGtkNoteBook.Create;
- { Place on form }
- FVBox:=TFPGTKVBox.create;
- FVBox.PackStart(FMainMenu,false, true, 0);
- FVBox.PackStart(FToolBarFrame,false, true, 0);
- If FSinglePage then
- FVBox.PackStart(FList,true, true, 0)
- else
- FVBox.PackStart(FPages,true, true, 0);
- Self.add(FVBox);
- Setusize(640,480);
- ConnectDeleteEvent(@OnDeleteEvent,Nil);
- end;
- Constructor TMainForm.Create;
- begin
- Inherited Create(gtk_window_dialog);
- LoadSettings;
- FSinglePage:=FLoadSinglePage;
- FPaused:=False;
- FCreating:=True;
- Try
- CreateWindow;
- Finally
- FCreating:=False;
- end;
- SetUpDebugServer;
- end;
- Procedure TMainForm.SetRunButtonBitmaps;
- begin
- FRunButtonImage.SetPixMap(FRunImages[FPaused],FRunMasks[FPaused]);
- end;
- Function TMainForm.SettingsFileName : String;
- Var
- Home : String;
- begin
- Home:=GetEnvironmentVariable('HOME');
- If (Home<>'') then
- Result:=IncludeTrailingBackslash(Home)+'.'+SConfigFile
- else
- Result:=SConfigFile;
- end;
- Procedure TMainForm.LoadSettings;
- begin
- With TIniFile.Create(SettingsFileName) do
- Try
- FLoadSinglePage:=ReadBool(SKeyParameters,SkeySinglePage,DefaultSinglePage);
- FCloseOnDisconnect:=ReadBool(SKeyParameters,SkeyCloseOnDisconnect,DefaultCloseOnConnect);
- FInsertNew:=ReadBool(SKeyParameters,SKeyInsertNew,DefaultInsertNew);
- finally
- Free;
- end;
- end;
- Procedure TMainForm.SaveSettings;
- begin
- With TIniFile.Create(SettingsFileName) do
- Try
- WriteBool(SKeyParameters,SkeySinglePage,FLoadSinglePage);
- WriteBool(SKeyParameters,SkeyCloseOnDisconnect,FCloseOnDisconnect);
- WriteBool(SKeyParameters,SKeyInsertNew,FinsertNew);
- UpdateFile;
- finally
- Free;
- end;
- end;
- { ---------------------------------------------------------------------
- Event handling.
- ---------------------------------------------------------------------}
- // GTK idle callback, to check for new connections during idle time.
- function GtkIdle (Data:pointer) : gint; Cdecl;
- begin
- With (TObject(Data) as TMainForm) do
- CheckForNewClient;
- end;
- // When input appears on one of the handles, we come here through the gtk
- // input watch.
- Procedure GtkHaveInput (Data : GPointer; Source : gint; Condition : TGDKInputCondition);cdecl;
- begin
- With (TObject(Data) as TMainForm) do
- HaveData(Source);
- end;
- // Real methods.
- Procedure TMainForm.SetupDebugServer;
- begin
- OpenDebugServer;
- FIdleHandle:=gtk_idle_add(@GtkIdle,Self);
- CloseObjConnectionCallBack:[email protected];
- end;
- Procedure TMainForm.ShutdownDebugServer;
- begin
- CloseObjConnectionCallBack:=Nil;
- gtk_idle_remove(FIdleHandle);
- CloseDebugServer;
- end;
- // tell gdk not to watch this handle any more.
- // Clean up of the associated page happens in log event.
- Procedure TMainForm.ConnectionClosed(C : TCLient);
- begin
- gdk_input_remove(gint(C.Data));
- end;
- // We get here when data is present on socket.
- Procedure TMainForm.HaveData(Handle : Gint);
- Var
- Event : TDebugEvent;
- begin
- ReadMessageEvent(Handle,Event);
- AddEventToList(Event);
- end;
- // Check if a new client has reported ?
- Function TMainForm.CheckForNewClient : TClient;
- Var
- IHandle : gint;
- L : TClientCList;
- begin
- // Writeln('Checking new client');
- Result:=CheckNewConnection;
- If Result<>Nil then
- begin
- If Not FSinglePage then
- begin
- L:=NewList(Result);
- FPages.AppendPage(L,L.TabLabel);
- FPages.Page:=L;
- // Force draw.
- Fpages.Draw(Nil);
- L.ShowNow;
- L.Draw(Nil);
- L.Clist.draw(Nil);
- end;
- IHandle:=gdk_input_add(Result.Handle,GDK_INPUT_READ,@GtkHaveInput,self);
- Result.Data:=Pointer(IHandle);
- end;
- end;
- // Add event data to the appropriate list.
- Procedure TMainForm.AddEventToList(Event : TDebugEvent);
- Const
- MsgTypeStrings : Array[-1..3] of String = ('*','?','!','!','.');
- Var
- T,D,S : String;
- L : TClientCList;
- TL : TFPgtkWidget;
- SL : TStringList;
- Index : Integer;
- begin
- With Event do
- begin
- T:=MsgTypeStrings[LogCode];
- D:=DateTimeToStr(TimeStamp);
- If FSinglePage or (logcode<>lctIdentify) then
- S:=Format(SMessageFrom,[Client.Peer,Event])
- else
- S:=Event;
- L:=Nil;
- If Assigned(Client) then
- L:=GetList(Client);
- If L=Nil then
- Writeln('No list found for event ',s)
- else
- begin
- If (LogCode=lctIdentify) then
- If Not FSinglePage then
- L.TabLabel.Text:=Event;
- If Not FPaused then
- begin
- If FInsertNew then
- begin
- Index:=0;
- L.CList.Prepend([T,D,S]);
- end
- else
- Index:=L.CList.Append([T,D,S]);
- L.Clist.SetPixMap(Index,0,FMsgImages[logCode],FmsgMasks[LogCode]);
- end;
- If LogCode=lctStop then
- begin
- L.Client:=Nil; // New clients MAY have the same addresspointer as existing;
- If (Not FSinglePage) and FCloseOnDisconnect then
- L.Free;
- end;
- end;
- end;
- CheckForNewClient;
- end;
- // Create new list.
- Function TMainForm.NewList(Client : TClient) : TClientCList;
- begin
- Result:=TClientCList.Create(Client);
- If Client<>Nil then
- Result.TabLabel:=TfpGtkLabel.Create(SNewClient);
- end;
- // Get page index on which messages for client are shown.
- // Only call when FSinglePage is not true
- Function TMainForm.GetClientPageIndex(Client : TClient) : Integer;
- Var
- P : TFPgtkWidget;
- begin
- With FPages,Children do
- begin
- Result:=Count-1;
- While Result>=0 do
- begin
- P:=GetChildOnPage(Result);
- if Not(P is TClientClist) or
- (TClientClist(P).Client<>Client) Then
- Dec(Result)
- end
- end;
- end;
- // Get list on which messages for client are shown.
- // Only call when FSinglePage is not true
- Function TMainForm.GetList(Client : TClient) : TClientCList;
- Var
- I : Integer;
- P : TFPgtkWidget;
- begin
- If FSinglePage then
- Result:=FList
- else
- begin
- With FPages,Children do
- For I:=0 to Count-1 do
- begin
- P:=GetChildOnPage(i);
- if P is TClientClist then
- If TClientClist(P).Client=Client Then
- begin
- Result:=TClientClist(P);
- exit
- end;
- end;
- end;
- end;
- // Return current list.
- Function TMainForm.CurrentList : TClientClist;
- begin
- If FSinglePage then
- Result:=FList
- else
- Result:=FPages.Page as TClientCList;
- end;
- // Write list contents to file.
- Procedure TMainForm.SaveToFile(C : TClientCList; FN : String);
- Var
- F : System.text;
- I,J : Integer;
- S,T : String;
- P : PGdkPixmap;
- M : PGdkBitmap;
- begin
- Assign(F,FN);
- rewrite(F);
- Try
- With C.Clist do
- For I:=0 To count-1 do
- begin
- GetPixmap(I,0,P,M);
- For J:=-1 to 3 do
- If (FMsgImages[J]=P) then
- T:=MsgTypes[J];
- S:=T+' '+CellText[i,1]+' '+Celltext[I,2];
- Writeln(F,S);
- end;
- finally
- System.Close(f);
- end;
- end;
- { ---------------------------------------------------------------------
- Callbacks for user events.
- ---------------------------------------------------------------------}
- Procedure TMainForm.FileClearClick(Sender : TFPGtkObject; Data : Pointer);
- Var
- L:TClientClist;
- begin
- L:=CurrentList;
- If L<>Nil then
- L.Clist.Clear;
- end;
- Procedure TMainForm.DialogSetFilename(Sender : TFPGtkWindow;Data : Pointer; Action : Integer;Initiator : TFPGtkObject);
- type
- PString = ^AnsiString;
- begin
- PString(Data)^:=(Sender as TFPgtkFileSelection).Filename;
- end;
- Function TMainForm.GetFileName(ATitle : String) : String;
- var
- FS : TFPgtkFileSelection;
- begin
- FS := TFPgtkFileSelection.Create (gtk_window_dialog);
- Result:='';
- with FS do
- begin
- Title:=ATitle;
- OKButton.ConnectClicked (@(CloseWithResult), inttopointer(drOk));
- CancelButton.ConnectClicked (@(CloseWindow), nil);
- if Not execute (nil, @Result, @DialogSetFilename) = drOk then
- Result:='';
- end;
- end;
- Procedure TMainForm.FileSaveClick(Sender : TFPGtkObject; Data : Pointer);
- Var
- L:TClientClist;
- FN : String;
- begin
- L:=CurrentList;
- If L<>Nil then
- begin
- FN:=GetFileName(SSaveFileTitle);
- If (FN<>'') then
- SaveToFile(L,Fn);
- end;
- end;
- Procedure TMainForm.FileCopyClick(Sender : TFPGtkObject; Data : Pointer);
- // not used for the moment; need to figure out a way to do this.
- begin
- end;
- Procedure TMainForm.FilePauseClick(Sender : TFPGtkObject; Data : Pointer);
- begin
- If (Sender<>FFilePause) then
- With FFilePause do
- Active:=Not Active;
- FPaused:=FFilePause.Active;
- SetRunButtonBitmaps;
- end;
- Procedure TMainForm.FileCloseClick(Sender : TFPGtkObject; Data : Pointer);
- Var
- L : TClientCList;
- begin
- L:=CurrentList;
- If (L<>Nil) and (L.Client=Nil) then
- L.Free;
- end;
- Procedure TMainForm.FileExitClick(Sender : TFPGtkObject; Data : Pointer);
- begin
- ShutdownDebugServer;
- Close;
- end;
- Procedure TMainForm.OptionsClick(Sender : TFPGtkObject; Data : Pointer);
- Type
- PBoolean = ^boolean;
- begin
- If not FCreating then
- begin
- PBoolean(data)^:=Not PBoolean(data)^;
- SaveSettings;
- If (@FLoadSinglePage=Data) then
- ShowMessage(SCaption,SNeedsRestart);
- end;
- end;
- Procedure TMainForm.HelpAboutClick(Sender : TFPGtkObject; Data : Pointer);
- begin
- With TAboutForm.Create do
- Execute(Nil,Nil,Nil);
- end;
- Function TMainForm.OnDeleteEvent(Sender:TFPgtkWidget; Event:PGdkEvent; data:pointer): boolean;
- begin
- ShutdownDebugServer;
- Result:=True;
- end;
- end.
|