123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797 |
- {
- This file is part of the Free Pascal Integrated Development Environment
- Copyright (c) 1998 by Berczi Gabor
- Resource File support objects and routines
- See the file COPYING.FPC, included in this distribution,
- for details about the copyright.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- **********************************************************************}
- unit WResourc;
- interface
- uses Objects;
- const
- TPDataBlockSignature = ord('F')+ord('B')*256;
- ResourceBlockSignature = ord('R')+ord('D')*256;
- langDefault = 0;
- rcBinary = 1;
- type
- TResourceEntryHeader = packed record
- ID : longint;
- LangID : longint;
- Flags : longint;
- DataOfs: longint;
- DataLen: sw_word;
- end;
- TResourceHeader = packed record
- _Class : longint;
- Flags : longint;
- NameLen : word;
- EntryCount : word;
- end;
- TResourceFileHeader = packed record
- Signature : word;
- InfoType : word;
- InfoSize : longint;
- { ---- }
- TableOfs : longint;
- end;
- PResourceEntry = ^TResourceEntry;
- TResourceEntry = object(TObject)
- constructor Init(AID, ALangID, AFlags, ADataLen: longint);
- private
- ID : longint;
- LangID : longint;
- Flags : longint;
- DataOfs : longint;
- DataLen : sw_word;
- procedure BuildHeader(var Header : TResourceEntryHeader);
- end;
- PResourceEntryCollection = ^TResourceEntryCollection;
- TResourceEntryCollection = object(TSortedCollection)
- function At(Index: Sw_Integer): PResourceEntry;
- function Compare(Key1, Key2: Pointer): Sw_Integer; virtual;
- function SearchEntryForLang(ALangID: longint): PResourceEntry;
- end;
- PGlobalResourceEntryCollection = ^TGlobalResourceEntryCollection;
- TGlobalResourceEntryCollection = object(TSortedCollection)
- function At(Index: Sw_Integer): PResourceEntry;
- function Compare(Key1, Key2: Pointer): Sw_Integer; virtual;
- end;
- PResource = ^TResource;
- TResource = object(TObject)
- constructor Init(const AName: string; AClass, AFlags: longint);
- function GetName: string; virtual;
- function FirstThatEntry(Func: pointer): PResourceEntry; virtual;
- procedure ForEachEntry(Func: pointer); virtual;
- destructor Done; virtual;
- private
- Name : PString;
- _Class : longint;
- Flags : longint;
- Items : PResourceEntryCollection;
- procedure BuildHeader(var Header : TResourceHeader);
- end;
- TResourceCollection = object(TSortedCollection)
- function At(Index: Sw_Integer): PResource;
- function Compare(Key1, Key2: Pointer): Sw_Integer; virtual;
- function SearchResourceByName(const AName: string): PResource;
- end;
- PResourceCollection = ^TResourceCollection;
- TResourceFile = object(TObject)
- constructor Init(var RS: TStream; ALoad: boolean);
- constructor Create(var RS: TStream);
- constructor Load(var RS: TStream);
- constructor CreateFile(AFileName: string);
- constructor LoadFile(AFileName: string);
- function FirstThatResource(Func: pointer): PResource; virtual;
- procedure ForEachResource(Func: pointer); virtual;
- procedure ForEachResourceEntry(Func: pointer); virtual;
- function CreateResource(const Name: string; AClass, AFlags: longint): boolean; virtual;
- function AddResourceEntry(const ResName: string; ALangID, AFlags: longint; var Data;
- ADataSize: sw_integer): boolean; virtual;
- function AddResourceEntryFromStream(const ResName: string; ALangID, AFlags: longint;
- var Source: TStream; ADataSize: longint): boolean; virtual;
- function DeleteResourceEntry(const ResName: string; ALangID: longint): boolean; virtual;
- function DeleteResource(const ResName: string): boolean; virtual;
- function ReadResourceEntry(const ResName: string; ALangID: longint; var Buf; BufSize: sw_word): boolean;
- function ReadResourceEntryToStream(const ResName: string; ALangID: longint; var DestS: TStream): boolean;
- procedure Flush; virtual;
- destructor Done; virtual;
- public
- BaseOfs: longint;
- function FindResource(const ResName: string): PResource;
- function FindResourceEntry(const ResName: string; ALangID: longint): PResourceEntry;
- private
- S : PStream;
- MyStream : boolean;
- Resources : PResourceCollection;
- Entries : PGlobalResourceEntryCollection;
- Header : TResourceFileHeader;
- Modified : boolean;
- procedure UpdateBlockDatas;
- function GetNextEntryID: longint;
- function GetTotalSize(IncludeHeaders: boolean): longint;
- function CalcSizes(IncludeHeaders, UpdatePosData: boolean): longint;
- procedure AddResEntryPtr(P: PResource; E: PResourceEntry);
- procedure RemoveResEntryPtr(P: PResource; E: PResourceEntry);
- function DeleteArea(AreaStart, AreaSize, TotalSize: longint): boolean;
- procedure BuildFileHeader;
- procedure WriteHeader;
- procedure WriteResourceTable;
- end;
- PResourceFile = ^TResourceFile;
- implementation
- uses
- WUtils;
- function TResourceEntryCollection.At(Index: Sw_Integer): PResourceEntry;
- begin
- At:=inherited At(Index);
- end;
- function TResourceEntryCollection.Compare(Key1, Key2: Pointer): Sw_Integer;
- var K1: PResourceEntry absolute Key1;
- K2: PResourceEntry absolute Key2;
- Re: Sw_integer;
- begin
- if K1^.LangID<K2^.LangID then Re:=-1 else
- if K1^.LangID>K2^.LangID then Re:= 1 else
- Re:=0;
- Compare:=Re;
- end;
- function TResourceEntryCollection.SearchEntryForLang(ALangID: longint): PResourceEntry;
- var P: PResourceEntry;
- E: TResourceEntry;
- Index: sw_integer;
- begin
- E.LangID:=ALangID;
- if Search(@E,Index)=false then P:=nil else
- P:=At(Index);
- SearchEntryForLang:=P;
- end;
- function TGlobalResourceEntryCollection.At(Index: Sw_Integer): PResourceEntry;
- begin
- At:=inherited At(Index);
- end;
- function TGlobalResourceEntryCollection.Compare(Key1, Key2: Pointer): Sw_Integer;
- var K1: PResourceEntry absolute Key1;
- K2: PResourceEntry absolute Key2;
- Re: Sw_integer;
- begin
- if K1^.ID<K2^.ID then Re:=-1 else
- if K1^.ID>K2^.ID then Re:= 1 else
- Re:=0;
- Compare:=Re;
- end;
- constructor TResourceEntry.Init(AID, ALangID, AFlags, ADataLen: longint);
- begin
- inherited Init;
- ID:=AID;
- LangID:=ALangID; Flags:=AFlags; DataLen:=ADataLen;
- end;
- procedure TResourceEntry.BuildHeader(var Header : TResourceEntryHeader);
- begin
- FillChar(Header,SizeOf(Header),0);
- Header.ID:=ID;
- Header.LangID:=LangID;
- Header.Flags:=Flags;
- Header.DataLen:=DataLen;
- Header.DataOfs:=DataOfs;
- end;
- constructor TResource.Init(const AName: string; AClass, AFlags: longint);
- begin
- inherited Init;
- Name:=NewStr(AName);
- _Class:=AClass;
- Flags:=AFlags;
- New(Items, Init(10,50));
- end;
- function TResource.GetName: string;
- begin
- GetName:=GetStr(Name);
- end;
- function TResource.FirstThatEntry(Func: pointer): PResourceEntry;
- var EP,P: PResourceEntry;
- I: sw_integer;
- begin
- P:=nil;
- for I:=0 to Items^.Count-1 do
- begin
- EP:=Items^.At(I);
- if Byte(Longint(CallPointerMethodLocal(Func,get_caller_frame(get_frame),@Self,EP)))<>0 then
- begin
- P := EP;
- Break;
- end;
- end;
- FirstThatEntry:=P;
- end;
- procedure TResource.ForEachEntry(Func: pointer);
- var RP: PResourceEntry;
- I: sw_integer;
- begin
- for I:=0 to Items^.Count-1 do
- begin
- RP:=Items^.At(I);
- CallPointerMethodLocal(Func,get_caller_frame(get_frame),@Self,RP);
- end;
- end;
- procedure TResource.BuildHeader(var Header : TResourceHeader);
- begin
- FillChar(Header,SizeOf(Header),0);
- Header._Class:=_Class;
- Header.Flags:=Flags;
- Header.NameLen:=length(GetName);
- Header.EntryCount:=Items^.Count;
- end;
- destructor TResource.Done;
- begin
- inherited Done;
- if Name<>nil then DisposeStr(Name); Name:=nil;
- if Items<>nil then Dispose(Items, Done); Items:=nil;
- end;
- function TResourceCollection.At(Index: Sw_Integer): PResource;
- begin
- At:=inherited At(Index);
- end;
- function TResourceCollection.Compare(Key1, Key2: Pointer): Sw_Integer;
- var K1: PResource absolute Key1;
- K2: PResource absolute Key2;
- N1,N2: string;
- Re: Sw_integer;
- begin
- N1:=UpcaseStr(K1^.GetName); N2:=UpcaseStr(K2^.GetName);
- if N1<N2 then Re:=-1 else
- if N1>N2 then Re:= 1 else
- Re:=0;
- Compare:=Re;
- end;
- function TResourceCollection.SearchResourceByName(const AName: string): PResource;
- var P,R: PResource;
- Index: sw_integer;
- begin
- New(R, Init(AName,0,0));
- if Search(R,Index)=false then P:=nil else
- P:=At(Index);
- Dispose(R, Done);
- SearchResourceByName:=P;
- end;
- constructor TResourceFile.Create(var RS: TStream);
- begin
- if Init(RS,false)=false then
- Fail;
- end;
- constructor TResourceFile.Load(var RS: TStream);
- begin
- if Init(RS,true)=false then
- Fail;
- end;
- constructor TResourceFile.Init(var RS: TStream; ALoad: boolean);
- var OK: boolean;
- RH: TResourceHeader;
- REH: TResourceEntryHeader;
- EndPos,I: longint;
- P: PResource;
- E: PResourceEntry;
- St: string;
- begin
- inherited Init;
- S:=@RS;
- New(Resources, Init(100, 1000));
- New(Entries, Init(500,2000));
- OK:=true;
- if ALoad=false then
- Modified:=true
- else
- begin
- S^.Reset;
- BaseOfs:=S^.GetPos;
- S^.Read(Header,SizeOf(Header));
- OK:=(S^.Status=stOK) and
- (Header.Signature=TPDataBlockSignature) and
- (Header.InfoType=ResourceBlockSignature);
- if OK then begin S^.Seek(BaseOfs+Header.TableOfs); OK:=S^.Status=stOK; end;
- EndPos:=BaseOfs+Header.InfoSize;
- if OK then
- while OK and (S^.GetPos<EndPos) do
- begin
- S^.Read(RH,SizeOf(RH)); OK:=(S^.Status=stOK);
- if OK then begin St[0]:=chr(RH.NameLen); S^.Read(St[1],RH.NameLen); OK:=(S^.Status=stOK); end;
- if OK then
- begin
- New(P, Init(St,RH._Class,RH.Flags));
- Resources^.Insert(P);
- end;
- I:=0;
- while OK and (I<RH.EntryCount) do
- begin
- S^.Read(REH,SizeOf(REH)); OK:=(S^.Status=stOK);
- if OK then
- begin
- New(E, Init(REH.ID,REH.LangID,REH.Flags,REH.DataLen));
- AddResEntryPtr(P,E);
- end;
- if OK then Inc(I);
- end;
- if OK then UpdateBlockDatas;
- end;
- end;
- if OK=false then
- begin
- Done;
- Fail;
- end;
- end;
- function TResourceFile.FirstThatResource(Func: pointer): PResource;
- var RP,P: PResource;
- I: sw_integer;
- begin
- P:=nil;
- for I:=0 to Resources^.Count-1 do
- begin
- RP:=Resources^.At(I);
- if Byte(Longint(CallPointerMethodLocal(Func,get_caller_frame(get_frame),@Self,RP)))<>0 then
- begin
- P := RP;
- Break;
- end;
- end;
- FirstThatResource:=P;
- end;
- procedure TResourceFile.ForEachResource(Func: pointer);
- var RP: PResource;
- I: sw_integer;
- begin
- for I:=0 to Resources^.Count-1 do
- begin
- RP:=Resources^.At(I);
- CallPointerMethodLocal(Func,get_caller_frame(get_frame),@Self,RP);
- end;
- end;
- procedure TResourceFile.ForEachResourceEntry(Func: pointer);
- var E: PResourceEntry;
- I: sw_integer;
- begin
- for I:=0 to Entries^.Count-1 do
- begin
- E:=Entries^.At(I);
- CallPointerMethodLocal(Func,get_caller_frame(get_frame),@Self,E);
- end;
- end;
- function TResourceFile.CreateResource(const Name: string; AClass, AFlags: longint): boolean;
- var OK: boolean;
- P: PResource;
- begin
- OK:=FindResource(Name)=nil;
- if OK then
- begin
- New(P, Init(Name,AClass,AFlags));
- Resources^.Insert(P);
- Modified:=true;
- end;
- CreateResource:=OK;
- end;
- function TResourceFile.AddResourceEntry(const ResName: string; ALangID, AFlags: longint; var Data;
- ADataSize: sw_integer): boolean;
- const BlockSize = 4096;
- var OK: boolean;
- P: PResource;
- E: PResourceEntry;
- RemSize,CurOfs,FragSize: longint;
- begin
- P:=FindResource(ResName);
- OK:=P<>nil;
- if OK then
- OK:=(P^.Items^.SearchEntryForLang(ALangID)=nil);
- if OK then
- begin
- New(E, Init(GetNextEntryID,ALangID, AFlags, ADataSize));
- AddResEntryPtr(P,E);
- UpdateBlockDatas;
- RemSize:=ADataSize; CurOfs:=0;
- S^.Reset;
- S^.Seek(BaseOfs+E^.DataOfs);
- while (RemSize>0) do
- begin
- FragSize:=Min(RemSize,BlockSize);
- S^.Write(PByteArray(@Data)^[CurOfs],FragSize);
- Dec(RemSize,FragSize); Inc(CurOfs,FragSize);
- end;
- Modified:=true;
- end;
- AddResourceEntry:=OK;
- end;
- function TResourceFile.AddResourceEntryFromStream(const ResName: string; ALangID, AFlags: longint;
- var Source: TStream; ADataSize: longint): boolean;
- const BufSize = 4096;
- var OK: boolean;
- P: PResource;
- E: PResourceEntry;
- RemSize,FragSize: longint;
- Buf: pointer;
- begin
- P:=FindResource(ResName);
- OK:=P<>nil;
- if OK then
- OK:=(P^.Items^.SearchEntryForLang(ALangID)=nil);
- if OK then
- begin
- New(E, Init(GetNextEntryID, ALangID, AFlags, ADataSize));
- AddResEntryPtr(P,E);
- UpdateBlockDatas;
- GetMem(Buf,BufSize);
- RemSize:=ADataSize;
- S^.Reset;
- S^.Seek(BaseOfs+E^.DataOfs);
- while (RemSize>0) do
- begin
- FragSize:=Min(RemSize,BufSize);
- Source.Read(Buf^,FragSize);
- S^.Write(Buf^,FragSize);
- Dec(RemSize,FragSize);
- end;
- FreeMem(Buf,BufSize);
- Modified:=true;
- end;
- AddResourceEntryFromStream:=OK;
- end;
- function TResourceFile.DeleteResourceEntry(const ResName: string; ALangID: longint): boolean;
- var E: PResourceEntry;
- P: PResource;
- OK: boolean;
- begin
- P:=FindResource(ResName);
- OK:=P<>nil;
- if OK then E:=P^.Items^.SearchEntryForLang(ALangID);
- OK:=OK and (E<>nil);
- if OK then
- begin
- OK:=DeleteArea(E^.DataOfs,E^.DataLen,GetTotalSize(false));
- if OK then begin RemoveResEntryPtr(P,E); Dispose(E, Done); end;
- Modified:=true;
- end;
- DeleteResourceEntry:=OK;
- end;
- function TResourceFile.DeleteResource(const ResName: string): boolean;
- var P: PResource;
- E: PResourceEntry;
- OK: boolean;
- begin
- P:=FindResource(ResName);
- OK:=P<>nil;
- if P<>nil then
- begin
- while OK and (P^.Items^.Count>0) do
- begin
- E:=P^.Items^.At(P^.Items^.Count-1);
- OK:=OK and DeleteResourceEntry(ResName,E^.LangID);
- end;
- Modified:=true;
- end;
- if OK then Resources^.Free(P);
- DeleteResource:=OK;
- end;
- function TResourceFile.ReadResourceEntry(const ResName: string; ALangID: longint; var Buf; BufSize: sw_word): boolean;
- var E: PResourceEntry;
- P: PResource;
- OK: boolean;
- CurOfs,CurFrag: sw_word;
- TempBuf: pointer;
- const TempBufSize = 4096;
- begin
- E:=nil;
- P:=FindResource(ResName);
- OK:=P<>nil;
- if OK then E:=P^.Items^.SearchEntryForLang(ALangID);
- OK:=OK and (E<>nil);
- OK:=OK and (E^.DataLen<=BufSize);
- if OK then
- begin
- GetMem(TempBuf,TempBufSize);
- S^.Reset;
- S^.Seek(BaseOfs+E^.DataOfs);
- OK:=(S^.Status=stOK);
- CurOfs:=0;
- while OK and (CurOfs<E^.DataLen) do
- begin
- CurFrag:=Min(E^.DataLen-CurOfs,TempBufSize);
- S^.Read(TempBuf^,CurFrag);
- OK:=OK and (S^.Status=stOK);
- if OK then
- Move(TempBuf^,PByteArray(@Buf)^[CurOfs],CurFrag);
- Inc(CurOfs,CurFrag);
- end;
- FreeMem(TempBuf,TempBufSize);
- end;
- ReadResourceEntry:=OK;
- end;
- function TResourceFile.ReadResourceEntryToStream(const ResName: string; ALangID: longint; var DestS: TStream): boolean;
- var E: PResourceEntry;
- P: PResource;
- OK: boolean;
- CurOfs,CurFrag: sw_word;
- TempBuf: pointer;
- const TempBufSize = 4096;
- begin
- P:=FindResource(ResName);
- OK:=P<>nil;
- if OK then E:=P^.Items^.SearchEntryForLang(ALangID);
- OK:=OK and (E<>nil);
- if OK then
- begin
- GetMem(TempBuf,TempBufSize);
- S^.Reset;
- S^.Seek(BaseOfs+E^.DataOfs);
- OK:=(S^.Status=stOK);
- CurOfs:=0;
- { this results sometimes in endless loops
- when the resource are changed PM }
- if E^.DataLen<0 then
- OK:=false;
- while OK and (CurOfs<E^.DataLen) do
- begin
- CurFrag:=Min(E^.DataLen-CurOfs,TempBufSize);
- S^.Read(TempBuf^,CurFrag);
- OK:=OK and (S^.Status=stOK);
- if OK then
- DestS.Write(TempBuf^,CurFrag);
- OK:=OK and (DestS.Status=stOK);
- Inc(CurOfs,CurFrag);
- end;
- FreeMem(TempBuf,TempBufSize);
- end;
- ReadResourceEntryToStream:=OK;
- end;
- function TResourceFile.FindResource(const ResName: string): PResource;
- begin
- FindResource:=Resources^.SearchResourceByName(ResName);
- end;
- function TResourceFile.FindResourceEntry(const ResName: string; ALangID: longint): PResourceEntry;
- var P: PResource;
- E: PResourceEntry;
- begin
- E:=nil;
- P:=FindResource(ResName);
- if P<>nil then
- E:=P^.Items^.SearchEntryForLang(ALangID);
- FindResourceEntry:=E;
- end;
- procedure TResourceFile.Flush;
- begin
- if Modified=false then Exit;
- BuildFileHeader;
- S^.Seek(BaseOfs);
- WriteHeader;
- S^.Seek(BaseOfs+Header.TableOfs);
- WriteResourceTable;
- S^.Truncate;
- Modified:=false;
- end;
- procedure TResourceFile.BuildFileHeader;
- begin
- FillChar(Header,SizeOf(Header),0);
- with Header do
- begin
- Signature:=TPDataBlockSignature;
- InfoType:=ResourceBlockSignature;
- InfoSize:=GetTotalSize(true);
- TableOfs:=GetTotalSize(false);
- end;
- end;
- procedure TResourceFile.WriteHeader;
- begin
- S^.Write(Header,SizeOf(Header));
- end;
- procedure TResourceFile.WriteResourceTable;
- var RH: TResourceHeader;
- REH: TResourceEntryHeader;
- procedure WriteResource(P: PResource);
- procedure WriteResourceEntry(P: PResourceEntry);
- begin
- P^.BuildHeader(REH);
- S^.Write(REH,SizeOf(REH));
- end;
- var N: string;
- begin
- if P^.Items^.Count=0 then Exit; { do not store resources with no entries }
- P^.BuildHeader(RH);
- S^.Write(RH,SizeOf(RH));
- N:=P^.GetName;
- S^.Write(N[1],length(N));
- P^.ForEachEntry(@WriteResourceEntry);
- end;
- begin
- ForEachResource(@WriteResource);
- end;
- procedure TResourceFile.UpdateBlockDatas;
- begin
- CalcSizes(false,true);
- end;
- function TResourceFile.GetTotalSize(IncludeHeaders: boolean): longint;
- begin
- GetTotalSize:=CalcSizes(IncludeHeaders,false);
- end;
- function TResourceFile.CalcSizes(IncludeHeaders, UpdatePosData: boolean): longint;
- var RH : TResourceHeader;
- REH : TResourceEntryHeader;
- Size: longint;
- NamesSize: longint;
- procedure AddResourceEntrySize(P: PResourceEntry);
- begin
- if UpdatePosData then P^.DataOfs:=Size;
- P^.BuildHeader(REH);
- Inc(Size,REH.DataLen);
- end;
- procedure AddResourceSize(P: PResource);
- var RH: TResourceHeader;
- begin
- P^.BuildHeader(RH);
- Inc(NamesSize,RH.NameLen);
- end;
- begin
- Size:=0; NamesSize:=0;
- Inc(Size,SizeOf(Header)); { this is on start so we always include it }
- ForEachResourceEntry(@AddResourceEntrySize);
- if IncludeHeaders then
- begin
- ForEachResource(@AddResourceSize);
- Inc(Size,SizeOf(RH)*Resources^.Count);
- Inc(Size,SizeOf(REH)*Entries^.Count);
- Inc(Size,NamesSize);
- end;
- CalcSizes:=Size;
- end;
- function TResourceFile.DeleteArea(AreaStart, AreaSize, TotalSize: longint): boolean;
- const BufSize = 4096;
- var RemSize,FragSize,CurOfs: longint;
- Buf: pointer;
- OK: boolean;
- begin
- GetMem(Buf,BufSize);
- RemSize:=TotalSize-(AreaStart+AreaSize); CurOfs:=0;
- OK:=RemSize>=0;
- while (RemSize>0) do
- begin
- FragSize:=Min(RemSize,BufSize);
- S^.Seek(BaseOfs+AreaStart+AreaSize+CurOfs);
- S^.Read(Buf^,BufSize);
- OK:=OK and (S^.Status=stOK);
- if OK then
- begin
- S^.Seek(BaseOfs+AreaStart+CurOfs);
- S^.Write(Buf^,BufSize);
- OK:=OK and (S^.Status=stOK);
- end;
- Inc(CurOfs,FragSize); Dec(RemSize,FragSize);
- end;
- FreeMem(Buf,BufSize);
- DeleteArea:=OK;
- end;
- procedure TResourceFile.AddResEntryPtr(P: PResource; E: PResourceEntry);
- begin
- if (P=nil) or (E=nil) then Exit;
- P^.Items^.Insert(E);
- Entries^.Insert(E);
- end;
- procedure TResourceFile.RemoveResEntryPtr(P: PResource; E: PResourceEntry);
- begin
- if (P=nil) or (E=nil) then Exit;
- Entries^.Delete(E);
- P^.Items^.Delete(E);
- end;
- function TResourceFile.GetNextEntryID: longint;
- var ID: longint;
- begin
- if Entries^.Count=0 then ID:=1 else
- ID:=Entries^.At(Entries^.Count-1)^.ID+1;
- GetNextEntryID:=ID;
- end;
- destructor TResourceFile.Done;
- begin
- Flush;
- inherited Done;
- { if assigned(S) then dispose(S,Done); S:=nil;}
- if Resources<>nil then Dispose(Resources, Done); Resources:=nil;
- if Entries<>nil then
- begin Entries^.DeleteAll; Dispose(Entries, Done); Entries:=nil; end;
- if MyStream and Assigned(S) then
- Dispose(S, Done);
- end;
- constructor TResourceFile.CreateFile(AFileName: string);
- var B: PFastBufStream;
- begin
- New(B, Init(AFileName, stCreate, 4096));
- if (B<>nil) and (B^.Status<>stOK) then
- begin Dispose(B, Done); B:=nil; end;
- if B=nil then Fail;
- if Create(B^)=false then
- Begin
- Dispose(B,Done);
- Fail;
- End;
- MyStream:=true;
- end;
- constructor TResourceFile.LoadFile(AFileName: string);
- var B: PFastBufStream;
- begin
- New(B, Init(AFileName, stOpen, 4096));
- if (B<>nil) and (B^.Status<>stOK) then
- begin Dispose(B, Done); B:=nil; end;
- if B=nil then Fail;
- if Load(B^)=false then
- Begin
- Dispose(B,Done);
- Fail;
- End;
- MyStream:=true;
- end;
- END.
|