classes.inc 29 KB

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