IdComponent.pas 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. { $HDR$}
  2. {**********************************************************************}
  3. { Unit archived using Team Coherence }
  4. { Team Coherence is Copyright 2002 by Quality Software Components }
  5. { }
  6. { For further information / comments, visit our WEB site at }
  7. { http://www.TeamCoherence.com }
  8. {**********************************************************************}
  9. {}
  10. { $Log: 10105: IdComponent.pas
  11. {
  12. { Rev 1.0 2002.11.12 10:33:40 PM czhower
  13. }
  14. unit IdComponent;
  15. interface
  16. uses
  17. Classes,
  18. IdAntiFreezeBase, IdBaseComponent, IdGlobal, IdStack, IdResourceStrings,
  19. SysUtils;
  20. type
  21. TIdStatus = ( hsResolving,
  22. hsConnecting,
  23. hsConnected,
  24. hsDisconnecting,
  25. hsDisconnected,
  26. hsStatusText,
  27. ftpTransfer, // These are to eliminate the TIdFTPStatus and the
  28. ftpReady, // coresponding event
  29. ftpAborted); // These can be use din the other protocols to.
  30. const
  31. IdStati: array[TIdStatus] of string = (
  32. RSStatusResolving,
  33. RSStatusConnecting,
  34. RSStatusConnected,
  35. RSStatusDisconnecting,
  36. RSStatusDisconnected,
  37. RSStatusText,
  38. RSStatusText,
  39. RSStatusText,
  40. RSStatusText);
  41. type
  42. TIdStatusEvent = procedure(ASender: TObject; const AStatus: TIdStatus;
  43. const AStatusText: string) of object;
  44. TWorkMode = (wmRead, wmWrite);
  45. TWorkInfo = record
  46. Current: Integer;
  47. Max: Integer;
  48. Level: Integer;
  49. end;
  50. TWorkBeginEvent = procedure(Sender: TObject; AWorkMode: TWorkMode;
  51. const AWorkCountMax: Integer) of object;
  52. TWorkEndEvent = procedure(Sender: TObject; AWorkMode: TWorkMode) of object;
  53. TWorkEvent = procedure(Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: Integer)
  54. of object;
  55. TIdComponent = class(TIdBaseComponent)
  56. protected
  57. FOnStatus: TIdStatusEvent;
  58. FOnWork: TWorkEvent;
  59. FOnWorkBegin: TWorkBeginEvent;
  60. FOnWorkEnd: TWorkEndEvent;
  61. FWorkInfos: array[TWorkMode] of TWorkInfo;
  62. //
  63. procedure DoStatus(AStatus: TIdStatus); overload;
  64. procedure DoStatus(AStatus: TIdStatus; const aaArgs: array of const); overload;
  65. // GetLocalName cannot be static/class method.
  66. // CBuilder doesnt handle it correctly for a prop accessor
  67. function GetLocalName: string;
  68. //
  69. property OnWork: TWorkEvent read FOnWork write FOnWork;
  70. property OnWorkBegin: TWorkBeginEvent read FOnWorkBegin write FOnWorkBegin;
  71. property OnWorkEnd: TWorkEndEvent read FOnWorkEnd write FOnWorkEnd;
  72. public
  73. procedure BeginWork(AWorkMode: TWorkMode; const ASize: Integer = 0); virtual;
  74. constructor Create(axOwner: TComponent); override;
  75. destructor Destroy; override;
  76. procedure DoWork(AWorkMode: TWorkMode; const ACount: Integer); virtual;
  77. procedure EndWork(AWorkMode: TWorkMode); virtual;
  78. //
  79. property LocalName: string read GetLocalName;
  80. published
  81. property OnStatus: TIdStatusEvent read FOnStatus write FOnStatus;
  82. end;
  83. implementation
  84. Uses
  85. SyncObjs;
  86. var
  87. GInstanceCount: Integer = 0;
  88. GStackCriticalSection: TCriticalSection;
  89. { TIdComponent }
  90. constructor TIdComponent.Create(axOwner: TComponent);
  91. begin
  92. inherited Create(axOwner);
  93. GStackCriticalSection.Acquire; try
  94. Inc(GInstanceCount);
  95. if GInstanceCount = 1 then begin
  96. GStack := TIdStack.CreateStack;
  97. end;
  98. finally GStackCriticalSection.Release; end;
  99. end;
  100. destructor TIdComponent.Destroy;
  101. begin
  102. inherited Destroy;
  103. // After inherited - do at last possible moment
  104. GStackCriticalSection.Acquire; try
  105. Dec(GInstanceCount);
  106. if GInstanceCount = 0 then begin
  107. // This CS will guarantee that during the FreeAndNil nobody will try to use
  108. // or construct GStack
  109. FreeAndNil(GStack);
  110. end;
  111. finally GStackCriticalSection.Release; end;
  112. end;
  113. procedure TIdComponent.DoStatus(AStatus: TIdStatus);
  114. begin
  115. DoStatus(AStatus, []);
  116. end;
  117. procedure TIdComponent.DoStatus(AStatus: TIdStatus; const aaArgs: array of const);
  118. begin
  119. //We do it this way because Format can sometimes cause
  120. //an AV if the variable array is blank and there is something
  121. //like a %s or %d. This is why there was sometimes an AV
  122. //in TIdFTP
  123. if assigned(OnStatus) then begin
  124. if Length(aaArgs)=0 then
  125. OnStatus(Self, AStatus, Format(IdStati[AStatus], [''])) {Do not Localize}
  126. else
  127. OnStatus(Self, AStatus, Format(IdStati[AStatus], aaArgs));
  128. end;
  129. end;
  130. function TIdComponent.GetLocalName: string;
  131. begin
  132. Result := GStack.WSGetHostName;
  133. end;
  134. procedure TIdComponent.BeginWork(AWorkMode: TWorkMode; const ASize: Integer = 0);
  135. begin
  136. Inc(FWorkInfos[AWorkMode].Level);
  137. if FWorkInfos[AWorkMode].Level = 1 then begin
  138. FWorkInfos[AWorkMode].Max := ASize;
  139. FWorkInfos[AWorkMode].Current := 0;
  140. if assigned(OnWorkBegin) then begin
  141. OnWorkBegin(Self, AWorkMode, ASize);
  142. end;
  143. end;
  144. end;
  145. procedure TIdComponent.DoWork(AWorkMode: TWorkMode; const ACount: Integer);
  146. begin
  147. if FWorkInfos[AWorkMode].Level > 0 then begin
  148. Inc(FWorkInfos[AWorkMode].Current, ACount);
  149. if assigned(OnWork) then begin
  150. OnWork(Self, AWorkMode, FWorkInfos[AWorkMode].Current);
  151. end;
  152. end;
  153. end;
  154. procedure TIdComponent.EndWork(AWorkMode: TWorkMode);
  155. begin
  156. if FWorkInfos[AWorkMode].Level = 1 then begin
  157. if assigned(OnWorkEnd) then begin
  158. OnWorkEnd(Self, AWorkMode);
  159. end;
  160. end;
  161. Dec(FWorkInfos[AWorkMode].Level);
  162. end;
  163. initialization
  164. GStackCriticalSection := TCriticalSection.Create;
  165. finalization
  166. // Dont Free. If shutdown is from another Init section, it can cause GPF when stack
  167. // tries to access it. App will kill it off anyways, so just let it leak
  168. // FreeAndNil(GStackCriticalSection);
  169. end.