installer/UnitfrmMain.pas
author Christian Hammacher <bmasterc@gmail.com>
Mon Dec 18 22:15:04 2006 +0000 (2006-12-18)
changeset 277 a50090ca6e6a
parent 274 4461dca354a5
child 285 05c677265fbc
permissions -rw-r--r--
quickfix for ftp function
     1 unit UnitfrmMain;
     2 
     3 interface
     4 
     5 uses
     6   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
     7   Dialogs, TFlatRadioButtonUnit, StdCtrls, ComCtrls, mxFlatControls, JvPageList,
     8   ExtCtrls, JvExControls, JvComponent, TFlatButtonUnit, jpeg, TFlatEditUnit,
     9   TFlatGaugeUnit, ImgList, FileCtrl, Registry, CheckLst, TFlatComboBoxUnit,
    10   TFlatCheckBoxUnit, IdBaseComponent, IdComponent, IdTCPConnection,
    11   IdTCPClient, IdFTP, IdException, IdAntiFreezeBase, IdAntiFreeze,
    12   IdIntercept, IdLogBase, IdLogFile, pngimage;
    13 
    14 type
    15   TfrmMain = class(TForm)
    16     jplWizard: TJvPageList;
    17     jspWelcome: TJvStandardPage;
    18     pnlButtons: TPanel;
    19     bvlSpace: TBevel;
    20     cmdNext: TFlatButton;
    21     cmdCancel: TFlatButton;
    22     imgInstall: TImage;
    23     lblWelcome: TLabel;
    24     lblInfo1: TLabel;
    25     lblInfo2: TLabel;
    26     lblInfo3: TLabel;
    27     jspLicense: TJvStandardPage;
    28     pnlLicense: TPanel;
    29     imgIcon1: TImage;
    30     lblTitle1: TLabel;
    31     lblSubTitle1: TLabel;
    32     freLicense: TmxFlatRichEdit;
    33     frbAgree: TFlatRadioButton;
    34     ftbDontAgree: TFlatRadioButton;
    35     jspInstallMethod: TJvStandardPage;
    36     pnlHeader2: TPanel;
    37     imgIcon2: TImage;
    38     lblTitle2: TLabel;
    39     lblSubTitle2: TLabel;
    40     lblInstallMethod: TLabel;
    41     pnlInstallMethod: TPanel;
    42     frbDedicatedServer: TFlatRadioButton;
    43     frbListenServer: TFlatRadioButton;
    44     frbSelectMod: TFlatRadioButton;
    45     frbFTP: TFlatRadioButton;
    46     cmdBack: TFlatButton;
    47     jspFTP: TJvStandardPage;
    48     pnlHeader3: TPanel;
    49     imgIcon3: TImage;
    50     lblTitle3: TLabel;
    51     lblSubTitle3: TLabel;
    52     lblStep1: TLabel;
    53     pnlFTPData: TPanel;
    54     lblHost: TLabel;
    55     txtHost: TFlatEdit;
    56     lblUserName: TLabel;
    57     txtUserName: TFlatEdit;
    58     txtPassword: TFlatEdit;
    59     lblPassword: TLabel;
    60     txtPort: TFlatEdit;
    61     lblPort: TLabel;
    62     lblStep2: TLabel;
    63     cmdConnect: TFlatButton;
    64     pnlDirectory: TPanel;
    65     trvDirectories: TTreeView;
    66     lblStep4: TLabel;
    67     jspInstallProgress: TJvStandardPage;
    68     pnlHeader5: TPanel;
    69     imgIcon4: TImage;
    70     lblTitle5: TLabel;
    71     lblSubTitle5: TLabel;
    72     ggeAll: TFlatGauge;
    73     lblProgress: TLabel;
    74     ggeItem: TFlatGauge;
    75     rtfDetails: TmxFlatRichEdit;
    76     lblDetails: TLabel;
    77     bvlSpace2: TBevel;
    78     ilImages: TImageList;
    79     bvlSpacer1: TBevel;
    80     bvlSpacer2: TBevel;
    81     bvlSpacer3: TBevel;
    82     bvlSpacer5: TBevel;
    83     jspSelectMod: TJvStandardPage;
    84     pnlSelectMod: TPanel;
    85     imgIcon5: TImage;
    86     lblSelectMod: TLabel;
    87     lblSelectModInfo: TLabel;
    88     bvlSelectMod: TBevel;
    89     lblInfo: TLabel;
    90     chkPassive: TFlatCheckBox;
    91     lblStep3: TLabel;
    92     pnlOS: TPanel;
    93     optWindows: TFlatRadioButton;
    94     optLinux: TFlatRadioButton;
    95     IdFTP: TIdFTP;
    96     cmdProxySettings: TFlatButton;
    97     IdAntiFreeze: TIdAntiFreeze;
    98     frbStandaloneServer: TFlatRadioButton;
    99     tmrSpeed: TTimer;
   100     IdLogFile: TIdLogFile;
   101     shpMods: TShape;
   102     trvMods: TTreeView;
   103     FlatRadioButton1: TFlatRadioButton;
   104     procedure jvwStepsCancelButtonClick(Sender: TObject);
   105     procedure cmdCancelClick(Sender: TObject);
   106     procedure cmdNextClick(Sender: TObject);
   107     procedure CheckNext(Sender: TObject);
   108     procedure cmdBackClick(Sender: TObject);
   109     procedure cmdConnectClick(Sender: TObject);
   110     procedure jplWizardChange(Sender: TObject);
   111     procedure FormCreate(Sender: TObject);
   112     procedure cmdProxySettingsClick(Sender: TObject);
   113     procedure txtPortChange(Sender: TObject);
   114     procedure trvDirectoriesExpanded(Sender: TObject; Node: TTreeNode);
   115     procedure trvDirectoriesChange(Sender: TObject; Node: TTreeNode);
   116     procedure IdFTPWork(Sender: TObject; AWorkMode: TWorkMode;
   117       const AWorkCount: Integer);
   118     procedure FormClose(Sender: TObject; var Action: TCloseAction);
   119     procedure tmrSpeedTimer(Sender: TObject);
   120     procedure trvDirectoriesExpanding(Sender: TObject; Node: TTreeNode;
   121       var AllowExpansion: Boolean);
   122     procedure trvDirectoriesCollapsing(Sender: TObject; Node: TTreeNode;
   123       var AllowCollapse: Boolean);
   124     procedure trvModsClick(Sender: TObject);
   125     procedure trvDirectoriesMouseDown(Sender: TObject;
   126       Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
   127   private
   128     OldProgress: Integer;
   129     CurrProgress: Integer;
   130   public
   131     procedure ExceptionHandler(Sender: TObject; E: Exception);
   132   end;
   133 
   134 var
   135   frmMain: TfrmMain;
   136 
   137 var VERSION: String = '<none>';
   138 
   139 implementation
   140 
   141 uses UnitFunctions, UnitfrmProxy, UnitInstall, UnitSelectModPath;
   142 
   143 {$R *.dfm}
   144 
   145 procedure TfrmMain.jvwStepsCancelButtonClick(Sender: TObject);
   146 begin
   147   Close;
   148 end;
   149 
   150 procedure TfrmMain.cmdCancelClick(Sender: TObject);
   151 begin
   152   Close;
   153 end;
   154 
   155 procedure TfrmMain.cmdNextClick(Sender: TObject);
   156 var ePath: String;
   157     eRegistry: TRegistry;
   158     eStr: TStringList;
   159     CurNode: TTreeNode;
   160     eOS: TOS;
   161     i: integer;
   162 begin
   163   { FTP }
   164   if jplWizard.ActivePage = jspFTP then begin
   165     if not IdFTP.Connected then
   166       IdFTP.Connect;
   167     eStr := TStringList.Create;
   168     ePath := '/';
   169     CurNode := trvDirectories.Selected;
   170     if (Assigned(CurNode)) then begin
   171       repeat
   172         ePath := '/' + CurNode.Text + ePath;
   173         CurNode := CurNode.Parent;
   174       until (not Assigned(CurNode));
   175     end;
   176     IdFTP.ChangeDir(ePath);
   177     IdFTP.List(eStr, '', False);
   178     if eStr.IndexOf('gameinfo.txt') = -1 then begin
   179       MessageBox(Handle, 'Invalid directory. Please select your mod directory and try again.', PChar(Application.Title), MB_ICONWARNING);
   180       eStr.Free;
   181       exit;
   182     end
   183     else
   184       eStr.Free;
   185 
   186     // design stuff
   187     trvDirectories.Enabled := False;
   188     cmdConnect.Enabled := False;
   189     optWindows.Enabled := False;
   190     optLinux.Enabled := False;
   191     Screen.Cursor := crHourGlass;
   192 
   193     if optWindows.Checked then
   194       eOS := osWindows
   195     else
   196       eOS := osLinux;
   197 
   198     jspInstallProgress.Show;
   199     // installation
   200     Screen.Cursor := crAppStart;
   201     InstallFTP(eOS);
   202   end
   203   else if jplWizard.ActivePage = jspInstallProgress then
   204     Close
   205   else if jplWizard.ActivePage = jspSelectMod then begin
   206     { Dedicated Server }
   207     if (frbDedicatedServer.Checked) or (frbStandaloneServer.Checked) then begin
   208       ePath := trvMods.Selected.Text;
   209       if ePath = 'Counter-Strike:Source' then
   210         ePath := 'cstrike'
   211       else if ePath = 'Day of Defeat:Source' then
   212         ePath := 'dod'
   213       else
   214         ePath := 'hl2mp';
   215       ePath := 'SteamApps\' + trvMods.Selected.Parent.Text + '\source dedicated server\' + ePath;
   216       // install it
   217       if frbDedicatedServer.Checked then begin
   218         if DirectoryExists(SteamPath + ePath) then begin
   219           jspInstallProgress.Show;
   220           InstallDedicated(IncludeTrailingPathDelimiter(SteamPath + ePath), True);
   221         end
   222         else begin
   223           MessageBox(Handle, 'Error: The directory of the mod you selected doesn''t exist any more. Run Dedicated Server with the chosen mod and try again.', PChar(Application.Title), MB_ICONERROR);
   224           jspSelectMod.Show;
   225           exit;
   226         end;
   227       end
   228       else begin
   229         if DirectoryExists(StandaloneServer + ePath) then begin
   230           jspInstallProgress.Show;
   231           InstallDedicated(IncludeTrailingPathDelimiter(StandaloneServer + ePath), False)
   232         end
   233         else begin
   234           MessageBox(Handle, 'Error: The directory of the mod you selected doesn''t exist (any more). Run Half-Life Dedicated Server with the chosen mod again and restart.', PChar(Application.Title), MB_ICONERROR);
   235           jspSelectMod.Show;
   236           exit;
   237         end;
   238       end;
   239     end;
   240     { Listen Server }
   241     if frbListenServer.Checked then begin
   242       ePath := trvMods.Selected.Text;
   243       if ePath = 'Counter-Strike:Source' then
   244         ePath := SteamPath + 'SteamApps\' + trvMods.Selected.Parent.Text + '\counter-strike source\cstrike'
   245       else if ePath = 'Half-Life 2 Deathmatch' then
   246         ePath := SteamPath + 'SteamApps\' + trvMods.Selected.Parent.Text + '\half-life 2 deathmatch\hl2mp'
   247       else
   248         ePath := SteamPath + 'SteamApps\' + trvMods.Selected.Parent.Text + '\day of defeat source\dod';
   249 
   250       if Pos(SteamPath, ePath) = 0 then
   251         MessageBox(Handle, 'An error occured. Please report this bug to the Metamod:Source team and post a new thread on the forums of www.amxmodx.org.', PChar(Application.Title), MB_ICONSTOP)
   252       else begin
   253          if not FileExists(ePath + '\gameinfo.txt') then begin
   254           MessageBox(Handle, 'You have to play this game once before installing Metamod:Source. Do that and try again.', PChar(Application.Title), MB_ICONWARNING);
   255           exit;
   256         end;
   257 
   258         jspInstallProgress.Show;
   259         InstallListen(IncludeTrailingPathDelimiter(ePath));
   260       end;
   261     end;
   262     { Custom mod below }
   263   end
   264   else if jplWizard.ActivePage <> jspInstallMethod then
   265     jplWizard.NextPage
   266   else begin
   267     if frbDedicatedServer.Checked then begin    // Dedicated Server
   268       eRegistry := TRegistry.Create(KEY_READ);
   269       try
   270         eRegistry.RootKey := HKEY_CURRENT_USER;
   271         if eRegistry.OpenKey('Software\Valve\Steam', False) then begin
   272           ePath := eRegistry.ReadString('SteamPath');
   273           ePath := IncludeTrailingPathDelimiter(StringReplace(ePath, '/', '\', [rfReplaceAll]));
   274           SteamPath := ePath;
   275 
   276           ePath := ePath + 'SteamApps\';
   277           if DirectoryExists(ePath) then begin
   278             trvMods.Items.Clear;
   279             // Check Mods
   280             eStr := GetAllFiles(ePath + '*.*', faDirectory, False, True, False);
   281             for i := 0 to eStr.Count -1 do begin
   282               CurNode := trvMods.Items.Add(nil, eStr[i]);
   283 
   284               if DirectoryExists(ePath + eStr[i] + '\source dedicated server\cstrike') then
   285                 trvMods.Items.AddChild(CurNode, 'Counter-Strike:Source');
   286               if DirectoryExists(ePath + eStr[i] + '\source dedicated server\dod') then
   287                 trvMods.Items.AddChild(CurNode, 'Day of Defeat:Source');
   288               if DirectoryExists(ePath + eStr[i] + '\source dedicated server\hl2mp') then
   289                 trvMods.Items.AddChild(CurNode, 'Half-Life 2 Deatmatch');
   290 
   291               if CurNode.Count = 0 then
   292                 CurNode.Free
   293               else
   294                 CurNode.Expand(False);
   295             end;
   296             // Misc
   297             jspSelectMod.Show;
   298             trvMods.Selected := nil;
   299             cmdNext.Enabled := False;
   300           end
   301           else
   302             MessageBox(Handle, 'You have to run Dedicated Server once before installing Metamod:Source!', 'Error', MB_ICONWARNING);
   303         end
   304         else
   305           MessageBox(Handle, 'You haven''t installed Steam yet! Download it at www.steampowered.com, install Dedicated Server and try again.', 'Error', MB_ICONWARNING);
   306       finally
   307         eRegistry.Free;
   308       end;
   309     end
   310     else if frbListenServer.Checked then begin  // Listen Server
   311       eRegistry := TRegistry.Create(KEY_READ);
   312       try
   313         eRegistry.RootKey := HKEY_CURRENT_USER;
   314         if eRegistry.OpenKey('Software\Valve\Steam', False) then begin
   315           ePath := eRegistry.ReadString('SteamPath');
   316           ePath := IncludeTrailingPathDelimiter(StringReplace(ePath, '/', '\', [rfReplaceAll]));
   317           SteamPath := ePath;
   318 
   319           ePath := ePath + 'SteamApps\';
   320           if DirectoryExists(ePath) then begin
   321             trvMods.Items.Clear;
   322             // Check Mods
   323             eStr := GetAllFiles(ePath + '*.*', faDirectory, False, True, False);
   324             for i := 0 to eStr.Count -1 do begin
   325               CurNode := trvMods.Items.Add(nil, eStr[i]);
   326 
   327               if DirectoryExists(ePath + eStr[i] + '\counter-strike source') then
   328                 trvMods.Items.AddChild(CurNode, 'Counter-Strike:Source');
   329               if DirectoryExists(ePath + eStr[i] + '\day of defeat source') then
   330                 trvMods.Items.AddChild(CurNode, 'Day of Defeat:Source');
   331               if DirectoryExists(ePath + eStr[i] + '\half-life 2 deathmatch') then
   332                 trvMods.Items.AddChild(CurNode, 'Half-Life 2 Deatmatch');
   333 
   334               if CurNode.Count = 0 then
   335                 CurNode.Free
   336               else
   337                 CurNode.Expand(False);
   338             end;
   339             // Misc
   340             jspSelectMod.Show;
   341             trvMods.Selected := nil;
   342             cmdNext.Enabled := False;
   343           end
   344           else
   345             MessageBox(Handle, 'You haven''t installed Steam yet! Download it at www.steampowered.com, install Dedicated Server and try again.', 'Error', MB_ICONWARNING);
   346         end
   347         else
   348           MessageBox(Handle, 'You haven''t installed Steam yet! Download it at www.steampowered.com, install Dedicated Server and try again.', 'Error', MB_ICONWARNING);
   349       finally
   350         eRegistry.Free;
   351       end;
   352     end
   353     else if frbStandaloneServer.Checked then begin // Standalone Server
   354       eRegistry := TRegistry.Create;
   355       try
   356         eRegistry.RootKey := HKEY_CURRENT_USER;
   357         if eRegistry.OpenKey('Software\Valve\HLServer', False) then begin
   358           StandaloneServer := IncludeTrailingPathDelimiter(eRegistry.ReadString('InstallPath'));
   359           if DirectoryExists(StandaloneServer + 'cstrike') then
   360             trvMods.Items.Add(nil, 'Counter-Strike:Source');
   361           if DirectoryExists(StandaloneServer + 'dod') then
   362             trvMods.Items.Add(nil, 'Day of Defeat:Source');
   363           if DirectoryExists(StandaloneServer + 'hl2mp') then
   364             trvMods.Items.Add(nil, 'Half-Life 2 Deatmatch');
   365           jspSelectMod.Show;
   366           cmdNext.Enabled := False;
   367         end
   368         else
   369           MessageBox(Handle, 'You haven''t installed Half-Life Dedicated Server yet!',  'Error', MB_ICONWARNING);
   370       finally
   371         eRegistry.Free;
   372       end;
   373     end
   374     else if frbSelectMod.Checked then begin 
   375       { Custom mod }
   376       if frmSelectModPath.ShowModal = mrOk then begin
   377         jspInstallProgress.Show;
   378         InstallCustom(IncludeTrailingPathDelimiter(frmSelectModPath.trvDirectory.SelectedFolder.PathName), osWindows);
   379       end;
   380     end
   381     else if frbFTP.Checked then // FTP
   382       jspFTP.Show;
   383   end;
   384 end;
   385 
   386 procedure TfrmMain.CheckNext(Sender: TObject);
   387 begin
   388   cmdNext.Enabled := frbAgree.Checked;
   389 end;
   390 
   391 procedure TfrmMain.cmdBackClick(Sender: TObject);
   392 begin
   393   if jplWizard.ActivePage = jspFTP then
   394     jspInstallMethod.Show
   395   else begin
   396     jplWizard.PrevPage;
   397     cmdBack.Visible := jplWizard.ActivePageIndex <> 0;
   398   end;
   399 end;
   400 
   401 procedure TfrmMain.cmdConnectClick(Sender: TObject);
   402 var i: integer;
   403     eStr: TStringList;
   404     CurNode: TTreeNode;
   405 begin
   406   if (Trim(txtHost.Text) = '') or (Trim(txtUsername.Text) = '') then
   407     MessageBox(Handle, 'Please fill in each field!', PChar(Application.Title), MB_ICONWARNING)
   408   else if cmdConnect.Caption = 'Connect' then begin
   409     // ... design stuff ...
   410     Screen.Cursor := crHourGlass;
   411     cmdConnect.Enabled := False;
   412     cmdProxySettings.Enabled := False;
   413     txtHost.Enabled := False;
   414     txtPort.Enabled := False;
   415     txtUsername.Enabled := False;
   416     txtPassword.Enabled := False;
   417     chkPassive.Enabled := False;
   418     cmdConnect.Caption := 'Connecting...';
   419     // ... set values ...
   420     IdFTP.Host := txtHost.Text;
   421     IdFTP.Port := StrToInt(txtPort.Text);
   422     IdFTP.Username := txtUsername.Text;
   423     IdFTP.Passive := chkPassive.Checked;
   424     IdFTP.Password := txtPassword.Text;
   425     // ... connect and check values etc ...
   426     try
   427       IdFTP.Connect(True, 15000);
   428       // ... scan for initial directory ...
   429       eStr := TStringList.Create;
   430       eStr.Text := StringReplace(IdFTP.RetrieveCurrentDir, '/', #13, [rfReplaceAll]);
   431       for i := eStr.Count -1 downto 0 do begin
   432         if eStr[i] = '' then
   433           eStr.Delete(i);
   434       end;
   435       // ... connect successful, change captions ...
   436       trvDirectories.Enabled := True;
   437       cmdConnect.Enabled := True;
   438       cmdConnect.Caption := 'Disconnect';
   439 
   440       CurNode := nil;
   441       if eStr.Count <> 0 then begin
   442         for i := 0 to eStr.Count -1 do
   443           CurNode := trvDirectories.Items.AddChild(CurNode, eStr[i]);
   444       end;
   445       if trvDirectories.Items.Count <> 0 then
   446         trvDirectories.Items.Item[0].Expand(True);
   447       eStr.Free;
   448 
   449       // ... scan for directories ...
   450       with GetAllDirs do begin
   451         for i := 0 to Count -1 do
   452           trvDirectories.Items.AddChild(trvDirectories.Items.AddChild(CurNode, Strings[i]), 'Scanning...');
   453         Free;
   454       end;
   455 
   456       if Assigned(CurNode) then
   457         CurNode.Expand(False);
   458     except
   459       on E: Exception do begin
   460         // reset button properties
   461         cmdConnect.Enabled := True;
   462         txtHost.Enabled := True;
   463         txtPort.Enabled := True;
   464         txtUsername.Enabled := True;
   465         txtPassword.Enabled := True;
   466         chkPassive.Enabled := True;
   467         cmdProxySettings.Enabled := True;
   468         cmdNext.Enabled := False;
   469         cmdConnect.Caption := 'Connect';
   470         // analyze messages
   471         if Pos('Login incorrect.', E.Message) <> 0 then begin // login failed
   472           MessageBox(Handle, 'Login incorrect. Check your FTP settings and try again.', PChar(Application.Title), MB_ICONWARNING);
   473           txtUsername.SetFocus;
   474           txtUsername.SelectAll;
   475         end
   476         else if Pos('Host not found.', E.Message) <> 0 then begin // host not found
   477           MessageBox(Handle, 'The entered host couldn''t be found. Check your settings and try again.', PChar(Application.Title), MB_ICONWARNING);
   478           txtHost.SetFocus;
   479           txtHost.SelectAll;
   480         end
   481         else if Pos('Connection refused.', E.Message) <> 0 then begin // wrong port (?)
   482           MessageBox(Handle, 'The host refused the connection. Check your port and try again.', PChar(Application.Title), MB_ICONWARNING);
   483           txtPort.SetFocus;
   484           txtPort.SelectAll;
   485         end
   486         else if E is EIdProtocolReplyError then begin // wrong port
   487           MessageBox(Handle, 'The port you entered is definitely wrong. Check it and try again.', PChar(Application.Title), MB_ICONWARNING);
   488           txtPort.SetFocus;
   489           txtPort.SelectAll;
   490         end
   491         else
   492           MessageBox(Handle, PChar(E.Message), PChar(Application.Title), MB_ICONWARNING); // unknown error
   493         // ... connect failed, leave procedure ...
   494         Screen.Cursor := crDefault;
   495         exit;
   496       end;
   497     end;
   498 
   499     Screen.Cursor := crDefault;
   500   end
   501   else begin
   502     Screen.Cursor := crHourGlass;
   503     IdFTP.Quit;
   504     trvDirectories.Items.Clear;
   505     trvDirectories.Enabled := False;
   506     cmdConnect.Enabled := True;
   507     cmdProxySettings.Enabled := True;
   508     txtHost.Enabled := True;
   509     txtPort.Enabled := True;
   510     txtUsername.Enabled := True;
   511     txtPassword.Enabled := True;
   512     chkPassive.Enabled := True;
   513     cmdConnect.Caption := 'Connect';
   514     cmdNext.Enabled := False;
   515     Screen.Cursor := crDefault;
   516   end;
   517 end;
   518 
   519 procedure TfrmMain.jplWizardChange(Sender: TObject);
   520 begin
   521   if (jplWizard.ActivePage = jspInstallProgress) then begin
   522     cmdNext.Caption := '&Finish';
   523     cmdNext.Enabled := False;
   524     cmdBack.Visible := False;
   525   end
   526   else begin
   527     cmdNext.Caption := '&Next >';
   528     cmdNext.Enabled := True;
   529     cmdBack.Visible := jplWizard.ActivePageIndex <> 0;
   530   end;
   531 
   532   if (jplWizard.ActivePage = jspLicense) then
   533     cmdNext.Enabled := frbAgree.Checked;
   534 
   535   if (jplWizard.ActivePage = jspFTP) then
   536     cmdNext.Enabled := False;
   537 end;
   538 
   539 procedure TfrmMain.FormCreate(Sender: TObject);
   540 begin
   541   if LowerCase(ParamStr(1)) = '-logftp' then begin
   542     MessageBox(Handle, 'FTP installation will be logged to FTP.log!', PChar(Application.Title), MB_ICONINFORMATION);
   543     IdLogFile.Filename := ExtractFilePath(ParamStr(0)) + 'FTP.log';
   544     IdLogFile.Active := True;
   545   end;
   546 
   547   rtfDetails.Clear;
   548 end;
   549 
   550 procedure TfrmMain.cmdProxySettingsClick(Sender: TObject);
   551 begin
   552   frmProxy.ShowModal;
   553   // Apply Proxy Settings
   554   case frmProxy.cboProxy.ItemIndex of
   555     0: IdFTP.ProxySettings.ProxyType := fpcmNone; // none
   556     1: IdFTP.ProxySettings.ProxyType := fpcmHttpProxyWithFtp; // HTTP Proxy with FTP
   557     2: IdFTP.ProxySettings.ProxyType := fpcmOpen; // Open
   558     3: IdFTP.ProxySettings.ProxyType := fpcmSite; // Site
   559     4: IdFTP.ProxySettings.ProxyType := fpcmTransparent; // Transparent
   560     5: IdFTP.ProxySettings.ProxyType := fpcmUserPass; // User (Password)
   561     6: IdFTP.ProxySettings.ProxyType := fpcmUserSite; // User (Site)
   562   end;
   563 
   564   IdFTP.ProxySettings.Host := frmProxy.txtHost.Text;
   565   IdFTP.ProxySettings.UserName := frmProxy.txtPort.Text;
   566   IdFTP.ProxySettings.Password := frmProxy.txtPassword.Text;
   567   IdFTP.ProxySettings.Port := StrToInt(frmProxy.txtPort.Text);
   568 end;
   569 
   570 procedure TfrmMain.txtPortChange(Sender: TObject);
   571 var i: integer;
   572 begin
   573   if txtPort.Text = '' then
   574     txtPort.Text := '21'
   575   else begin
   576     // check if value is numeric...
   577     for i := Length(txtPort.Text) downto 1 do begin
   578       if Pos(txtPort.Text[i], '0123456789') = 0 then begin
   579         txtPort.Text := '21';
   580         txtPort.SelStart := 4;
   581         exit;
   582       end;
   583     end;
   584   end;
   585 end;
   586 
   587 procedure TfrmMain.trvDirectoriesExpanded(Sender: TObject;
   588   Node: TTreeNode);
   589 var ePath: String;
   590     CurNode: TTreeNode;
   591     i: integer;
   592 begin
   593   if Node.Item[0].Text = 'Scanning...' then begin // no directories added yet
   594     Screen.Cursor := crHourGlass;
   595     // get complete path
   596     ePath := '/';
   597     CurNode := Node;
   598     repeat
   599       ePath := '/' + CurNode.Text + ePath;
   600       CurNode := CurNode.Parent;
   601     until (not Assigned(CurNode));
   602     // change dir and add directories in it
   603     try
   604       Repaint;
   605       IdFTP.ChangeDir(ePath);
   606       with GetAllDirs do begin
   607         Node.Item[0].Free;
   608         for i := 0 to Count -1 do begin
   609           trvDirectories.Items.AddChild(trvDirectories.Items.AddChild(Node, Strings[i]), 'Scanning...');
   610         end;
   611         Free;
   612       end;
   613     finally
   614       Application.ProcessMessages;
   615     end;
   616     Screen.Cursor := crDefault;
   617   end;
   618 end;
   619 
   620 procedure TfrmMain.trvDirectoriesChange(Sender: TObject; Node: TTreeNode);
   621 begin
   622   cmdNext.Enabled := Assigned(trvDirectories.Selected);
   623 end;
   624 
   625 procedure TfrmMain.IdFTPWork(Sender: TObject; AWorkMode: TWorkMode;
   626   const AWorkCount: Integer);
   627 begin
   628   if AWorkCount > 15 then begin
   629     ggeItem.Progress := AWorkCount;
   630     CurrProgress := AWorkCount;
   631   end;
   632 
   633   if Cancel then
   634     IdFTP.Abort;
   635     
   636   Application.ProcessMessages;
   637 end;
   638 
   639 procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction);
   640 begin
   641   if (jplWizard.ActivePage = jspFTP) and (IdFTP.Connected) then
   642     IdFTP.Quit;
   643   if (jplWizard.ActivePage = jspInstallProgress) and (ggeAll.Progress <> ggeAll.MaxValue) and (not Cancel) then begin
   644     if MessageBox(Handle, 'Do you really want to cancel the installation?', PChar(Application.Title), MB_ICONQUESTION + MB_YESNO) = mrYes then begin
   645       Screen.Cursor := crDefault;
   646       Application.OnException := ExceptionHandler;
   647       Cancel := True;
   648       if IdFTP.Connected then
   649         IdFTP.Quit;
   650     end
   651     else
   652       Action := caNone;
   653   end;
   654 end;
   655 
   656 procedure TfrmMain.ExceptionHandler(Sender: TObject; E: Exception);
   657 begin
   658   // IF any exceptions were raised after close, nobody would want them so leave this empty
   659 end;
   660 
   661 procedure TfrmMain.tmrSpeedTimer(Sender: TObject);
   662 begin
   663   Caption := CalcSpeed(OldProgress, CurrProgress);
   664   OldProgress := CurrProgress;
   665 end;
   666 
   667 procedure TfrmMain.trvDirectoriesExpanding(Sender: TObject;
   668   Node: TTreeNode; var AllowExpansion: Boolean);
   669 begin
   670   Node.ImageIndex := 1;
   671   Node.SelectedIndex := 1;
   672 end;
   673 
   674 procedure TfrmMain.trvDirectoriesCollapsing(Sender: TObject;
   675   Node: TTreeNode; var AllowCollapse: Boolean);
   676 begin
   677   Node.ImageIndex := 0;
   678   Node.SelectedIndex := 0;
   679 end;
   680 
   681 procedure TfrmMain.trvModsClick(Sender: TObject);
   682 begin
   683   if Assigned(trvMods.Selected) then
   684     cmdNext.Enabled := Assigned(trvMods.Selected.Parent)
   685   else
   686     cmdNext.Enabled := False;
   687 end;
   688 
   689 procedure TfrmMain.trvDirectoriesMouseDown(Sender: TObject;
   690   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
   691 var Node: TTreeNode;
   692 begin
   693   Node := trvDirectories.GetNodeAt(X, Y);
   694   if (Assigned(Node)) then begin
   695     if (Node.DisplayRect(True).Right < X) then
   696       trvDirectories.Selected := nil;
   697   end;
   698 end;
   699 
   700 end.