mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-28 06:23:48 +02:00
746 lines
19 KiB
ObjectPascal
746 lines
19 KiB
ObjectPascal
{
|
|
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:=@Self.ConnectionClosed;
|
|
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.
|