classes.inc 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240
  1. {
  2. $Id$
  3. This file is part of the Free Component Library (FCL)
  4. Copyright (c) 1999-2000 by Michael Van Canneyt and Florian Klaempfl
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {**********************************************************************
  12. * Class implementations are in separate files. *
  13. **********************************************************************}
  14. var
  15. ClassList : TThreadlist;
  16. ClassAliasList : TStringList;
  17. {
  18. Include all message strings
  19. Add a language with IFDEF LANG_NAME
  20. just befor the final ELSE. This way English will always be the default.
  21. }
  22. {$IFDEF LANG_GERMAN}
  23. {$i constsg.inc}
  24. {$ELSE}
  25. {$IFDEF LANG_SPANISH}
  26. {$i constss.inc}
  27. {$ELSE}
  28. {$i constse.inc}
  29. {$ENDIF}
  30. {$ENDIF}
  31. { Utility routines }
  32. {$i util.inc}
  33. { TBits implementation }
  34. {$i bits.inc}
  35. { All streams implementations: }
  36. { Tstreams THandleStream TFileStream TResourcseStreams TStringStream }
  37. { TCustomMemoryStream TMemoryStream }
  38. {$i streams.inc}
  39. { TParser implementation}
  40. {$i parser.inc}
  41. { TCollection and TCollectionItem implementations }
  42. {$i collect.inc}
  43. { TList and TThreadList implementations }
  44. {$i lists.inc}
  45. { TStrings and TStringList implementations }
  46. {$i stringl.inc}
  47. { TPersistent implementation }
  48. {$i persist.inc }
  49. { TComponent implementation }
  50. {$i compon.inc}
  51. { TBasicAction implementation }
  52. {$i action.inc}
  53. { TDataModule implementation }
  54. {$i dm.inc}
  55. { Class and component registration routines }
  56. {$I cregist.inc}
  57. { Interface related stuff }
  58. {$ifdef HASINTF}
  59. {$I intf.inc}
  60. {$endif HASINTF}
  61. {**********************************************************************
  62. * Miscellaneous procedures and functions *
  63. **********************************************************************}
  64. { Point and rectangle constructors }
  65. function Point(AX, AY: Integer): TPoint;
  66. begin
  67. with Result do
  68. begin
  69. X := AX;
  70. Y := AY;
  71. end;
  72. end;
  73. function SmallPoint(AX, AY: SmallInt): TSmallPoint;
  74. begin
  75. with Result do
  76. begin
  77. X := AX;
  78. Y := AY;
  79. end;
  80. end;
  81. function Rect(ALeft, ATop, ARight, ABottom: Integer): TRect;
  82. begin
  83. with Result do
  84. begin
  85. Left := ALeft;
  86. Top := ATop;
  87. Right := ARight;
  88. Bottom := ABottom;
  89. end;
  90. end;
  91. function Bounds(ALeft, ATop, AWidth, AHeight: Integer): TRect;
  92. begin
  93. with Result do
  94. begin
  95. Left := ALeft;
  96. Top := ATop;
  97. Right := ALeft + AWidth;
  98. Bottom := ATop + AHeight;
  99. end;
  100. end;
  101. { Object filing routines }
  102. var
  103. IntConstList: TThreadList;
  104. type
  105. TIntConst = class
  106. IntegerType: PTypeInfo; // The integer type RTTI pointer
  107. IdentToIntFn: TIdentToInt; // Identifier to Integer conversion
  108. IntToIdentFn: TIntToIdent; // Integer to Identifier conversion
  109. constructor Create(AIntegerType: PTypeInfo; AIdentToInt: TIdentToInt;
  110. AIntToIdent: TIntToIdent);
  111. end;
  112. constructor TIntConst.Create(AIntegerType: PTypeInfo; AIdentToInt: TIdentToInt;
  113. AIntToIdent: TIntToIdent);
  114. begin
  115. IntegerType := AIntegerType;
  116. IdentToIntFn := AIdentToInt;
  117. IntToIdentFn := AIntToIdent;
  118. end;
  119. procedure RegisterIntegerConsts(IntegerType: Pointer; IdentToIntFn: TIdentToInt;
  120. IntToIdentFn: TIntToIdent);
  121. begin
  122. IntConstList.Add(TIntConst.Create(IntegerType, IdentToIntFn, IntToIdentFn));
  123. end;
  124. function FindIntToIdent(AIntegerType: Pointer): TIntToIdent;
  125. var
  126. i: Integer;
  127. begin
  128. with IntConstList.LockList do
  129. try
  130. for i := 0 to Count - 1 do
  131. if TIntConst(Items[i]).IntegerType = AIntegerType then
  132. exit(TIntConst(Items[i]).IntToIdentFn);
  133. Result := nil;
  134. finally
  135. IntConstList.UnlockList;
  136. end;
  137. end;
  138. function FindIdentToInt(AIntegerType: Pointer): TIdentToInt;
  139. var
  140. i: Integer;
  141. begin
  142. with IntConstList.LockList do
  143. try
  144. for i := 0 to Count - 1 do
  145. with TIntConst(Items[I]) do
  146. if TIntConst(Items[I]).IntegerType = AIntegerType then
  147. exit(IdentToIntFn);
  148. Result := nil;
  149. finally
  150. IntConstList.UnlockList;
  151. end;
  152. end;
  153. function IdentToInt(const Ident: String; var Int: LongInt;
  154. const Map: array of TIdentMapEntry): Boolean;
  155. var
  156. i: Integer;
  157. begin
  158. for i := Low(Map) to High(Map) do
  159. if CompareText(Map[i].Name, Ident) = 0 then
  160. begin
  161. Int := Map[i].Value;
  162. exit(True);
  163. end;
  164. Result := False;
  165. end;
  166. function IntToIdent(Int: LongInt; var Ident: String;
  167. const Map: array of TIdentMapEntry): Boolean;
  168. var
  169. i: Integer;
  170. begin
  171. for i := Low(Map) to High(Map) do
  172. if Map[i].Value = Int then
  173. begin
  174. Ident := Map[i].Name;
  175. exit(True);
  176. end;
  177. Result := False;
  178. end;
  179. { TPropFixup }
  180. type
  181. TPropFixup = class
  182. FInstance: TPersistent;
  183. FInstanceRoot: TComponent;
  184. FPropInfo: PPropInfo;
  185. FRootName: string;
  186. FName: string;
  187. constructor Create(AInstance: TPersistent; AInstanceRoot: TComponent;
  188. APropInfo: PPropInfo; const ARootName, AName: String);
  189. function MakeGlobalReference: Boolean;
  190. end;
  191. var
  192. GlobalFixupList: TThreadList;
  193. constructor TPropFixup.Create(AInstance: TPersistent; AInstanceRoot: TComponent;
  194. APropInfo: PPropInfo; const ARootName, AName: String);
  195. begin
  196. FInstance := AInstance;
  197. FInstanceRoot := AInstanceRoot;
  198. FPropInfo := APropInfo;
  199. FRootName := ARootName;
  200. FName := AName;
  201. end;
  202. function TPropFixup.MakeGlobalReference: Boolean;
  203. var
  204. i: Integer;
  205. s, p: PChar;
  206. begin
  207. i := Pos('.', FName);
  208. if i = 0 then
  209. exit(False);
  210. FRootName := Copy(FName, 1, i - 1);
  211. FName := Copy(FName, i + 1, Length(FName));
  212. Result := True;
  213. end;
  214. Type
  215. TInitHandler = Class(TObject)
  216. AHandler : TInitComponentHandler;
  217. AClass : TComponentClass;
  218. end;
  219. Var
  220. InitHandlerList : TList;
  221. procedure RegisterInitComponentHandler(ComponentClass: TComponentClass; Handler: TInitComponentHandler);
  222. Var
  223. I : Integer;
  224. H: TInitHandler;
  225. begin
  226. If (InitHandlerList=Nil) then
  227. InitHandlerList:=TList.Create;
  228. H:=TInitHandler.Create;
  229. H.Aclass:=ComponentClass;
  230. H.AHandler:=Handler;
  231. With InitHandlerList do
  232. begin
  233. I:=0;
  234. While (I<Count) and not H.AClass.InheritsFrom(TInitHandler(Items[i]).AClass) do
  235. Inc(I);
  236. InitHandlerList.Insert(I,H);
  237. end;
  238. end;
  239. function InitInheritedComponent(Instance: TComponent; RootAncestor: TClass): Boolean;
  240. Var
  241. I : Integer;
  242. begin
  243. I:=0;
  244. Result:=False;
  245. With InitHandlerList do
  246. begin
  247. I:=0;
  248. // Instance is the normally the lowest one, so that one should be used when searching.
  249. While Not result and (I<Count) do
  250. begin
  251. If (Instance.InheritsFrom(TInitHandler(Items[i]).AClass)) then
  252. Result:=TInitHandler(Items[i]).AHandler(Instance,RootAncestor);
  253. Inc(I);
  254. end;
  255. end;
  256. end;
  257. function InitComponentRes(const ResName: String; Instance: TComponent): Boolean;
  258. begin
  259. { !!!: Too Win32-specific }
  260. InitComponentRes := False;
  261. end;
  262. function ReadComponentRes(const ResName: String; Instance: TComponent): TComponent;
  263. begin
  264. { !!!: Too Win32-specific }
  265. ReadComponentRes := nil;
  266. end;
  267. function ReadComponentResEx(HInstance: THandle; const ResName: String): TComponent;
  268. begin
  269. { !!!: Too Win32-specific in VCL }
  270. ReadComponentResEx := nil;
  271. end;
  272. function ReadComponentResFile(const FileName: String; Instance: TComponent): TComponent;
  273. var
  274. FileStream: TStream;
  275. begin
  276. FileStream := TFileStream.Create(FileName, fmOpenRead {!!!:or fmShareDenyWrite});
  277. try
  278. Result := FileStream.ReadComponentRes(Instance);
  279. finally
  280. FileStream.Free;
  281. end;
  282. end;
  283. procedure WriteComponentResFile(const FileName: String; Instance: TComponent);
  284. var
  285. FileStream: TStream;
  286. begin
  287. FileStream := TFileStream.Create(FileName, fmCreate);
  288. try
  289. FileStream.WriteComponentRes(Instance.ClassName, Instance);
  290. finally
  291. FileStream.Free;
  292. end;
  293. end;
  294. procedure GlobalFixupReferences;
  295. var
  296. GlobalList, DoneList, ToDoList: TList;
  297. I, Index: Integer;
  298. Root: TComponent;
  299. Instance: TPersistent;
  300. Reference: Pointer;
  301. begin
  302. if not Assigned(FindGlobalComponent) then
  303. exit;
  304. {!!!: GlobalNameSpace.BeginWrite;
  305. try}
  306. GlobalList := GlobalFixupList.LockList;
  307. try
  308. if GlobalList.Count > 0 then
  309. begin
  310. ToDoList := nil;
  311. DoneList := TList.Create;
  312. ToDoList := TList.Create;
  313. try
  314. i := 0;
  315. while i < GlobalList.Count do
  316. with TPropFixup(GlobalList[i]) do
  317. begin
  318. Root := FindGlobalComponent(FRootName);
  319. if Assigned(Root) or (GetOrdProp(FInstance, FPropInfo) <> 0) then
  320. begin
  321. if Assigned(Root) then
  322. begin
  323. Reference := FindNestedComponent(Root, FName);
  324. SetOrdProp(FInstance, FPropInfo, Longint(Reference));
  325. end;
  326. // Move component to list of done components, if necessary
  327. if (DoneList.IndexOf(FInstance) < 0) and
  328. (ToDoList.IndexOf(FInstance) >= 0) then
  329. DoneList.Add(FInstance);
  330. GlobalList.Delete(i);
  331. Free; // ...the fixup
  332. end else
  333. begin
  334. // Move component to list of components to process, if necessary
  335. Index := DoneList.IndexOf(FInstance);
  336. if Index <> -1 then
  337. DoneList.Delete(Index);
  338. if ToDoList.IndexOf(FInstance) < 0 then
  339. ToDoList.Add(FInstance);
  340. Inc(i);
  341. end;
  342. end;
  343. for i := 0 to DoneList.Count - 1 do
  344. begin
  345. Instance := TPersistent(DoneList[I]);
  346. if Instance.InheritsFrom(TComponent) then
  347. Exclude(TComponent(Instance).FComponentState, csFixups);
  348. end;
  349. finally
  350. ToDoList.Free;
  351. DoneList.Free;
  352. end;
  353. end;
  354. finally
  355. GlobalFixupList.UnlockList;
  356. end;
  357. {finally
  358. GlobalNameSpace.EndWrite;
  359. end;}
  360. end;
  361. function IsStringInList(const AString: String; AList: TStrings): Boolean;
  362. var
  363. i: Integer;
  364. begin
  365. for i := 0 to AList.Count - 1 do
  366. if CompareText(AList[i], AString) = 0 then
  367. exit(True);
  368. Result := False;
  369. end;
  370. procedure GetFixupReferenceNames(Root: TComponent; Names: TStrings);
  371. var
  372. i: Integer;
  373. CurFixup: TPropFixup;
  374. begin
  375. with GlobalFixupList.LockList do
  376. try
  377. for i := 0 to Count - 1 do
  378. begin
  379. CurFixup := TPropFixup(Items[i]);
  380. if ((not Assigned(Root)) or (CurFixup.FInstanceRoot = Root)) and
  381. not IsStringInList(CurFixup.FRootName, Names) then
  382. Names.Add(CurFixup.FRootName);
  383. end;
  384. finally
  385. GlobalFixupList.UnlockList;
  386. end;
  387. end;
  388. procedure GetFixupInstanceNames(Root: TComponent;
  389. const ReferenceRootName: string; Names: TStrings);
  390. var
  391. i: Integer;
  392. CurFixup: TPropFixup;
  393. begin
  394. with GlobalFixupList.LockList do
  395. try
  396. for i := 0 to Count - 1 do
  397. begin
  398. CurFixup := TPropFixup(Items[i]);
  399. if (CurFixup.FInstanceRoot = Root) and
  400. (UpperCase(ReferenceRootName) = UpperCase(CurFixup.FRootName)) and
  401. not IsStringInList(CurFixup.FName, Names) then
  402. Names.Add(CurFixup.FName);
  403. end;
  404. finally
  405. GlobalFixupList.UnlockList;
  406. end;
  407. end;
  408. procedure RedirectFixupReferences(Root: TComponent; const OldRootName,
  409. NewRootName: string);
  410. var
  411. i: Integer;
  412. CurFixup: TPropFixup;
  413. begin
  414. with GlobalFixupList.LockList do
  415. try
  416. for i := 0 to Count - 1 do
  417. begin
  418. CurFixup := TPropFixup(Items[i]);
  419. if ((not Assigned(Root)) or (CurFixup.FInstanceRoot = Root)) and
  420. (UpperCase(OldRootName) = UpperCase(CurFixup.FRootName)) then
  421. CurFixup.FRootName := NewRootName;
  422. end;
  423. GlobalFixupReferences;
  424. finally
  425. GlobalFixupList.Unlocklist;
  426. end;
  427. end;
  428. procedure RemoveFixupReferences(Root: TComponent; const RootName: string);
  429. var
  430. i: Integer;
  431. CurFixup: TPropFixup;
  432. begin
  433. if not Assigned(GlobalFixupList) then
  434. exit;
  435. with GlobalFixupList.LockList do
  436. try
  437. for i := Count - 1 downto 0 do
  438. begin
  439. CurFixup := TPropFixup(Items[i]);
  440. if ((not Assigned(Root)) or (CurFixup.FInstanceRoot = Root)) and
  441. ((Length(RootName) = 0) or
  442. (UpperCase(RootName) = UpperCase(CurFixup.FRootName))) then
  443. begin
  444. Delete(i);
  445. CurFixup.Free;
  446. end;
  447. end;
  448. finally
  449. GlobalFixupList.UnlockList;
  450. end;
  451. end;
  452. procedure RemoveFixups(Instance: TPersistent);
  453. var
  454. i: Integer;
  455. CurFixup: TPropFixup;
  456. begin
  457. if not Assigned(GlobalFixupList) then
  458. exit;
  459. with GlobalFixupList.LockList do
  460. try
  461. for i := Count - 1 downto 0 do
  462. begin
  463. CurFixup := TPropFixup(Items[i]);
  464. if (CurFixup.FInstance = Instance) then
  465. begin
  466. Delete(i);
  467. CurFixup.Free;
  468. end;
  469. end;
  470. finally
  471. GlobalFixupList.UnlockList;
  472. end;
  473. end;
  474. function FindNestedComponent(Root: TComponent; const NamePath: string): TComponent;
  475. var
  476. Current, Found: TComponent;
  477. s, p: PChar;
  478. Name: String;
  479. begin
  480. Result := nil;
  481. if Length(NamePath) > 0 then
  482. begin
  483. Current := Root;
  484. p := PChar(NamePath);
  485. while p[0] <> #0 do
  486. begin
  487. s := p;
  488. while not (p^ in ['.', '-', #0]) do
  489. Inc(p);
  490. SetString(Name, s, p - s);
  491. Found := Current.FindComponent(Name);
  492. if (not Assigned(Found)) and (UpperCase(Name) = 'OWNER') then
  493. Found := Current;
  494. if not Assigned(Found) then exit;
  495. // Remove the dereference operator from the name
  496. if p[0] = '.' then
  497. Inc(P);
  498. if p[0] = '-' then
  499. Inc(P);
  500. if p[0] = '>' then
  501. Inc(P);
  502. Current := Found;
  503. end;
  504. end;
  505. Result := Current;
  506. end;
  507. {!!!: Should be threadvar - doesn't work for all platforms yet!}
  508. var
  509. GlobalLoaded, GlobalLists: TList;
  510. procedure BeginGlobalLoading;
  511. begin
  512. if not Assigned(GlobalLists) then
  513. GlobalLists := TList.Create;
  514. GlobalLists.Add(GlobalLoaded);
  515. GlobalLoaded := TList.Create;
  516. end;
  517. { Notify all global components that they have been loaded completely }
  518. procedure NotifyGlobalLoading;
  519. var
  520. i: Integer;
  521. begin
  522. for i := 0 to GlobalLoaded.Count - 1 do
  523. TComponent(GlobalLoaded[i]).Loaded;
  524. end;
  525. procedure EndGlobalLoading;
  526. begin
  527. { Free the memory occupied by BeginGlobalLoading }
  528. GlobalLoaded.Free;
  529. GlobalLoaded := TList(GlobalLists.Last);
  530. GlobalLists.Delete(GlobalLists.Count - 1);
  531. if GlobalLists.Count = 0 then
  532. begin
  533. GlobalLists.Free;
  534. GlobalLists := nil;
  535. end;
  536. end;
  537. function CollectionsEqual(C1, C2: TCollection): Boolean;
  538. begin
  539. // !!!: Implement this
  540. CollectionsEqual:=false;
  541. end;
  542. { Object conversion routines }
  543. procedure ObjectBinaryToText(Input, Output: TStream);
  544. procedure OutStr(s: String);
  545. begin
  546. if Length(s) > 0 then
  547. Output.Write(s[1], Length(s));
  548. end;
  549. procedure OutLn(s: String);
  550. begin
  551. OutStr(s + #10);
  552. end;
  553. procedure OutString(s: String);
  554. var
  555. res, NewStr: String;
  556. i: Integer;
  557. InString, NewInString: Boolean;
  558. begin
  559. res := '';
  560. InString := False;
  561. for i := 1 to Length(s) do begin
  562. NewInString := InString;
  563. case s[i] of
  564. #0..#31: begin
  565. if InString then
  566. NewInString := False;
  567. NewStr := '#' + IntToStr(Ord(s[i]));
  568. end;
  569. '''':
  570. if InString then NewStr := ''''''
  571. else NewStr := '''''''';
  572. else begin
  573. if not InString then
  574. NewInString := True;
  575. NewStr := s[i];
  576. end;
  577. end;
  578. if NewInString <> InString then begin
  579. NewStr := '''' + NewStr;
  580. InString := NewInString;
  581. end;
  582. res := res + NewStr;
  583. end;
  584. if InString then res := res + '''';
  585. OutStr(res);
  586. end;
  587. function ReadInt(ValueType: TValueType): LongInt;
  588. begin
  589. case ValueType of
  590. vaInt8: Result := ShortInt(Input.ReadByte);
  591. vaInt16: Result := SmallInt(Input.ReadWord);
  592. vaInt32: Result := LongInt(Input.ReadDWord);
  593. end;
  594. end;
  595. function ReadInt: LongInt;
  596. begin
  597. Result := ReadInt(TValueType(Input.ReadByte));
  598. end;
  599. function ReadSStr: String;
  600. var
  601. len: Byte;
  602. begin
  603. len := Input.ReadByte;
  604. SetLength(Result, len);
  605. Input.Read(Result[1], len);
  606. end;
  607. procedure ReadPropList(indent: String);
  608. procedure ProcessValue(ValueType: TValueType; Indent: String);
  609. procedure Stop(s: String);
  610. begin
  611. WriteLn(s);
  612. Halt;
  613. end;
  614. procedure ProcessBinary;
  615. var
  616. ToDo, DoNow, i: LongInt;
  617. lbuf: array[0..31] of Byte;
  618. s: String;
  619. begin
  620. ToDo := Input.ReadDWord;
  621. OutLn('{');
  622. while ToDo > 0 do begin
  623. DoNow := ToDo;
  624. if DoNow > 32 then DoNow := 32;
  625. Dec(ToDo, DoNow);
  626. s := Indent + ' ';
  627. Input.Read(lbuf, DoNow);
  628. for i := 0 to DoNow - 1 do
  629. s := s + IntToHex(lbuf[i], 2);
  630. OutLn(s);
  631. end;
  632. OutLn(indent + '}');
  633. end;
  634. var
  635. s: String;
  636. len: LongInt;
  637. IsFirst: Boolean;
  638. ext: Extended;
  639. begin
  640. case ValueType of
  641. vaList: begin
  642. OutStr('(');
  643. IsFirst := True;
  644. while True do begin
  645. ValueType := TValueType(Input.ReadByte);
  646. if ValueType = vaNull then break;
  647. if IsFirst then begin
  648. OutLn('');
  649. IsFirst := False;
  650. end;
  651. OutStr(Indent + ' ');
  652. ProcessValue(ValueType, Indent + ' ');
  653. end;
  654. OutLn(Indent + ')');
  655. end;
  656. vaInt8: OutLn(IntToStr(ShortInt(Input.ReadByte)));
  657. vaInt16: OutLn( IntToStr(SmallInt(Input.ReadWord)));
  658. vaInt32: OutLn(IntToStr(LongInt(Input.ReadDWord)));
  659. vaExtended: begin
  660. Input.Read(ext, SizeOf(ext));
  661. OutLn(FloatToStr(ext));
  662. end;
  663. vaString: begin
  664. OutString(ReadSStr);
  665. OutLn('');
  666. end;
  667. vaIdent: OutLn(ReadSStr);
  668. vaFalse: OutLn('False');
  669. vaTrue: OutLn('True');
  670. vaBinary: ProcessBinary;
  671. vaSet: begin
  672. OutStr('[');
  673. IsFirst := True;
  674. while True do begin
  675. s := ReadSStr;
  676. if Length(s) = 0 then break;
  677. if not IsFirst then OutStr(', ');
  678. IsFirst := False;
  679. OutStr(s);
  680. end;
  681. OutLn(']');
  682. end;
  683. vaLString:
  684. Stop('!!LString!!');
  685. vaNil:
  686. OutLn('nil');
  687. vaCollection: begin
  688. OutStr('<');
  689. while Input.ReadByte <> 0 do begin
  690. OutLn(Indent);
  691. Input.Seek(-1, soFromCurrent);
  692. OutStr(indent + ' item');
  693. ValueType := TValueType(Input.ReadByte);
  694. if ValueType <> vaList then
  695. OutStr('[' + IntToStr(ReadInt(ValueType)) + ']');
  696. OutLn('');
  697. ReadPropList(indent + ' ');
  698. OutStr(indent + ' end');
  699. end;
  700. OutLn('>');
  701. end;
  702. {vaSingle: begin OutLn('!!Single!!'); exit end;
  703. vaCurrency: begin OutLn('!!Currency!!'); exit end;
  704. vaDate: begin OutLn('!!Date!!'); exit end;
  705. vaWString: begin OutLn('!!WString!!'); exit end;}
  706. else
  707. Stop(IntToStr(Ord(ValueType)));
  708. end;
  709. end;
  710. begin
  711. while Input.ReadByte <> 0 do begin
  712. Input.Seek(-1, soFromCurrent);
  713. OutStr(indent + ReadSStr + ' = ');
  714. ProcessValue(TValueType(Input.ReadByte), Indent);
  715. end;
  716. end;
  717. procedure ReadObject(indent: String);
  718. var
  719. b: Byte;
  720. ObjClassName, ObjName: String;
  721. ChildPos: LongInt;
  722. begin
  723. // Check for FilerFlags
  724. b := Input.ReadByte;
  725. if (b and $f0) = $f0 then begin
  726. if (b and 2) <> 0 then ChildPos := ReadInt;
  727. end else begin
  728. b := 0;
  729. Input.Seek(-1, soFromCurrent);
  730. end;
  731. ObjClassName := ReadSStr;
  732. ObjName := ReadSStr;
  733. OutStr(Indent);
  734. if (b and 1) <> 0 then OutStr('inherited')
  735. else OutStr('object');
  736. OutStr(' ');
  737. if ObjName <> '' then
  738. OutStr(ObjName + ': ');
  739. OutStr(ObjClassName);
  740. if (b and 2) <> 0 then OutStr('[' + IntToStr(ChildPos) + ']');
  741. OutLn('');
  742. ReadPropList(indent + ' ');
  743. while Input.ReadByte <> 0 do begin
  744. Input.Seek(-1, soFromCurrent);
  745. ReadObject(indent + ' ');
  746. end;
  747. OutLn(indent + 'end');
  748. end;
  749. type
  750. PLongWord = ^LongWord;
  751. const
  752. signature: PChar = 'TPF0';
  753. begin
  754. if Input.ReadDWord <> PLongWord(Pointer(signature))^ then
  755. raise EReadError.Create('Illegal stream image' {###SInvalidImage});
  756. ReadObject('');
  757. end;
  758. procedure ObjectTextToBinary(Input, Output: TStream);
  759. var
  760. parser: TParser;
  761. procedure WriteString(s: String);
  762. begin
  763. Output.WriteByte(Length(s));
  764. if Length(s) > 0 then
  765. Output.Write(s[1], Length(s));
  766. end;
  767. procedure WriteInteger(value: LongInt);
  768. begin
  769. if (value >= -128) and (value <= 127) then begin
  770. Output.WriteByte(Ord(vaInt8));
  771. Output.WriteByte(Byte(value));
  772. end else if (value >= -32768) and (value <= 32767) then begin
  773. Output.WriteByte(Ord(vaInt16));
  774. Output.WriteWord(Word(value));
  775. end else begin
  776. Output.WriteByte(ord(vaInt32));
  777. Output.WriteDWord(LongWord(value));
  778. end;
  779. end;
  780. procedure ProcessProperty; forward;
  781. procedure ProcessValue;
  782. var
  783. flt: Extended;
  784. s: String;
  785. stream: TMemoryStream;
  786. begin
  787. case parser.Token of
  788. toInteger:
  789. begin
  790. WriteInteger(parser.TokenInt);
  791. parser.NextToken;
  792. end;
  793. toFloat:
  794. begin
  795. Output.WriteByte(Ord(vaExtended));
  796. flt := Parser.TokenFloat;
  797. Output.Write(flt, SizeOf(flt));
  798. parser.NextToken;
  799. end;
  800. toString:
  801. begin
  802. s := parser.TokenString;
  803. while parser.NextToken = '+' do
  804. begin
  805. parser.NextToken; // Get next string fragment
  806. parser.CheckToken(toString);
  807. s := s + parser.TokenString;
  808. end;
  809. Output.WriteByte(Ord(vaString));
  810. WriteString(s);
  811. end;
  812. toSymbol:
  813. begin
  814. if CompareText(parser.TokenString, 'True') = 0 then
  815. Output.WriteByte(Ord(vaTrue))
  816. else if CompareText(parser.TokenString, 'False') = 0 then
  817. Output.WriteByte(Ord(vaFalse))
  818. else if CompareText(parser.TokenString, 'nil') = 0 then
  819. Output.WriteByte(Ord(vaNil))
  820. else
  821. begin
  822. Output.WriteByte(Ord(vaIdent));
  823. WriteString(parser.TokenComponentIdent);
  824. end;
  825. Parser.NextToken;
  826. end;
  827. // Set
  828. '[':
  829. begin
  830. parser.NextToken;
  831. Output.WriteByte(Ord(vaSet));
  832. if parser.Token <> ']' then
  833. while True do
  834. begin
  835. parser.CheckToken(toSymbol);
  836. WriteString(parser.TokenString);
  837. parser.NextToken;
  838. if parser.Token = ']' then
  839. break;
  840. parser.CheckToken(',');
  841. parser.NextToken;
  842. end;
  843. Output.WriteByte(0);
  844. parser.NextToken;
  845. end;
  846. // List
  847. '(':
  848. begin
  849. parser.NextToken;
  850. Output.WriteByte(Ord(vaList));
  851. while parser.Token <> ')' do
  852. ProcessValue;
  853. Output.WriteByte(0);
  854. parser.NextToken;
  855. end;
  856. // Collection
  857. '<':
  858. begin
  859. parser.NextToken;
  860. Output.WriteByte(Ord(vaCollection));
  861. while parser.Token <> '>' do
  862. begin
  863. parser.CheckTokenSymbol('item');
  864. parser.NextToken;
  865. // ConvertOrder
  866. Output.WriteByte(Ord(vaList));
  867. while not parser.TokenSymbolIs('end') do
  868. ProcessProperty;
  869. parser.NextToken; // Skip 'end'
  870. Output.WriteByte(0);
  871. end;
  872. Output.WriteByte(0);
  873. parser.NextToken;
  874. end;
  875. // Binary data
  876. '{':
  877. begin
  878. Output.WriteByte(Ord(vaBinary));
  879. stream := TMemoryStream.Create;
  880. try
  881. parser.HexToBinary(stream);
  882. Output.WriteDWord(stream.Size);
  883. Output.Write(Stream.Memory^, stream.Size);
  884. finally
  885. stream.Free;
  886. end;
  887. parser.NextToken;
  888. end;
  889. else
  890. parser.Error(SInvalidProperty);
  891. end;
  892. end;
  893. procedure ProcessProperty;
  894. var
  895. name: String;
  896. begin
  897. // Get name of property
  898. parser.CheckToken(toSymbol);
  899. name := parser.TokenString;
  900. while True do begin
  901. parser.NextToken;
  902. if parser.Token <> '.' then break;
  903. parser.NextToken;
  904. parser.CheckToken(toSymbol);
  905. name := name + '.' + parser.TokenString;
  906. end;
  907. WriteString(name);
  908. parser.CheckToken('=');
  909. parser.NextToken;
  910. ProcessValue;
  911. end;
  912. procedure ProcessObject;
  913. var
  914. IsInherited: Boolean;
  915. ObjectName, ObjectType: String;
  916. begin
  917. if parser.TokenSymbolIs('OBJECT') then
  918. IsInherited := False
  919. else begin
  920. parser.CheckTokenSymbol('INHERITED');
  921. IsInherited := True;
  922. end;
  923. parser.NextToken;
  924. parser.CheckToken(toSymbol);
  925. ObjectName := '';
  926. ObjectType := parser.TokenString;
  927. parser.NextToken;
  928. if parser.Token = ':' then begin
  929. parser.NextToken;
  930. parser.CheckToken(toSymbol);
  931. ObjectName := ObjectType;
  932. ObjectType := parser.TokenString;
  933. parser.NextToken;
  934. end;
  935. WriteString(ObjectType);
  936. WriteString(ObjectName);
  937. // Convert property list
  938. while not (parser.TokenSymbolIs('END') or
  939. parser.TokenSymbolIs('OBJECT') or
  940. parser.TokenSymbolIs('INHERITED')) do
  941. ProcessProperty;
  942. Output.WriteByte(0); // Terminate property list
  943. // Convert child objects
  944. while not parser.TokenSymbolIs('END') do ProcessObject;
  945. parser.NextToken; // Skip end token
  946. Output.WriteByte(0); // Terminate property list
  947. end;
  948. const
  949. signature: PChar = 'TPF0';
  950. begin
  951. parser := TParser.Create(Input);
  952. try
  953. Output.Write(signature[0], 4);
  954. ProcessObject;
  955. finally
  956. parser.Free;
  957. end;
  958. end;
  959. procedure ObjectResourceToText(Input, Output: TStream);
  960. begin
  961. Input.ReadResHeader;
  962. ObjectBinaryToText(Input, Output);
  963. end;
  964. procedure ObjectTextToResource(Input, Output: TStream);
  965. var
  966. StartPos, SizeStartPos, BinSize: LongInt;
  967. parser: TParser;
  968. name: String;
  969. begin
  970. // Get form type name
  971. StartPos := Input.Position;
  972. parser := TParser.Create(Input);
  973. try
  974. if not parser.TokenSymbolIs('OBJECT') then parser.CheckTokenSymbol('INHERITED');
  975. parser.NextToken;
  976. parser.CheckToken(toSymbol);
  977. parser.NextToken;
  978. parser.CheckToken(':');
  979. parser.NextToken;
  980. parser.CheckToken(toSymbol);
  981. name := parser.TokenString;
  982. finally
  983. parser.Free;
  984. Input.Position := StartPos;
  985. end;
  986. // Write resource header
  987. name := UpperCase(name);
  988. Output.WriteByte($ff);
  989. Output.WriteByte(10);
  990. Output.WriteByte(0);
  991. Output.Write(name[1], Length(name) + 1); // Write null-terminated form type name
  992. Output.WriteWord($1030);
  993. SizeStartPos := Output.Position;
  994. Output.WriteDWord(0); // Placeholder for data size
  995. ObjectTextToBinary(Input, Output); // Convert the stuff!
  996. BinSize := Output.Position - SizeStartPos - 4;
  997. Output.Position := SizeStartPos;
  998. Output.WriteDWord(BinSize); // Insert real resource data size
  999. end;
  1000. { Utility routines }
  1001. function LineStart(Buffer, BufPos: PChar): PChar;
  1002. begin
  1003. Result := BufPos;
  1004. while Result > Buffer do begin
  1005. Dec(Result);
  1006. if Result[0] = #10 then break;
  1007. end;
  1008. end;
  1009. procedure CommonInit;
  1010. begin
  1011. InitHandlerList:=Nil;
  1012. IntConstList := TThreadList.Create;
  1013. GlobalFixupList := TThreadList.Create;
  1014. ClassList := TThreadList.Create;
  1015. ClassAliasList := TStringList.Create;
  1016. end;
  1017. procedure CommonCleanup;
  1018. var
  1019. i: Integer;
  1020. begin
  1021. // !!!: GlobalNameSpace.BeginWrite;
  1022. with IntConstList.LockList do
  1023. try
  1024. for i := 0 to Count - 1 do
  1025. TIntConst(Items[I]).Free;
  1026. finally
  1027. IntConstList.UnlockList;
  1028. end;
  1029. IntConstList.Free;
  1030. ClassList.Free;
  1031. ClassAliasList.Free;
  1032. RemoveFixupReferences(nil, '');
  1033. GlobalFixupList.Free;
  1034. GlobalFixupList := nil;
  1035. GlobalLists.Free;
  1036. ComponentPages.Free;
  1037. {!!!: GlobalNameSpace.Free;
  1038. GlobalNameSpace := nil;}
  1039. InitHandlerList.Free;
  1040. InitHandlerList:=Nil;
  1041. end;
  1042. { TFiler implementation }
  1043. {$i filer.inc}
  1044. { TReader implementation }
  1045. {$i reader.inc}
  1046. { TWriter implementations }
  1047. {$i writer.inc}
  1048. {$i twriter.inc}
  1049. {
  1050. $Log$
  1051. Revision 1.1 2003-10-06 20:33:58 peter
  1052. * classes moved to rtl for 1.1
  1053. * classes .inc and classes.pp files moved to fcl/classes for
  1054. backwards 1.0.x compatiblity to have it in the fcl
  1055. Revision 1.14 2003/06/04 17:40:44 michael
  1056. + Minor fix by Mattias Gaertner
  1057. Revision 1.13 2003/06/04 15:27:24 michael
  1058. + TDataModule en InitInheritedComponent erbij voor Delphi 6 compatibility
  1059. Revision 1.12 2003/04/19 14:29:25 michael
  1060. + Fix from Mattias Gaertner, closes memory leak
  1061. Revision 1.11 2002/12/02 12:04:07 sg
  1062. * Fixed handling of zero-length strings (classes.inc: When converting
  1063. empty strings from text forms to binary forms; reader.inc: When reading
  1064. an empty string from a binary serialization)
  1065. Revision 1.10 2002/09/07 15:15:24 peter
  1066. * old logs removed and tabs fixed
  1067. Revision 1.9 2002/07/16 13:32:51 florian
  1068. + skeleton for TInterfaceList added
  1069. Revision 1.8 2002/01/06 21:54:49 peter
  1070. * action classes added
  1071. }