{ $Project$ $Workfile$ $Revision$ $DateUTC$ $Id$ This file is part of the Indy (Internet Direct) project, and is offered under the dual-licensing agreement described on the Indy website. (http://www.indyproject.org/) Copyright: (c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved. } { $Log$ } { Rev 1.1 2/8/2004 1:35:40 PM JPMugaas IdSocks is now in DotNET. Rev 1.0 2/3/2004 12:28:06 PM JPMugaas Kudzu wanted this renamed. Rev 1.27 2004.01.01 2:40:02 PM czhower Removed test ifdef Rev 1.26 1/1/2004 3:32:30 PM BGooijen Added icons for .Net Rev 1.25 2003.12.31 11:02:50 PM czhower New components now registered for .net. Rev 1.24 2003.12.25 6:55:20 PM czhower TCPServer Rev 1.23 11/22/2003 11:49:52 PM BGooijen Icons for DotNet Rev 1.22 17/11/2003 16:00:22 ANeillans Fix Delphi compile errors. Rev 1.21 11/8/2003 8:09:24 PM BGooijen fix, i mixed up some stuff Rev 1.20 11/8/2003 7:27:10 PM BGooijen DotNet Rev 1.19 2003.10.19 1:35:32 PM czhower Moved Borland define to .inc Rev 1.18 2003.10.18 11:32:42 PM czhower Changed throttler to intercept Rev 1.17 2003.10.17 6:18:50 PM czhower TIdInterceptSimLog Rev 1.16 2003.10.14 1:26:42 PM czhower Uupdates + Intercept support Rev 1.15 9/21/2003 01:10:40 AM JPMugaas Added IdThreadCOmponent to the registration in Core. Rev 1.14 2003.08.19 11:06:34 PM czhower Fixed names of scheduler units. Rev 1.13 8/19/2003 01:25:08 AM JPMugaas Unnecessary junk removed. Rev 1.12 8/15/2003 12:02:48 AM JPMugaas Incremented version number. Moved some units to new IndySuperCore package in D7. Made sure package titles are uniform in the IDE and in the .RES files. Rev 1.11 7/24/2003 03:22:00 AM JPMugaas Removed some old files. Rev 1.10 7/18/2003 4:33:12 PM SPerry Added TIdCmdTCPClient Rev 1.7 4/17/2003 05:02:26 PM JPMugaas Rev 1.6 4/11/2003 01:09:50 PM JPMugaas Rev 1.5 3/25/2003 11:12:54 PM BGooijen TIdChainEngineStack added. Rev 1.4 3/25/2003 05:02:00 PM JPMugaas TCmdTCPServer added. Rev 1.3 3/22/2003 10:14:54 PM BGooijen Added TIdServerIOHandlerChain to the palette Rev 1.2 3/22/2003 02:20:48 PM JPMugaas Updated registration. Rev 1.1 1/17/2003 04:18:44 PM JPMugaas Now compiles with new packages. Rev 1.0 11/13/2002 08:41:42 AM JPMugaas } unit IdRegisterCore; interface uses Classes; // Procedures procedure Register; implementation {$I IdCompilerDefines.inc} uses {$IFDEF FMX} Controls, {$ENDIF} {$IFDEF FPC} LResources, {$ENDIF} IdSocks, {$IFDEF HAS_TSelectionEditor} {$IFDEF FPC} PropEdits, ComponentEditors, {$ELSE} DesignIntf, DesignEditors, {$ENDIF} TypInfo, {$IFDEF VCL_2010_OR_ABOVE} Rtti, {$ENDIF} SysUtils, IdGlobal, {$ENDIF} IdBaseComponent, IdComponent, IdDsnCoreResourceStrings, IdAntiFreeze, IdCmdTCPClient, IdCmdTCPServer, IdIOHandlerStream, {$IFNDEF DOTNET} IdIcmpClient, {$ENDIF} IdInterceptSimLog, IdInterceptThrottler, IdIPMCastClient, IdIPMCastServer, IdLogDebug, IdLogEvent, IdLogFile, IdLogStream, IdSchedulerOfThread, IdSchedulerOfThreadDefault, IdSchedulerOfThreadPool, IdServerIOHandlerSocket, IdServerIOHandlerStack, IdSimpleServer, IdThreadComponent, {$IFNDEF DOTNET} IdTraceRoute, {$ENDIF} IdUDPClient, IdUDPServer, IdIOHandlerSocket, IdIOHandlerStack, IdIntercept, IdTCPServer, IdTCPClient; {$IFDEF DOTNET} {$R IconsDotNet\TIdAntiFreeze.bmp} {$R IconsDotNet\TIdCmdTCPClient.bmp} {$R IconsDotNet\TIdCmdTCPServer.bmp} {$R IconsDotNet\TIdConnectionIntercept.bmp} {$R IconsDotNet\TIdICMPClient.bmp} {$R IconsDotNet\TIdInterceptSimLog.bmp} {$R IconsDotNet\TIdInterceptThrottler.bmp} {$R IconsDotNet\TIdIOHandlerStack.bmp} {$R IconsDotNet\TIdIOHandlerStream.bmp} {$R IconsDotNet\TIdLogDebug.bmp} {$R IconsDotNet\TIdLogEvent.bmp} {$R IconsDotNet\TIdLogFile.bmp} {$R IconsDotNet\TIdLogStream.bmp} {$R IconsDotNet\TIdSchedulerOfThreadDefault.bmp} {$R IconsDotNet\TIdSchedulerOfThreadPool.bmp} {$R IconsDotNet\TIdServerIOHandlerStack.bmp} {$R IconsDotNet\TIdSimpleServer.bmp} {$R IconsDotNet\TIdTCPClient.bmp} {$R IconsDotNet\TIdTCPServer.bmp} {$R IconsDotNet\TIdThreadComponent.bmp} {$R IconsDotNet\TIdUDPClient.bmp} {$R IconsDotNet\TIdUDPServer.bmp} {$R IconsDotNet\TIdIPMCastClient.bmp} {$R IconsDotNet\TIdIPMCastServer.bmp} {$R IconsDotNet\TIdSocksInfo.bmp} {$ELSE} {$IFNDEF FPC} {$IFDEF BORLAND} {$R IdCoreRegister.dcr} {$ELSE} {$R IdCoreRegisterCool.dcr} {$ENDIF} {$ENDIF} {$ENDIF} {$IFDEF HAS_TSelectionEditor} // TIdComponentSelectionEditor is called at design-time when saving/compiling a // project. It enumerates the data types of all parameters and return values of // every event handler assigned to any Indy component, extracting the unit names // of those data types and passing them to the IDE so it can insert them into // 'uses' clauses as needed. procedure SendUnitNameToProc(const AUnitName: String; Proc: TGetStrProc); begin // Do not return the 'System' unit, otherwise it will // cause an "Identifier redeclared" compiler error! if (AUnitName <> '') and (not TextIsSame(AUnitName, 'System')) then begin {do not localize} Proc(AUnitName); end; end; {$IFDEF VCL_XE2_OR_ABOVE} // in Delphi XE2 and later, TRttiInvokableType is used to enumerate parameters // and return values, and TRttiType reports fully qualified type names, so // finding a given type's unit name is very easy... function GetUnitNameForType(const AType: TRttiType): String; begin // TRttiType.UnitName returns the unit that declares TRttiType itself // (System.Rtti), so parse the TRttiType.QualifiedName value instead... if AType <> nil then begin Result := AType.QualifiedName; SetLength(Result, Length(Result) - Length(AType.Name) - 1); end else begin Result := ''; end; end; {$ELSE} // in Delphi prior to XE2, as well as in FreePascal, TRttiInvokableType is not // available, so we have to use TypInfo RTTI to enumerating parameters and // return values, but only certain versions implement rich enough RTTI to allow // that. Let's try to pull out what we can... {$IFDEF FPC_2_6_0_OR_ABOVE} {$DEFINE HAS_tkEnumeration_UnitName} {$DEFINE HAS_tkMethod_ParamTypeInfo} {$ELSE} {$IFDEF VCL_6_OR_ABOVE} {$DEFINE HAS_tkEnumeration_UnitName} {$ENDIF} {$IFDEF VCL_2010_OR_ABOVE} {$DEFINE HAS_tkMethod_ParamTypeInfo} {$ENDIF} {$ENDIF} procedure SkipShortString(var P: PByte); begin Inc(P, 1 + Integer(P^)); end; function ReadShortString(var P: PByte): String; begin {$IFDEF VCL_2009_OR_ABOVE} Result := UTF8ToString(PShortString(P)^); {$ELSE} Result := PShortString(P)^; {$ENDIF} SkipShortString(P); end; {$IFDEF FPC_2_6_0_OR_ABOVE} function NextShortString(PS: PShortString): PShortString; begin Result := PShortString(Pointer(PS)+PByte(PS)^+1); end; {$ENDIF} function GetUnitNameFromTypeName(const ATypeName: String): String; var K: Integer; begin // check if the type is qualified K := LastDelimiter('.', ATypeName); if K <> 0 then begin Result := Copy(ATypeName, 1, K-1); end else begin // TODO: enumerate package units and find the typename... Result := ''; end; end; function GetUnitNameFromTypeInfo(const ATypeInfo: PPTypeInfo): String; var LTypeData: PTypeData; {$IFDEF HAS_tkEnumeration_UnitName} {$IFDEF FPC} PS, PSLast: PShortString; {$ELSE} LBaseTypeData: PTypeData; Value: Integer; P: PByte; {$ENDIF} {$ENDIF} begin Result := ''; if ATypeInfo = nil then begin Exit; end; if ATypeInfo^ = nil then begin Exit; end; LTypeData := GetTypeData(ATypeInfo^); case ATypeInfo^.Kind of {$IFDEF HAS_tkEnumeration_UnitName} tkEnumeration: begin {$IFDEF FPC} // the unit name iss the last string in the name list PS := @(LTypeData^.NameList); PSLast := nil; while PByte(PS)^ <> 0 do begin PSLast := PS; PS := NextShortString(PS); end; if PSLast <> nil then begin Result := PSLast^; end; {$ELSE} // the unit name follows after the name list LBaseTypeData := GetTypeData(LTypeData^.BaseType^); P := PByte(@(LBaseTypeData^.NameList)); // LongBool/WordBool/ByteBool have MinValue < 0 and arbitrary // content in Value; Boolean has Value in [0, 1] } if (ATypeInfo^ = System.TypeInfo(Boolean)) or (LBaseTypeData^.MinValue < 0) then begin for Value := 0 to 1 do begin SkipShortString(P); end; end else begin for Value := LBaseTypeData^.MinValue to LBaseTypeData^.MaxValue do begin SkipShortString(P); end; end; Result := ReadShortString(P); {$ENDIF} end; {$ENDIF} tkSet: begin Result := GetUnitNameFromTypeInfo(LTypeData^.CompType); end; {$IFDEF VCL_5_OR_ABOVE} tkClass: begin {$IFDEF VCL_2009_OR_ABOVE} Result := UTF8ToString(LTypeData^.UnitName); {$ELSE} Result := LTypeData^.UnitName; {$ENDIF} end; {$ENDIF} {$IFDEF FPC_2_6_0_OR_ABOVE} tkHelper: begin Result := LTypeData^.HelperUnit; end; {$ENDIF} {$IFDEF VCL_5_OR_ABOVE} tkInterface: begin {$IFDEF VCL_2009_OR_ABOVE} Result := UTF8ToString(LTypeData^.IntfUnit); {$ELSE} Result := LTypeData^.IntfUnit; {$ENDIF} end; {$ENDIF} {$IFDEF FPC_2_2_2_OR_ABOVE} // TODO: when was tkInterfaceRaw added? tkInterfaceRaw: begin Result := LTypeData^.RawIntfUnit; end; {$ENDIF} {$IFDEF VCL_6_OR_ABOVE} tkDynArray: begin {$IFDEF VCL_2009_OR_ABOVE} Result := UTF8ToString(LTypeData^.DynUnitName); {$ELSE} Result := LTypeData^.DynUnitName; {$ENDIF} if Result = '' then begin Result := GetUnitNameFromTypeInfo(LTypeData^.elType2); end; end; {$ENDIF} end; end; procedure GetUnitNamesForMethodType(const ATypeInfo: PTypeInfo; Proc: TGetStrProc); type PPPTypeInfo = ^PPTypeInfo; var LTypeData: PTypeData; LTypeDataPtr: PByte; K: Integer; UnitName: string; begin if ATypeInfo = nil then begin Exit; end; LTypeData := GetTypeData(ATypeInfo); LTypeDataPtr := PByte(@(LTypeData^.ParamList)); if LTypeData^.ParamCount > 0 then begin for K := 0 to LTypeData^.ParamCount-1 do begin Inc(LTypeDataPtr, SizeOf(TParamFlags)); SkipShortString(LTypeDataPtr); {$IFDEF HAS_tkMethod_ParamTypeInfo} // handled further below... SkipShortString(LTypeDataPtr); {$ELSE} UnitName := GetUnitNameFromTypeName(ReadShortString(LTypeDataPtr)); SendUnitNameToProc(UnitName, Proc); {$ENDIF} end; end; if LTypeData^.MethodKind = mkFunction then begin {$IFDEF HAS_tkMethod_ParamTypeInfo} SkipShortString(LTypeDataPtr); UnitName := GetUnitNameFromTypeInfo(PPPTypeInfo(LTypeDataPtr)^); Inc(LTypeDataPtr, SizeOf(PPTypeInfo)); {$ELSE} UnitName := GetUnitNameFromTypeName(ReadShortString(LTypeDataPtr)); {$ENDIF} SendUnitNameToProc(UnitName, Proc); end; {$IFDEF HAS_tkMethod_ParamTypeInfo} if LTypeData^.ParamCount > 0 then begin Inc(LTypeDataPtr, SizeOf(TCallConv)); for K := 0 to LTypeData^.ParamCount-1 do begin UnitName := GetUnitNameFromTypeInfo(PPPTypeInfo(LTypeDataPtr)^); SendUnitNameToProc(UnitName, Proc); Inc(LTypeDataPtr, SizeOf(PPTypeInfo)); end; end; {$ENDIF} end; {$ENDIF} type TIdBaseComponentSelectionEditor = class(TSelectionEditor) public procedure RequiresUnits(Proc: TGetStrProc); override; end; procedure TIdBaseComponentSelectionEditor.RequiresUnits(Proc: TGetStrProc); var Comp: TIdBaseComponent; I: Integer; {$IFDEF VCL_2010_OR_ABOVE} Ctx: TRttiContext; PropInfo: TRttiProperty; PropValue: TValue; {$IFDEF VCL_XE2_OR_ABOVE} PropType: TRttiMethodType; Param: TRttiParameter; {$ENDIF} {$ELSE} PropList: PPropList; PropCount: Integer; PropInfo: PPropInfo; J: Integer; {$ENDIF} begin inherited RequiresUnits(Proc); if (Designer = nil) or (Designer.Root = nil) then Exit; for I := 0 to Designer.Root.ComponentCount - 1 do begin if Designer.Root.Components[i] is TIdBaseComponent then begin Comp := TIdBaseComponent(Designer.Root.Components[i]); {$IFDEF VCL_2010_OR_ABOVE} Ctx := TRttiContext.Create; for PropInfo in Ctx.GetType(Comp.ClassType).GetProperties do begin // only interested in *assigned* event handlers // NOTE: Delphi 2010 has a problem with checking the TValue.IsEmpty // property inlined like below. It causes a "F2084 Internal Error C13394" // compiler error. So splitting up the comparison to use a local TValue // variable to work around that... { if (PropInfo.PropertyType.TypeKind = tkMethod) and (not PropInfo.GetValue(Comp).IsEmpty) then } if PropInfo.PropertyType.TypeKind = tkMethod then begin PropValue := PropInfo.GetValue(Comp); if not PropValue.IsEmpty then begin // although the System.Rtti unit was introduced in Delphi 2010, // the TRttiInvokableType class was not added to it until XE2 {$IFDEF VCL_XE2_OR_ABOVE} PropType := PropInfo.PropertyType as TRttiMethodType; for Param in PropType.GetParameters do begin SendUnitNameToProc(GetUnitNameForType(Param.ParamType), Proc); end; SendUnitNameToProc(GetUnitNameForType(PropType.ReturnType), Proc); {$ELSE} // use the System.TypInfo unit to access the parameters and return type GetUnitNamesForMethodType(PropInfo.PropertyType.Handle, Proc); {$ENDIF} end; end; end; {$ELSE} PropCount := GetPropList(Comp, PropList); if PropCount > 0 then begin try for J := 0 to PropCount-1 do begin PropInfo := PropList^[J]; // only interested in *assigned* event handlers if (PropInfo^.PropType^.Kind = tkMethod) and (GetMethodProp(Comp, PropInfo).Code <> nil) then begin GetUnitNamesForMethodType(PropInfo^.PropType^, Proc); end; end; finally FreeMem(PropList); end; end; {$ENDIF} end; end; end; {$ENDIF} procedure Register; begin {$IFNDEF FPC} RegisterComponents(RSRegIndyClients, [ TIdTCPClient ,TIdUDPClient ,TIdCmdTCPClient ,TIdIPMCastClient {$IFNDEF DOTNET} ,TIdIcmpClient ,TIdTraceRoute {$ENDIF} ]); RegisterComponents(RSRegIndyServers, [ TIdUDPServer, TIdCmdTCPServer, TIdSimpleServer, TIdTCPServer, TIdIPMCastServer ]); RegisterComponents(RSRegIndyIOHandlers,[ TIdIOHandlerStack ,TIdIOHandlerStream ,TIdServerIOHandlerStack ]); RegisterComponents(RSRegIndyIntercepts, [ TIdConnectionIntercept ,TIdInterceptSimLog ,TIdInterceptThrottler ,TIdLogDebug ,TIdLogEvent ,TIdLogFile ,TIdLogStream ]); {$IFDEF FMX} // RLebeau 8/1/2011 - FireMonkey has problems resolving references to // TIdAntiFreeze correctly because it is implemented in a design-time // package and not a run-time package. Until we can fix that properly, // we'll group TIdAntiFreeze with TControl so the IDE can filter out // TIdAntiFreeze from appearing at design-time in FireMoney projects. // Users will have to instantiate TIdAntiFreeze in code. This does not // affect VCL projects. GroupDescendentsWith(TIdAntiFreeze, TControl); {$ENDIF} RegisterComponents(RSRegIndyMisc, [ TIdSocksInfo, TIdAntiFreeze, TIdSchedulerOfThreadDefault, TIdSchedulerOfThreadPool, TIdThreadComponent ]); {$ELSE} //This is a tempoary workaround for components not fitting on the palette //in Lazarus. Unlike Delphi, Lazarus still does not have the ability to //scroll through a palette page. RegisterComponents(RSRegIndyClients+CoreSuffix, [ TIdTCPClient ,TIdUDPClient ,TIdCmdTCPClient ,TIdIPMCastClient {$IFNDEF DOTNET} ,TIdIcmpClient ,TIdTraceRoute {$ENDIF} ]); RegisterComponents(RSRegIndyServers+CoreSuffix, [ TIdUDPServer, TIdCmdTCPServer, TIdSimpleServer, TIdTCPServer, TIdIPMCastServer ]); RegisterComponents(RSRegIndyIOHandlers+CoreSuffix,[ TIdIOHandlerStack ,TIdIOHandlerStream ,TIdServerIOHandlerStack ]); RegisterComponents(RSRegIndyIntercepts+CoreSuffix, [ TIdConnectionIntercept ,TIdInterceptSimLog ,TIdInterceptThrottler ,TIdLogDebug ,TIdLogEvent ,TIdLogFile ,TIdLogStream ]); RegisterComponents(RSRegIndyMisc+CoreSuffix, [ TIdSocksInfo, TIdAntiFreeze, TIdSchedulerOfThreadDefault, TIdSchedulerOfThreadPool, TIdThreadComponent ]); {$ENDIF} {$IFDEF HAS_TSelectionEditor} RegisterSelectionEditor(TIdBaseComponent, TIdBaseComponentSelectionEditor); {$ENDIF} end; {$IFDEF FPC} initialization {$i IdRegisterCore.lrs} {$ENDIF} end.