wresourc.pas 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724
  1. {
  2. $Id$
  3. This file is part of the Free Pascal Integrated Development Environment
  4. Copyright (c) 1998 by Berczi Gabor
  5. Resource File support objects and routines
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit WResource;
  13. interface
  14. uses Objects;
  15. const
  16. TPDataBlockSignature = ord('F')+ord('B')*256;
  17. ResourceBlockSignature = ord('R')+ord('D')*256;
  18. langDefault = 0;
  19. rcBinary = 1;
  20. type
  21. TResourceEntryHeader = packed record
  22. ID : longint;
  23. LangID : longint;
  24. Flags : longint;
  25. DataOfs: longint;
  26. DataLen: longint;
  27. end;
  28. TResourceHeader = packed record
  29. _Class : longint;
  30. Flags : longint;
  31. NameLen : word;
  32. EntryCount : word;
  33. end;
  34. TResourceFileHeader = packed record
  35. Signature : word;
  36. InfoType : word;
  37. InfoSize : longint;
  38. { ---- }
  39. TableOfs : longint;
  40. end;
  41. PResourceEntry = ^TResourceEntry;
  42. TResourceEntry = object(TObject)
  43. constructor Init(AID, ALangID, AFlags, ADataLen: longint);
  44. private
  45. ID : longint;
  46. LangID : longint;
  47. Flags : longint;
  48. DataOfs : longint;
  49. DataLen : longint;
  50. procedure BuildHeader(var Header : TResourceEntryHeader);
  51. end;
  52. PResourceEntryCollection = ^TResourceEntryCollection;
  53. TResourceEntryCollection = object(TSortedCollection)
  54. function At(Index: Sw_Integer): PResourceEntry;
  55. function Compare(Key1, Key2: Pointer): Sw_Integer; virtual;
  56. function SearchEntryForLang(ALangID: longint): PResourceEntry;
  57. end;
  58. PGlobalResourceEntryCollection = ^TGlobalResourceEntryCollection;
  59. TGlobalResourceEntryCollection = object(TSortedCollection)
  60. function At(Index: Sw_Integer): PResourceEntry;
  61. function Compare(Key1, Key2: Pointer): Sw_Integer; virtual;
  62. end;
  63. PResource = ^TResource;
  64. TResource = object(TObject)
  65. constructor Init(const AName: string; AClass, AFlags: longint);
  66. function GetName: string; virtual;
  67. function FirstThatEntry(Func: pointer): PResourceEntry; virtual;
  68. procedure ForEachEntry(Func: pointer); virtual;
  69. destructor Done; virtual;
  70. private
  71. Name : PString;
  72. _Class : longint;
  73. Flags : longint;
  74. Items : PResourceEntryCollection;
  75. procedure BuildHeader(var Header : TResourceHeader);
  76. end;
  77. TResourceCollection = object(TSortedCollection)
  78. function At(Index: Sw_Integer): PResource;
  79. function Compare(Key1, Key2: Pointer): Sw_Integer; virtual;
  80. function SearchResourceByName(const AName: string): PResource;
  81. end;
  82. PResourceCollection = ^TResourceCollection;
  83. TResourceFile = object(TObject)
  84. constructor Init(var RS: TStream; ALoad: boolean);
  85. constructor Create(var RS: TStream);
  86. constructor Load(var RS: TStream);
  87. constructor CreateFile(AFileName: string);
  88. constructor LoadFile(AFileName: string);
  89. function FirstThatResource(Func: pointer): PResource; virtual;
  90. procedure ForEachResource(Func: pointer); virtual;
  91. procedure ForEachResourceEntry(Func: pointer); virtual;
  92. function CreateResource(const Name: string; AClass, AFlags: longint): boolean; virtual;
  93. function AddResourceEntry(const ResName: string; ALangID, AFlags: longint; var Data;
  94. ADataSize: sw_integer): boolean; virtual;
  95. function AddResourceEntryFromStream(const ResName: string; ALangID, AFlags: longint;
  96. var Source: TStream; ADataSize: longint): boolean; virtual;
  97. function DeleteResourceEntry(const ResName: string; ALangID: longint): boolean; virtual;
  98. function DeleteResource(const ResName: string): boolean; virtual;
  99. procedure Flush; virtual;
  100. destructor Done; virtual;
  101. public
  102. BaseOfs: longint;
  103. function FindResource(const ResName: string): PResource;
  104. function FindResourceEntry(const ResName: string; ALangID: longint): PResourceEntry;
  105. private
  106. S : PStream;
  107. MyStream : boolean;
  108. Resources : PResourceCollection;
  109. Entries : PGlobalResourceEntryCollection;
  110. Header : TResourceFileHeader;
  111. Modified : boolean;
  112. procedure UpdateBlockDatas;
  113. function GetNextEntryID: longint;
  114. function GetTotalSize(IncludeHeaders: boolean): longint;
  115. function CalcSizes(IncludeHeaders, UpdatePosData: boolean): longint;
  116. procedure AddResEntryPtr(P: PResource; E: PResourceEntry);
  117. procedure RemoveResEntryPtr(P: PResource; E: PResourceEntry);
  118. function DeleteArea(AreaStart, AreaSize, TotalSize: longint): boolean;
  119. procedure BuildFileHeader;
  120. procedure WriteHeader;
  121. procedure WriteResourceTable;
  122. end;
  123. PResourceFile = ^TResourceFile;
  124. implementation
  125. uses CallSpec,
  126. WUtils;
  127. function TResourceEntryCollection.At(Index: Sw_Integer): PResourceEntry;
  128. begin
  129. At:=inherited At(Index);
  130. end;
  131. function TResourceEntryCollection.Compare(Key1, Key2: Pointer): Sw_Integer;
  132. var K1: PResourceEntry absolute Key1;
  133. K2: PResourceEntry absolute Key2;
  134. Re: Sw_integer;
  135. begin
  136. if K1^.LangID<K2^.LangID then Re:=-1 else
  137. if K1^.LangID>K2^.LangID then Re:= 1 else
  138. Re:=0;
  139. Compare:=Re;
  140. end;
  141. function TResourceEntryCollection.SearchEntryForLang(ALangID: longint): PResourceEntry;
  142. var P: PResourceEntry;
  143. E: TResourceEntry;
  144. Index: sw_integer;
  145. begin
  146. E.LangID:=ALangID;
  147. if Search(@E,Index)=false then P:=nil else
  148. P:=At(Index);
  149. SearchEntryForLang:=P;
  150. end;
  151. function TGlobalResourceEntryCollection.At(Index: Sw_Integer): PResourceEntry;
  152. begin
  153. At:=inherited At(Index);
  154. end;
  155. function TGlobalResourceEntryCollection.Compare(Key1, Key2: Pointer): Sw_Integer;
  156. var K1: PResourceEntry absolute Key1;
  157. K2: PResourceEntry absolute Key2;
  158. Re: Sw_integer;
  159. begin
  160. if K1^.ID<K2^.ID then Re:=-1 else
  161. if K1^.ID>K2^.ID then Re:= 1 else
  162. Re:=0;
  163. Compare:=Re;
  164. end;
  165. constructor TResourceEntry.Init(AID, ALangID, AFlags, ADataLen: longint);
  166. begin
  167. inherited Init;
  168. ID:=AID;
  169. LangID:=ALangID; Flags:=AFlags; DataLen:=ADataLen;
  170. end;
  171. procedure TResourceEntry.BuildHeader(var Header : TResourceEntryHeader);
  172. begin
  173. FillChar(Header,SizeOf(Header),0);
  174. Header.ID:=ID;
  175. Header.LangID:=LangID;
  176. Header.Flags:=Flags;
  177. Header.DataLen:=DataLen;
  178. Header.DataOfs:=DataOfs;
  179. end;
  180. constructor TResource.Init(const AName: string; AClass, AFlags: longint);
  181. begin
  182. inherited Init;
  183. Name:=NewStr(AName);
  184. _Class:=AClass;
  185. Flags:=AFlags;
  186. New(Items, Init(10,50));
  187. end;
  188. function TResource.GetName: string;
  189. begin
  190. GetName:=GetStr(Name);
  191. end;
  192. function TResource.FirstThatEntry(Func: pointer): PResourceEntry;
  193. var EP,P: PResourceEntry;
  194. I: sw_integer;
  195. begin
  196. P:=nil;
  197. for I:=0 to Items^.Count-1 do
  198. begin
  199. EP:=Items^.At(I);
  200. if Byte(Longint(CallPointerMethodLocal(Func,PreviousFramePointer,@Self,EP)))<>0 then
  201. begin
  202. P := EP;
  203. Break;
  204. end;
  205. end;
  206. FirstThatEntry:=P;
  207. end;
  208. procedure TResource.ForEachEntry(Func: pointer);
  209. var RP: PResourceEntry;
  210. I: sw_integer;
  211. begin
  212. for I:=0 to Items^.Count-1 do
  213. begin
  214. RP:=Items^.At(I);
  215. CallPointerMethodLocal(Func,PreviousFramePointer,@Self,RP);
  216. end;
  217. end;
  218. procedure TResource.BuildHeader(var Header : TResourceHeader);
  219. begin
  220. FillChar(Header,SizeOf(Header),0);
  221. Header._Class:=_Class;
  222. Header.Flags:=Flags;
  223. Header.NameLen:=length(GetName);
  224. Header.EntryCount:=Items^.Count;
  225. end;
  226. destructor TResource.Done;
  227. begin
  228. inherited Done;
  229. if Name<>nil then DisposeStr(Name); Name:=nil;
  230. if Items<>nil then Dispose(Items, Done); Items:=nil;
  231. end;
  232. function TResourceCollection.At(Index: Sw_Integer): PResource;
  233. begin
  234. At:=inherited At(Index);
  235. end;
  236. function TResourceCollection.Compare(Key1, Key2: Pointer): Sw_Integer;
  237. var K1: PResource absolute Key1;
  238. K2: PResource absolute Key2;
  239. N1,N2: string;
  240. Re: Sw_integer;
  241. begin
  242. N1:=UpcaseStr(K1^.GetName); N2:=UpcaseStr(K2^.GetName);
  243. if N1<N2 then Re:=-1 else
  244. if N1>N2 then Re:= 1 else
  245. Re:=0;
  246. Compare:=Re;
  247. end;
  248. function TResourceCollection.SearchResourceByName(const AName: string): PResource;
  249. var P,R: PResource;
  250. Index: sw_integer;
  251. begin
  252. New(R, Init(AName,0,0));
  253. if Search(R,Index)=false then P:=nil else
  254. P:=At(Index);
  255. Dispose(R, Done);
  256. SearchResourceByName:=P;
  257. end;
  258. constructor TResourceFile.Create(var RS: TStream);
  259. begin
  260. if Init(RS,false)=false then
  261. Fail;
  262. end;
  263. constructor TResourceFile.Load(var RS: TStream);
  264. begin
  265. if Init(RS,true)=false then
  266. Fail;
  267. end;
  268. constructor TResourceFile.Init(var RS: TStream; ALoad: boolean);
  269. var OK: boolean;
  270. RH: TResourceHeader;
  271. REH: TResourceEntryHeader;
  272. EndPos,I: longint;
  273. P: PResource;
  274. E: PResourceEntry;
  275. St: string;
  276. begin
  277. inherited Init;
  278. S:=@RS;
  279. New(Resources, Init(100, 1000));
  280. New(Entries, Init(500,2000));
  281. OK:=true;
  282. if ALoad=false then
  283. Modified:=true
  284. else
  285. begin
  286. BaseOfs:=S^.GetPos;
  287. S^.Read(Header,SizeOf(Header));
  288. OK:=(S^.Status=stOK) and
  289. (Header.Signature=TPDataBlockSignature) and
  290. (Header.InfoType=ResourceBlockSignature);
  291. if OK then begin S^.Seek(BaseOfs+Header.TableOfs); OK:=S^.Status=stOK; end;
  292. EndPos:=BaseOfs+Header.InfoSize;
  293. if OK then
  294. while OK and (S^.GetPos<EndPos) do
  295. begin
  296. S^.Read(RH,SizeOf(RH)); OK:=(S^.Status=stOK);
  297. if OK then begin St[0]:=chr(RH.NameLen); S^.Read(St[1],RH.NameLen); OK:=(S^.Status=stOK); end;
  298. if OK then
  299. begin
  300. New(P, Init(St,RH._Class,RH.Flags));
  301. Resources^.Insert(P);
  302. end;
  303. I:=0;
  304. while OK and (I<RH.EntryCount) do
  305. begin
  306. S^.Read(REH,SizeOf(REH)); OK:=(S^.Status=stOK);
  307. if OK then
  308. begin
  309. New(E, Init(REH.ID,REH.LangID,REH.Flags,REH.DataLen));
  310. AddResEntryPtr(P,E);
  311. end;
  312. if OK then Inc(I);
  313. end;
  314. if OK then UpdateBlockDatas;
  315. end;
  316. end;
  317. if OK=false then
  318. begin
  319. Done;
  320. Fail;
  321. end;
  322. end;
  323. function TResourceFile.FirstThatResource(Func: pointer): PResource;
  324. var RP,P: PResource;
  325. I: sw_integer;
  326. begin
  327. P:=nil;
  328. for I:=0 to Resources^.Count-1 do
  329. begin
  330. RP:=Resources^.At(I);
  331. if Byte(Longint(CallPointerMethodLocal(Func,PreviousFramePointer,@Self,RP)))<>0 then
  332. begin
  333. P := RP;
  334. Break;
  335. end;
  336. end;
  337. FirstThatResource:=P;
  338. end;
  339. procedure TResourceFile.ForEachResource(Func: pointer);
  340. var RP: PResource;
  341. I: sw_integer;
  342. begin
  343. for I:=0 to Resources^.Count-1 do
  344. begin
  345. RP:=Resources^.At(I);
  346. CallPointerMethodLocal(Func,PreviousFramePointer,@Self,RP);
  347. end;
  348. end;
  349. procedure TResourceFile.ForEachResourceEntry(Func: pointer);
  350. var E: PResourceEntry;
  351. I: sw_integer;
  352. begin
  353. for I:=0 to Entries^.Count-1 do
  354. begin
  355. E:=Entries^.At(I);
  356. CallPointerMethodLocal(Func,PreviousFramePointer,@Self,E);
  357. end;
  358. end;
  359. function TResourceFile.CreateResource(const Name: string; AClass, AFlags: longint): boolean;
  360. var OK: boolean;
  361. P: PResource;
  362. begin
  363. OK:=FindResource(Name)=nil;
  364. if OK then
  365. begin
  366. New(P, Init(Name,AClass,AFlags));
  367. Resources^.Insert(P);
  368. Modified:=true;
  369. end;
  370. CreateResource:=OK;
  371. end;
  372. function TResourceFile.AddResourceEntry(const ResName: string; ALangID, AFlags: longint; var Data;
  373. ADataSize: sw_integer): boolean;
  374. const BlockSize = 4096;
  375. var OK: boolean;
  376. P: PResource;
  377. E: PResourceEntry;
  378. RemSize,CurOfs,FragSize: longint;
  379. begin
  380. P:=FindResource(ResName);
  381. OK:=P<>nil;
  382. if OK then
  383. OK:=(P^.Items^.SearchEntryForLang(ALangID)=nil);
  384. if OK then
  385. begin
  386. New(E, Init(GetNextEntryID,ALangID, AFlags, ADataSize));
  387. AddResEntryPtr(P,E);
  388. UpdateBlockDatas;
  389. RemSize:=ADataSize; CurOfs:=0;
  390. S^.Seek(BaseOfs+E^.DataOfs);
  391. while (RemSize>0) do
  392. begin
  393. FragSize:=Min(RemSize,BlockSize);
  394. S^.Write(PByteArray(@Data)^[CurOfs],FragSize);
  395. Dec(RemSize,FragSize); Inc(CurOfs,FragSize);
  396. end;
  397. Modified:=true;
  398. end;
  399. AddResourceEntry:=OK;
  400. end;
  401. function TResourceFile.AddResourceEntryFromStream(const ResName: string; ALangID, AFlags: longint;
  402. var Source: TStream; ADataSize: longint): boolean;
  403. const BufSize = 4096;
  404. var OK: boolean;
  405. P: PResource;
  406. E: PResourceEntry;
  407. RemSize,FragSize: longint;
  408. Buf: pointer;
  409. begin
  410. P:=FindResource(ResName);
  411. OK:=P<>nil;
  412. if OK then
  413. OK:=(P^.Items^.SearchEntryForLang(ALangID)=nil);
  414. if OK then
  415. begin
  416. New(E, Init(GetNextEntryID, ALangID, AFlags, ADataSize));
  417. AddResEntryPtr(P,E);
  418. UpdateBlockDatas;
  419. GetMem(Buf,BufSize);
  420. RemSize:=ADataSize;
  421. S^.Seek(BaseOfs+E^.DataOfs);
  422. while (RemSize>0) do
  423. begin
  424. FragSize:=Min(RemSize,BufSize);
  425. Source.Read(Buf^,FragSize);
  426. S^.Write(Buf^,FragSize);
  427. Dec(RemSize,FragSize);
  428. end;
  429. FreeMem(Buf,BufSize);
  430. Modified:=true;
  431. end;
  432. AddResourceEntryFromStream:=OK;
  433. end;
  434. function TResourceFile.DeleteResourceEntry(const ResName: string; ALangID: longint): boolean;
  435. var E: PResourceEntry;
  436. P: PResource;
  437. OK: boolean;
  438. begin
  439. P:=FindResource(ResName);
  440. OK:=P<>nil;
  441. if OK then E:=P^.Items^.SearchEntryForLang(ALangID);
  442. OK:=OK and (E<>nil);
  443. if OK then
  444. begin
  445. OK:=DeleteArea(E^.DataOfs,E^.DataLen,GetTotalSize(false));
  446. if OK then begin RemoveResEntryPtr(P,E); Dispose(E, Done); end;
  447. Modified:=true;
  448. end;
  449. DeleteResourceEntry:=OK;
  450. end;
  451. function TResourceFile.DeleteResource(const ResName: string): boolean;
  452. var P: PResource;
  453. E: PResourceEntry;
  454. OK: boolean;
  455. begin
  456. P:=FindResource(ResName);
  457. OK:=P<>nil;
  458. if P<>nil then
  459. begin
  460. while OK and (P^.Items^.Count>0) do
  461. begin
  462. E:=P^.Items^.At(P^.Items^.Count-1);
  463. OK:=OK and DeleteResourceEntry(ResName,E^.LangID);
  464. end;
  465. Modified:=true;
  466. end;
  467. if OK then Resources^.Free(P);
  468. DeleteResource:=OK;
  469. end;
  470. function TResourceFile.FindResource(const ResName: string): PResource;
  471. begin
  472. FindResource:=Resources^.SearchResourceByName(ResName);
  473. end;
  474. function TResourceFile.FindResourceEntry(const ResName: string; ALangID: longint): PResourceEntry;
  475. var P: PResource;
  476. E: PResourceEntry;
  477. begin
  478. E:=nil;
  479. P:=FindResource(ResName);
  480. if P<>nil then
  481. E:=P^.Items^.SearchEntryForLang(ALangID);
  482. FindResourceEntry:=E;
  483. end;
  484. procedure TResourceFile.Flush;
  485. begin
  486. if Modified=false then Exit;
  487. BuildFileHeader;
  488. S^.Seek(BaseOfs);
  489. WriteHeader;
  490. S^.Seek(BaseOfs+Header.TableOfs);
  491. WriteResourceTable;
  492. S^.Truncate;
  493. Modified:=false;
  494. end;
  495. procedure TResourceFile.BuildFileHeader;
  496. begin
  497. FillChar(Header,SizeOf(Header),0);
  498. with Header do
  499. begin
  500. Signature:=TPDataBlockSignature;
  501. InfoType:=ResourceBlockSignature;
  502. InfoSize:=GetTotalSize(true);
  503. TableOfs:=GetTotalSize(false);
  504. end;
  505. end;
  506. procedure TResourceFile.WriteHeader;
  507. begin
  508. S^.Write(Header,SizeOf(Header));
  509. end;
  510. procedure TResourceFile.WriteResourceTable;
  511. var RH: TResourceHeader;
  512. REH: TResourceEntryHeader;
  513. procedure WriteResource(P: PResource); {$ifndef FPC}far;{$endif}
  514. procedure WriteResourceEntry(P: PResourceEntry); {$ifndef FPC}far;{$endif}
  515. begin
  516. P^.BuildHeader(REH);
  517. S^.Write(REH,SizeOf(REH));
  518. end;
  519. var N: string;
  520. begin
  521. if P^.Items^.Count=0 then Exit; { do not store resources with no entries }
  522. P^.BuildHeader(RH);
  523. S^.Write(RH,SizeOf(RH));
  524. N:=P^.GetName;
  525. S^.Write(N[1],length(N));
  526. P^.ForEachEntry(@WriteResourceEntry);
  527. end;
  528. begin
  529. ForEachResource(@WriteResource);
  530. end;
  531. procedure TResourceFile.UpdateBlockDatas;
  532. begin
  533. CalcSizes(false,true);
  534. end;
  535. function TResourceFile.GetTotalSize(IncludeHeaders: boolean): longint;
  536. begin
  537. GetTotalSize:=CalcSizes(IncludeHeaders,false);
  538. end;
  539. function TResourceFile.CalcSizes(IncludeHeaders, UpdatePosData: boolean): longint;
  540. var RH : TResourceHeader;
  541. REH : TResourceEntryHeader;
  542. Size: longint;
  543. procedure AddResourceEntrySize(P: PResourceEntry); {$ifndef FPC}far;{$endif}
  544. begin
  545. if UpdatePosData then P^.DataOfs:=Size;
  546. P^.BuildHeader(REH);
  547. Inc(Size,REH.DataLen);
  548. end;
  549. begin
  550. Size:=0;
  551. Inc(Size,SizeOf(Header)); { this is on start so we always include it }
  552. ForEachResourceEntry(@AddResourceEntrySize);
  553. if IncludeHeaders then
  554. begin
  555. Inc(Size,SizeOf(RH)*Resources^.Count);
  556. Inc(Size,SizeOf(REH)*Entries^.Count);
  557. end;
  558. CalcSizes:=Size;
  559. end;
  560. function TResourceFile.DeleteArea(AreaStart, AreaSize, TotalSize: longint): boolean;
  561. const BufSize = 4096;
  562. var RemSize,FragSize,CurOfs: longint;
  563. Buf: pointer;
  564. OK: boolean;
  565. begin
  566. GetMem(Buf,BufSize);
  567. RemSize:=TotalSize-(AreaStart+AreaSize); CurOfs:=0;
  568. OK:=RemSize>=0;
  569. while (RemSize>0) do
  570. begin
  571. FragSize:=Min(RemSize,BufSize);
  572. S^.Seek(BaseOfs+AreaStart+AreaSize+CurOfs);
  573. S^.Read(Buf^,BufSize);
  574. OK:=OK and (S^.Status=stOK);
  575. if OK then
  576. begin
  577. S^.Seek(BaseOfs+AreaStart+CurOfs);
  578. S^.Write(Buf^,BufSize);
  579. OK:=OK and (S^.Status=stOK);
  580. end;
  581. Inc(CurOfs,FragSize); Dec(RemSize,FragSize);
  582. end;
  583. FreeMem(Buf,BufSize);
  584. DeleteArea:=OK;
  585. end;
  586. procedure TResourceFile.AddResEntryPtr(P: PResource; E: PResourceEntry);
  587. begin
  588. if (P=nil) or (E=nil) then Exit;
  589. P^.Items^.Insert(E);
  590. Entries^.Insert(E);
  591. end;
  592. procedure TResourceFile.RemoveResEntryPtr(P: PResource; E: PResourceEntry);
  593. begin
  594. if (P=nil) or (E=nil) then Exit;
  595. Entries^.Delete(E);
  596. P^.Items^.Delete(E);
  597. end;
  598. function TResourceFile.GetNextEntryID: longint;
  599. var ID: longint;
  600. begin
  601. if Entries^.Count=0 then ID:=1 else
  602. ID:=Entries^.At(Entries^.Count-1)^.ID+1;
  603. GetNextEntryID:=ID;
  604. end;
  605. destructor TResourceFile.Done;
  606. begin
  607. Flush;
  608. inherited Done;
  609. if Resources<>nil then Dispose(Resources, Done); Resources:=nil;
  610. if Entries<>nil then
  611. begin Entries^.DeleteAll; Dispose(Entries, Done); Entries:=nil; end;
  612. if MyStream and Assigned(S) then
  613. Dispose(S, Done);
  614. end;
  615. constructor TResourceFile.CreateFile(AFileName: string);
  616. var B: PBufStream;
  617. begin
  618. New(B, Init(AFileName, stCreate, 4096));
  619. if (B<>nil) and (B^.Status<>stOK) then
  620. begin Dispose(B, Done); B:=nil; end;
  621. if B=nil then Fail;
  622. if Create(B^)=false then
  623. Fail;
  624. MyStream:=true;
  625. end;
  626. constructor TResourceFile.LoadFile(AFileName: string);
  627. var B: PBufStream;
  628. begin
  629. New(B, Init(AFileName, stCreate, 4096));
  630. if (B<>nil) and (B^.Status<>stOK) then
  631. begin Dispose(B, Done); B:=nil; end;
  632. if B=nil then Fail;
  633. if Load(B^)=false then
  634. Fail;
  635. MyStream:=true;
  636. end;
  637. END.
  638. {
  639. $Log$
  640. Revision 1.4 1999-04-07 21:56:05 peter
  641. + object support for browser
  642. * html help fixes
  643. * more desktop saving things
  644. * NODEBUG directive to exclude debugger
  645. Revision 1.3 1999/03/23 16:16:43 peter
  646. * linux fixes
  647. Revision 1.2 1999/03/23 15:11:40 peter
  648. * desktop saving things
  649. * vesa mode
  650. * preferences dialog
  651. Revision 1.1 1999/03/16 12:38:18 peter
  652. * tools macro fixes
  653. + tph writer
  654. + first things for resource files
  655. }