{**************************************************************************************************} { } { Project JEDI Code Library (JCL) } { } { The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); } { you may not use this file except in compliance with the License. You may obtain a copy of the } { License at http://www.mozilla.org/MPL/ } { } { Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF } { ANY KIND, either express or implied. See the License for the specific language governing rights } { and limitations under the License. } { } { The Original Code is JclOtaUtils.pas. } { } { The Initial Developer of the Original Code is Petr Vones. } { Portions created by Petr Vones are Copyright (C) of Petr Vones. } { } { Contributors: } { Florent Ouchet (outchy) } { } {**************************************************************************************************} { } { Unit owner: Florent Ouchet } { Last modified: $Date: 2006/02/02 19:57:08 $ } { } {**************************************************************************************************} unit JclOtaUtils; interface {$I jcl.inc} {$I crossplatform.inc} uses SysUtils, Classes, Windows, Controls, ComCtrls, ActnList, Menus, {$IFDEF MSWINDOWS} JclDebug, {$ENDIF MSWINDOWS} ToolsAPI; const MapFileOptionDetailed = 3; type // note to developers // to avoid JCL exceptions to be reported as Borland's exceptions in automatic // bug reports, all entry points should be protected with this code model: // uses // JclOtaUtils; // try // // except // on ExceptionObj: TObject do // begin // JclExpertShowExceptionDialog(ExceptionObj); // raise; // end; // end; // entry points for experts are usually: // - initialization sections // - finalization sections // - Register procedures // - expert entry point // - Action update events // - Action execute events // - notifier callback functions // - ... (non exhaustive list) EJclExpertException = class (Exception) {$IFDEF MSWINDOWS} private FStackInfo: TJclStackInfoList; {$ENDIF MSWINDOWS} public constructor CreateTrace(const Msg: string); {$IFDEF MSWINDOWS} destructor Destroy; override; property StackInfo: TJclStackInfoList read FStackInfo; {$ENDIF MSWINDOWS} end; TJclOTASettings = class (TObject) private FKeyName: string; FBaseKeyName: string; public constructor Create(ExpertName: string); function LoadBool(Name: string; Def: Boolean): Boolean; function LoadString(Name: string; Def: string): string; function LoadInteger(Name: string; Def: Integer): Integer; procedure LoadStrings(Name: string; List: TStrings); procedure SaveBool(Name: string; Value: Boolean); procedure SaveString(Name: string; Value: string); procedure SaveInteger(Name: string; Value: Integer); procedure SaveStrings(Name: string; List: TStrings); property KeyName: string read FKeyName; property BaseKeyName: string read FBaseKeyName; end; // Note: we MUST use an interface as the type of the Expert parameter // and not an object to avoid a bug in C++ Builder 5 compiler. If we // used an object, the compiler would crash or give internal error GH4148 // being obviously lost trying to resolve almost circular references // between this unit and the JclOtaConfigurationForm unit. IJclOTAOptionsCallback = interface; TJclOTAAddPageFunc = procedure (AControl: TControl; PageName: string; Expert: IJclOTAOptionsCallback) of object; IJclOTAOptionsCallback = interface procedure AddConfigurationPages(AddPageFunc: TJclOTAAddPageFunc); procedure ConfigurationClosed(AControl: TControl; SaveChanges: Boolean); end; TJclOTAExpertBase = class(TInterfacedObject, IJclOTAOptionsCallback) private FEnvVariables: TStringList; FRootDir: string; FServices: IOTAServices; FName: string; FNTAServices: INTAServices; FSettings: TJclOTASettings; function GetModuleHInstance: Cardinal; function GetActiveProject: IOTAProject; function GetProjectGroup: IOTAProjectGroup; function GetRootDir: string; procedure ReadEnvVariables; procedure ConfigurationActionUpdate(Sender: TObject); procedure ConfigurationActionExecute(Sender: TObject); public class procedure AddExpert(AExpert: TJclOTAExpertBase); class procedure RemoveExpert(AExpert: TJclOTAExpertBase); class function GetExpertCount: Integer; class function GetExpert(Index: Integer): TJclOTAExpertBase; class function ConfigurationDialog(StartName: string = ''): Boolean; class procedure CheckToolBarButton(AToolBar: TToolBar; AAction: TCustomAction); class function GetActionCount: Integer; class function GetAction(Index: Integer): TAction; class function ActionSettings: TJclOtaSettings; public constructor Create(AName: string); virtual; destructor Destroy; override; function FindExecutableName(const MapFileName, OutputDirectory: string; var ExecutableFileName: string): Boolean; function GetDrcFileName(const Project: IOTAProject): string; function GetMapFileName(const Project: IOTAProject): string; function GetOutputDirectory(const Project: IOTAProject): string; function IsInstalledPackage(const Project: IOTAProject): Boolean; function IsPackage(const Project: IOTAProject): Boolean; function SubstitutePath(const Path: string): string; procedure AddConfigurationPages(AddPageFunc: TJclOTAAddPageFunc); virtual; procedure ConfigurationClosed(AControl: TControl; SaveChanges: Boolean); virtual; procedure RegisterCommands; virtual; procedure UnregisterCommands; virtual; procedure RegisterAction(Action: TCustomAction); procedure UnregisterAction(Action: TCustomAction); property ActiveProject: IOTAProject read GetActiveProject; property Settings: TJclOTASettings read FSettings; property Name: string read FName; property NTAServices: INTAServices read FNTAServices; property ProjectGroup: IOTAProjectGroup read GetProjectGroup; property RootDir: string read GetRootDir; property Services: IOTAServices read FServices; property ModuleHInstance: Cardinal read GetModuleHInstance; end; TJclOTAExpert = class(TJclOTAExpertBase, IOTAWizard) protected procedure AfterSave; procedure BeforeSave; procedure Destroyed; procedure Modified; procedure Execute; function GetIDString: string; function GetName: string; function GetState: TWizardState; end; // procedure SaveOptions(const Options: IOTAOptions; const FileName: string); function JclExpertShowExceptionDialog(AExceptionObj: TObject): Boolean; {$IFDEF BDS} procedure RegisterSplashScreen; procedure RegisterAboutBox; {$ENDIF BDS} implementation uses {$IFDEF HAS_UNIT_VARIANTS} Variants, {$ENDIF HAS_UNIT_VARIANTS} Forms, Graphics, Dialogs, {$IFDEF MSWINDOWS} ImageHlp, JclRegistry, {$ENDIF MSWINDOWS} {$IFDEF KYLIX} JclBorlandTools, {$ENDIF KYLIX} JclFileUtils, JclStrings, JclSysInfo, JclOtaConsts, JclOtaResources, JclOtaExceptionForm, JclOtaConfigurationForm, JclOtaActionConfigureSheet; {$IFDEF BDS} {$R 'JclImages.res'} {$ENDIF BDS} var GlobalActionList: TList = nil; GlobalActionSettings: TJclOtaSettings = nil; GlobalExpertList: TList = nil; ConfigurationAction: TAction = nil; ConfigurationMenuItem: TMenuItem = nil; ActionConfigureSheet: TJclOtaActionConfigureFrame = nil; {$IFNDEF COMPILER6_UP} OldFindGlobalComponentProc: TFindGlobalComponent = nil; {$ENDIF COMPILER6_UP} function FindActions(const Name: string): TComponent; var Index: Integer; TestAction: TCustomAction; begin try Result := nil; if Assigned(GlobalActionList) then for Index := 0 to GlobalActionList.Count-1 do begin TestAction := TCustomAction(GlobalActionList.Items[Index]); if (CompareText(Name,TestAction.Name) = 0) then Result := TestAction; end; {$IFNDEF COMPILER6_UP} if (not Assigned(Result)) and Assigned(OldFindGlobalComponentProc) then Result := OldFindGlobalComponentProc(Name) {$ENDIF COMPILER6_UP} except on ExceptionObj: TObject do begin JclExpertShowExceptionDialog(ExceptionObj); raise; end; end; end; function JclExpertShowExceptionDialog(AExceptionObj: TObject): Boolean; var AJclExpertExceptionForm: TJclExpertExceptionForm; begin AJclExpertExceptionForm := TJclExpertExceptionForm.Create(Application); try AJclExpertExceptionForm.ShowException(AExceptionObj); Result := AJclExpertExceptionForm.Execute; finally AJclExpertExceptionForm.Free; end; end; //=== { EJclExpertException } ================================================ constructor EJclExpertException.CreateTrace(const Msg: string); begin inherited Create(Msg); {$IFDEF MSWINDOWS} FStackInfo := JclCreateStackList(False, 0, nil); {$ENDIF MSWINDOWS} end; {$IFDEF MSWINDOWS} destructor EJclExpertException.Destroy; begin FreeAndNil(FStackInfo); inherited Destroy; end; {$ENDIF MSWINDOWS} { TJclOTASettings } constructor TJclOTASettings.Create(ExpertName: string); var OTAServices: IOTAServices; begin inherited Create; Supports(BorlandIDEServices,IOTAServices,OTAServices); if not Assigned(OTAServices) then raise EJclExpertException.CreateTrace(RsENoIDEServices); FBaseKeyName := StrEnsureSuffix('\', OTAServices.GetBaseRegistryKey); FKeyName := BaseKeyName + JediIDESubKey + ExpertName; end; function TJclOTASettings.LoadBool(Name: string; Def: Boolean): Boolean; begin {$IFDEF MSWINDOWS} Result := RegReadBoolDef(HKCU, KeyName, Name, Def); {$ELSE MSWINDOWS} Result := Def; {$ENDIF MSWINDOWS} end; function TJclOTASettings.LoadInteger(Name: string; Def: Integer): Integer; begin {$IFDEF MSWINDOWS} Result := RegReadIntegerDef(HKCU, KeyName, Name, Def); {$ELSE MSWINDOWS} Result := Def; {$ENDIF MSWINDOWS} end; function TJclOTASettings.LoadString(Name, Def: string): string; begin {$IFDEF MSWINDOWS} Result := RegReadStringDef(HKCU, KeyName, Name, Def); {$ELSE MSWINDOWS} Result := Def; {$ENDIF MSWINDOWS} end; procedure TJclOTASettings.LoadStrings(Name: string; List: TStrings); begin {$IFDEF MSWINDOWS} RegLoadList(HKCU, KeyName, Name, List); {$ELSE MSWINDOWS} List.Clear; {$ENDIF MSWINDOWS} end; procedure TJclOTASettings.SaveBool(Name: string; Value: Boolean); begin {$IFDEF MSWINDOWS} RegWriteBool(HKCU, KeyName, Name, Value); {$ENDIF MSWINDOWS} end; procedure TJclOTASettings.SaveInteger(Name: string; Value: Integer); begin {$IFDEF MSWINDOWS} RegWriteInteger(HKCU, KeyName, Name, Value); {$ENDIF MSWINDOWS} end; procedure TJclOTASettings.SaveString(Name, Value: string); begin {$IFDEF MSWINDOWS} RegWriteString(HKCU, KeyName, Name, Value); {$ENDIF MSWINDOWS} end; procedure TJclOTASettings.SaveStrings(Name: string; List: TStrings); begin {$IFDEF MSWINDOWS} RegSaveList(HKCU, KeyName, Name, List); {$ENDIF MSWINDOWS} end; //=== { TJclOTAExpertBase } ================================================== class function TJclOTAExpertBase.ConfigurationDialog( StartName: string): Boolean; var OptionsForm: TJclOtaOptionsForm; Index: Integer; begin OptionsForm := TJclOtaOptionsForm.Create(nil); try for Index := 0 to GetExpertCount - 1 do GetExpert(Index).AddConfigurationPages(OptionsForm.AddPage); Result := OptionsForm.Execute(StartName); finally OptionsForm.Free; end; end; class function TJclOTAExpertBase.GetExpert(Index: Integer): TJclOTAExpertBase; begin if Assigned(GlobalExpertList) then Result := TJclOTAExpertBase(GlobalExpertList.Items[Index]) else Result := nil; end; class function TJclOTAExpertBase.GetExpertCount: Integer; begin if Assigned(GlobalExpertList) then Result := GlobalExpertList.Count else Result := 0; end; class procedure TJclOTAExpertBase.AddExpert(AExpert: TJclOTAExpertBase); begin if not Assigned(GlobalExpertList) then GlobalExpertList := TList.Create; GlobalExpertList.Add(AExpert); end; class procedure TJclOTAExpertBase.RemoveExpert(AExpert: TJclOTAExpertBase); begin if Assigned(GlobalExpertList) then GlobalExpertList.Remove(AExpert); end; class function TJclOTAExpertBase.GetAction(Index: Integer): TAction; begin if Assigned(GlobalActionList) then Result := TAction(GlobalActionList.Items[Index]) else Result := nil; end; class function TJclOTAExpertBase.GetActionCount: Integer; begin if Assigned(GlobalActionList) then Result := GlobalActionList.Count else Result := 0; end; type TAccessToolButton = class(TToolButton); class procedure TJclOTAExpertBase.CheckToolBarButton(AToolBar: TToolBar; AAction: TCustomAction); var Index: Integer; AButton: TAccessToolButton; begin if Assigned(AToolBar) then for Index := AToolBar.ButtonCount - 1 downto 0 do begin AButton := TAccessToolButton(AToolBar.Buttons[Index]); if AButton.Action = AAction then begin AButton.SetToolBar(nil); AButton.Free; end; end; end; class function TJclOTAExpertBase.ActionSettings: TJclOtaSettings; begin if not Assigned(GlobalActionSettings) then GlobalActionSettings := TJclOTASettings.Create(JclActionSettings); Result := GlobalActionSettings; end; procedure TJclOTAExpertBase.ConfigurationActionExecute(Sender: TObject); begin try ConfigurationDialog(''); except on ExceptionObj: TObject do begin JclExpertShowExceptionDialog(ExceptionObj); raise; end; end; end; procedure TJclOTAExpertBase.ConfigurationActionUpdate(Sender: TObject); begin try (Sender as TAction).Enabled := True; except on ExceptionObj: TObject do begin JclExpertShowExceptionDialog(ExceptionObj); raise; end; end; end; procedure TJclOTAExpertBase.AddConfigurationPages( AddPageFunc: TJclOTAAddPageFunc); begin // AddPageFunc uses '\' as a separator in PageName to build a tree if not Assigned(ActionConfigureSheet) then begin ActionConfigureSheet := TJclOtaActionConfigureFrame.Create(Application); AddPageFunc(ActionConfigureSheet, RsActionSheet, Self); end; // override to customize end; procedure TJclOTAExpertBase.ConfigurationClosed(AControl: TControl; SaveChanges: Boolean); begin if Assigned(AControl) and (AControl = ActionConfigureSheet) then begin if SaveChanges then ActionConfigureSheet.SaveChanges; FreeAndNil(ActionConfigureSheet); end else AControl.Free; // override to customize end; constructor TJclOTAExpertBase.Create(AName: string); begin inherited Create; {$IFDEF BDS} RegisterSplashScreen; RegisterAboutBox; {$ENDIF BDS} Supports(BorlandIDEServices,IOTAServices,FServices); if not Assigned(FServices) then raise EJclExpertException.CreateTrace(RsENoIDEServices); Supports(FServices,INTAServices,FNTAServices); if not Assigned(FNTAServices) then raise EJclExpertException.CreateTrace(RsENoNTAServices); FName := AName; FEnvVariables := TStringList.Create; FSettings := TJclOTASettings.Create(FName); RegisterCommands; AddExpert(Self); end; destructor TJclOTAExpertBase.Destroy; begin RemoveExpert(Self); UnRegisterCommands; FreeAndNil(FSettings); FreeAndNil(FEnvVariables); FServices := nil; FNTAServices := nil; inherited Destroy; end; function TJclOTAExpertBase.FindExecutableName(const MapFileName, OutputDirectory: string; var ExecutableFileName: string): Boolean; var Se: TSearchRec; Res: Integer; LatestTime: Integer; FileName: TFileName; {$IFDEF MSWINDOWS} LI: LoadedImage; {$ENDIF MSWINDOWS} begin LatestTime := 0; ExecutableFileName := ''; // the latest executable file is very likely our file Res := SysUtils.FindFirst(ChangeFileExt(MapFileName, '.*'), faArchive, Se); while Res = 0 do begin FileName := PathAddSeparator(OutputDirectory) + Se.Name; {$IFDEF MSWINDOWS} if MapAndLoad(PChar(FileName), nil, @LI, False, True) then begin if (not LI.fDOSImage) and (Se.Time > LatestTime) then begin ExecutableFileName := FileName; LatestTime := Se.Time; end; UnMapAndLoad(@LI); end; {$ELSE} if Se.Time > LatestTime then begin ExecutableFileName := FileName; LatestTime := Se.Time; end; {$ENDIF MSWINDOWS} Res := SysUtils.FindNext(Se); end; SysUtils.FindClose(Se); Result := (ExecutableFileName <> ''); end; function TJclOTAExpertBase.GetActiveProject: IOTAProject; var TempProjectGroup: IOTAProjectGroup; begin TempProjectGroup := ProjectGroup; if Assigned(TempProjectGroup) then Result := TempProjectGroup.ActiveProject else Result := nil; end; function TJclOTAExpertBase.GetDrcFileName(const Project: IOTAProject): string; begin if not Assigned(Project) then raise EJclExpertException.CreateTrace(RsENoActiveProject); Result := ChangeFileExt(Project.FileName, DRCExtension); end; function TJclOTAExpertBase.GetMapFileName(const Project: IOTAProject): string; var ProjectFileName, OutputDirectory, LibPrefix, LibSuffix: string; begin if not Assigned(Project) then raise EJclExpertException.CreateTrace(RsENoActiveProject); ProjectFileName := Project.FileName; OutputDirectory := GetOutputDirectory(Project); {$IFDEF RTL140_UP} if not Assigned(Project.ProjectOptions) then raise EJclExpertException.CreateTrace(RsENoProjectOptions); LibPrefix := Trim(VarToStr(Project.ProjectOptions.Values[LIBPREFIXOptionName])); LibSuffix := Trim(VarToStr(Project.ProjectOptions.Values[LIBSUFFIXOptionName])); {$ELSE ~RTL140_UP} LibPrefix := ''; LibSuffix := ''; {$ENDIF ~RTL140_UP} Result := PathAddSeparator(OutputDirectory) + LibPrefix + PathExtractFileNameNoExt(ProjectFileName) + LibSuffix + MAPExtension; end; function TJclOTAExpertBase.GetModuleHInstance: Cardinal; begin Result := FindClassHInstance(ClassType); if Result = 0 then raise EJclExpertException.CreateTrace(RsBadModuleHInstance); end; function TJclOTAExpertBase.GetOutputDirectory(const Project: IOTAProject): string; begin if not Assigned(Project) then raise EJclExpertException.CreateTrace(RsENoActiveProject); if not Assigned(Project.ProjectOptions) then raise EJclExpertException.CreateTrace(RsENoProjectOptions); if IsPackage(Project) then begin Result := VarToStr(Project.ProjectOptions.Values[PkgDllDirOptionName]); if Result = '' then begin if not Assigned(FServices.GetEnvironmentOptions) then raise EJclExpertException.CreateTrace(RsENoEnvironmentOptions); Result := FServices.GetEnvironmentOptions.Values[BPLOutputDirOptionName]; end; end else Result := VarToStr(Project.ProjectOptions.Values[OutputDirOptionName]); Result := SubstitutePath(Trim(Result)); if Result = '' then Result := ExtractFilePath(Project.FileName); end; function TJclOTAExpertBase.GetProjectGroup: IOTAProjectGroup; var AModuleServices: IOTAModuleServices; AModule: IOTAModule; I: Integer; begin Supports(BorlandIDEServices, IOTAModuleServices, AModuleServices); if not Assigned(AModuleServices) then raise EJclExpertException.CreateTrace(RsENoModuleServices); for I := 0 to AModuleServices.ModuleCount - 1 do begin AModule := AModuleServices.Modules[I]; if not Assigned(AModule) then raise EJclExpertException.CreateTrace(RsENoModule); if AModule.QueryInterface(IOTAProjectGroup, Result) = S_OK then Exit; end; Result := nil; end; function TJclOTAExpertBase.GetRootDir: string; {$IFDEF KYLIX} var RADToolsInstallations: TJclBorRADToolInstallations; RADToolInstallation: TJclBorRADToolInstallation; {$ENDIF KYLIX} begin if FRootDir = '' then begin //(usc) another possibility for D7 or higher is to use IOTAServices.GetRootDirectory {$IFDEF MSWINDOWS} FRootDir := RegReadStringDef(HKEY_LOCAL_MACHINE, Settings.BaseKeyName, DelphiRootDirKeyValue, ''); // (rom) bugfix if using -r switch of D9 by Dan Miser if FRootDir = '' then FRootDir := RegReadStringDef(HKEY_CURRENT_USER, Settings.BaseKeyName, DelphiRootDirKeyValue, ''); {$ENDIF MSWINDOWS} {$IFDEF KYLIX} RADToolsInstallations := TJclBorRADToolInstallations.Create; try {$IFDEF KYLIX3} {$IFDEF BCB} RADToolInstallation := RADToolsInstallations.BCBInstallationFromVersion[3]; {$ELSE} RADToolInstallation := RADToolsInstallations.DelphiInstallationFromVersion[3]; {$ENDIF BCB} {$ELSE} RADToolInstallation := nil; {$ENDIF KYLIX3} if Assigned(RADToolInstallation) then FRootDir := RADToolInstallation.RootDir; finally RADToolsInstallations.Free; end; {$ENDIF KYLIX} if FRootDir = '' then raise EJclExpertException.CreateTrace(RsENoRootDir); end; Result := FRootDir; end; function TJclOTAExpertBase.IsInstalledPackage(const Project: IOTAProject): Boolean; var PackageFileName, ExecutableNameNoExt: string; APackageServices: IOTAPackageServices; I: Integer; begin if not Assigned(Project) then raise EJclExpertException.CreateTrace(RsENoActiveProject); Result := IsPackage(Project); if Result then begin Result := False; if not Assigned(Project.ProjectOptions) then raise EJclExpertException.CreateTrace(RsENoProjectOptions); if not Project.ProjectOptions.Values[RuntimeOnlyOptionName] then begin ExecutableNameNoExt := ChangeFileExt(GetMapFileName(Project), ''); Supports(BorlandIDEServices, IOTAPackageServices, APackageServices); if not Assigned(APackageServices) then raise EJclExpertException.CreateTrace(RsENoPackageServices); for I := 0 to APackageServices.PackageCount - 1 do begin PackageFileName := ChangeFileExt(APackageServices.PackageNames[I], BPLExtension); PackageFileName := GetModulePath(GetModuleHandle(PChar(PackageFileName))); if AnsiSameText(ChangeFileExt(PackageFileName, ''), ExecutableNameNoExt) then begin Result := True; Break; end; end; end; end; end; function TJclOTAExpertBase.IsPackage(const Project: IOTAProject): Boolean; var FileName, FileExtension, ProjectContent: string; Index, SourceNodePosition: Integer; ProjectFile: TStrings; begin if not Assigned(Project) then raise EJclExpertException.CreateTrace(RsENoActiveProject); FileName := Project.FileName; FileExtension := ExtractFileExt(FileName); if AnsiSameText(FileExtension, BDSPROJExtension) and FileExists(FileName) then begin ProjectFile := TStringList.Create; try ProjectFile.LoadFromFile(FileName); ProjectContent := ProjectFile.Text; SourceNodePosition := AnsiPos(' 0 do for I := 0 to FEnvVariables.Count - 1 do begin Name := FEnvVariables.Names[I]; Result := StringReplace(Result, Format('$(%s)', [Name]), FEnvVariables.Values[Name], [rfReplaceAll, rfIgnoreCase]); end; end; procedure TJclOTAExpertBase.RegisterAction(Action: TCustomAction); begin if Action.Name <> '' then begin Action.Tag := Action.ShortCut; // to restore settings Action.ShortCut := ActionSettings.LoadInteger(Action.Name, Action.ShortCut); end; if not Assigned(GlobalActionList) then begin GlobalActionList := TList.Create; {$IFDEF COMPILER6_UP} RegisterFindGlobalComponentProc(FindActions); {$ELSE COMPILER6_UP} if not Assigned(OldFindGlobalComponentProc) then begin OldFindGlobalComponentProc := FindGlobalComponent; FindGlobalComponent := FindActions; end; {$ENDIF COMPILER6_UP} end; GlobalActionList.Add(Action); end; procedure TJclOTAExpertBase.UnregisterAction(Action: TCustomAction); begin if Action.Name <> '' then ActionSettings.SaveInteger(Action.Name, Action.ShortCut); if Assigned(GlobalActionList) then begin GlobalActionList.Remove(Action); if (GlobalActionList.Count = 0) then begin FreeAndNil(GlobalActionList); {$IFDEF COMPILER6_UP} UnRegisterFindGlobalComponentProc(FindActions); {$ELSE COMPILER6_UP} FindGlobalComponent := OldFindGlobalComponentProc; {$ENDIF COMPILER6_UP} end; end; // remove action from toolbar to avoid crash when recompile package inside the IDE. CheckToolBarButton(FNTAServices.ToolBar[sCustomToolBar], Action); CheckToolBarButton(FNTAServices.ToolBar[sStandardToolBar], Action); CheckToolBarButton(FNTAServices.ToolBar[sDebugToolBar], Action); CheckToolBarButton(FNTAServices.ToolBar[sViewToolBar], Action); CheckToolBarButton(FNTAServices.ToolBar[sDesktopToolBar], Action); {$IFDEF COMPILER7_UP} CheckToolBarButton(FNTAServices.ToolBar[sInternetToolBar], Action); CheckToolBarButton(FNTAServices.ToolBar[sCORBAToolBar], Action); {$ENDIF COMPILER7_UP} end; procedure TJclOTAExpertBase.RegisterCommands; var JclIcon: TIcon; Category: string; Index: Integer; IDEMenuItem, ToolsMenuItem: TMenuItem; begin if not Assigned(ConfigurationAction) then begin Category := ''; for Index := 0 to NTAServices.ActionList.ActionCount - 1 do if CompareText(NTAServices.ActionList.Actions[Index].Name, 'ToolsOptionsCommand') = 0 then Category := NTAServices.ActionList.Actions[Index].Category; ConfigurationAction := TAction.Create(nil); JclIcon := TIcon.Create; try // not ModuleHInstance because the resource is in JclBaseExpert.bpl JclIcon.Handle := LoadIcon(HInstance, 'JCLCONFIGURE'); ConfigurationAction.ImageIndex := NTAServices.ImageList.AddIcon(JclIcon); finally JclIcon.Free; end; ConfigurationAction.Caption := RsJCLOptions; ConfigurationAction.Name := JclConfigureActionName; ConfigurationAction.Category := Category; ConfigurationAction.Visible := True; ConfigurationAction.OnUpdate := ConfigurationActionUpdate; ConfigurationAction.OnExecute := ConfigurationActionExecute; ConfigurationAction.ActionList := NTAServices.ActionList; RegisterAction(ConfigurationAction); end; if not Assigned(ConfigurationMenuItem) then begin IDEMenuItem := NTAServices.MainMenu.Items; if not Assigned(IDEMenuItem) then raise EJclExpertException.CreateTrace(RsENoIDEMenu); ToolsMenuItem := nil; for Index := 0 to IDEMenuItem.Count - 1 do if CompareText(IDEMenuItem.Items[Index].Name, 'ToolsMenu') = 0 then ToolsMenuItem := IDEMenuItem.Items[Index]; if not Assigned(ToolsMenuItem) then raise EJclExpertException.CreateTrace(RsENoToolsMenu); ConfigurationMenuItem := TMenuItem.Create(nil); ConfigurationMenuItem.Action := ConfigurationAction; ToolsMenuItem.Insert(0, ConfigurationMenuItem); end; // override to add actions and menu items end; procedure TJclOTAExpertBase.UnregisterCommands; begin if GetExpertCount = 0 then begin UnregisterAction(ConfigurationAction); FreeAndNil(ConfigurationAction); FreeAndNil(ConfigurationMenuItem); end; // override to remove actions and menu items end; //=== { TJclOTAExpert } ====================================================== procedure TJclOTAExpert.AfterSave; begin end; procedure TJclOTAExpert.BeforeSave; begin end; procedure TJclOTAExpert.Destroyed; begin end; procedure TJclOTAExpert.Execute; begin end; function TJclOTAExpert.GetIDString: string; begin Result := 'Jedi.' + ClassName; end; function TJclOTAExpert.GetName: string; begin Result := ClassName; end; function TJclOTAExpert.GetState: TWizardState; begin Result := []; end; procedure TJclOTAExpert.Modified; begin end; {$IFDEF BDS} var AboutBoxServices: IOTAAboutBoxServices = nil; AboutBoxIndex: Integer = -1; SplashScreenInitialized: Boolean = False; procedure RegisterAboutBox; var ProductImage: HBITMAP; begin if AboutBoxIndex = -1 then begin Supports(BorlandIDEServices,IOTAAboutBoxServices, AboutBoxServices); if not Assigned(AboutBoxServices) then raise EJclExpertException.CreateTrace(RsENoAboutServices); ProductImage := LoadBitmap(FindResourceHInstance(HInstance), 'JCLSPLASH'); if ProductImage = 0 then raise EJclExpertException.CreateTrace(RsENoBitmapResources); AboutBoxIndex := AboutBoxServices.AddProductInfo(RsAboutDialogTitle, RsAboutCopyright, RsAboutTitle, RsAboutDescription, 0, ProductImage, False, RsAboutLicenceStatus); end; end; procedure UnregisterAboutBox; begin if (AboutBoxIndex <> -1) and Assigned(AboutBoxServices) then begin AboutBoxServices.RemoveProductInfo(AboutBoxIndex); AboutBoxIndex := -1; AboutBoxServices := nil; end; end; procedure RegisterSplashScreen; var ProductImage: HBITMAP; begin if Assigned(SplashScreenServices) and not SplashScreenInitialized then begin ProductImage := LoadBitmap(FindResourceHInstance(HInstance), 'JCLSPLASH'); if ProductImage = 0 then raise EJclExpertException.CreateTrace(RsENoBitmapResources); // C#Builder 1 doesn't display AddProductBitmap //SplashScreenServices.AddProductBitmap(RsAboutDialogTitle, ProductImage, // False, RsAboutLicenceStatus); SplashScreenServices.AddPluginBitmap(RsAboutDialogTitle, ProductImage, False, RsAboutLicenceStatus); SplashScreenInitialized := True; end; end; {$ENDIF BDS} initialization finalization try {$IFDEF BDS} UnregisterAboutBox; {$ENDIF BDS} FreeAndNil(GlobalActionList); FreeAndNil(GlobalActionSettings); FreeAndNil(GlobalExpertList); except on ExceptionObj: TObject do begin JclExpertShowExceptionDialog(ExceptionObj); raise; end; end; //=== Helper routines ======================================================== { (rom) disabled, unused procedure SaveOptions(const Options: IOTAOptions; const FileName: string); var OptArray: TOTAOptionNameArray; I: Integer; begin OptArray := Options.GetOptionNames; with TStringList.Create do try for I := Low(OptArray) to High(OptArray) do Add(OptArray[I].Name + '=' + VarToStr(Options.Values[OptArray[I].Name])); SaveToFile(FileName); finally Free; end; end; } // History: // $Log: JclOtaUtils.pas,v $ // Revision 1.17 2006/02/02 19:57:08 outchy // IT3464: EFOpenError when the bdsproj is not on drive // // Revision 1.16 2006/01/15 19:14:41 ahuser // Delphi 7 JCL Option bugfix and layout // // Revision 1.15 2006/01/08 17:16:56 outchy // Settings reworked. // Common window for expert configurations // // Revision 1.14 2005/12/26 18:03:40 outchy // Enhanced bds support (including C#1 and D8) // Introduction of dll experts // Project types in templates // // Revision 1.13 2005/12/16 23:46:25 outchy // Added expert stack form. // Added code to display call stack on expert exception. // Fixed package extension for D2006. // // Revision 1.12 2005/10/28 04:34:27 rrossmair // - replaced {$IFDEF RTL170_UP} by more appropriate {$IFDEF BDS} // // Revision 1.11 2005/10/27 13:50:39 rrossmair // - cleaned up mistakenly expanded check-in comments // // Revision 1.10 2005/10/27 11:00:43 marquardt // cleaned up the sources and created a .rc file // // Revision 1.9 2005/10/27 08:31:08 outchy // Items add in the splash screen and in the about box of Delphi (requires at least D2005) // // Revision 1.8 2005/10/26 08:29:53 marquardt // Kylix dummy Load results fixed // // Revision 1.7 2005/10/26 03:29:44 rrossmair // - improved header information, added Date and Log CVS tags. // // Revision 1.6 2005/10/25 14:45:22 uschuster // some changes for Kylix // // Revision 1.5 2005/10/25 13:00:12 marquardt // Load and Save methods for TJclOTAExpertBase // // Revision 1.4 2005/10/25 08:27:22 marquardt // minor cleanups, deactivated unused function // // Revision 1.3 2005/10/24 12:05:51 marquardt // further cleanup // // Revision 1.2 2005/10/23 12:53:36 marquardt // further expert cleanup and integration, use of JclRegistry // // Revision 1.1 2005/10/21 12:24:41 marquardt // experts reorganized with new directory common // // Revision 1.3 2005/10/20 22:55:17 outchy // Experts are now generated by the package generator. // No WEAKPACKAGEUNIT in design-time packages. // // Revision 1.2 2005/10/20 17:19:30 outchy // Moving function calls out of Asserts // // Revision 1.1 2005/10/03 16:15:58 rrossmair // - moved over from jcl\examples\vcl\debugextension // // Revision 1.10 2005/09/17 23:01:46 outchy // user's settings are now stored in the registry (HKEY_CURRENT_USER) // // Revision 1.9 2005/08/07 13:42:38 outchy // IT3115: Adding system and user environment variables. // // Revision 1.8 2005/07/26 17:41:06 outchy // Icons can now be placed in the IDE's toolbars via the customize dialog. They are restored at the IDE's startup. // // Revision 1.7 2005/05/08 15:43:28 outchy // Compiler conditions modified for C++Builder // // Revision 1.6 2005/03/14 05:56:27 rrossmair // - fixed issue #2752 (TJclOTAUtils.SubstitutePath does not support nested environment variables) as proposed by the reporter. // end.