123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389 |
- {
- This file is part of the Free Pascal run time library.
- Copyright (c) 2008 by Giulio Bernardi
- Resource support for non-PECOFF targets (ELF, Mach-O)
- 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.
- **********************************************************************}
- type
- PResInfoNode = ^TResInfoNode;
- TResInfoNode = packed record
- nameid : PChar; //name / integer ID / languageID
- ncounthandle : longword; //named sub-entries count / resource handle
- idcountsize : longword; //id sub-entries count / resource size
- subptr : PResInfoNode; //first sub-entry pointer
- end;
- TResHdr = packed record
- rootptr : PResInfoNode; //pointer to root node
- count : longword; //number of resources in the file
- usedhandles : longword; //last resource handle used
- handles : PPtrUint; //pointer to handles
- end;
- PResHdr = ^TResHdr;
- PPResHdr = ^PResHdr;
- TLibGetResHdr=function():PResHdr;
- var
- {$ifdef FPC_HAS_WINLIKERESOURCES}
- {$ifdef FPC_HAS_INDIRECT_ENTRY_INFORMATION}
- ResHeader : PPResHdr; external name '_FPC_ResLocation';
- {$else}
- ResHeaderVar: PResHdr; external name 'FPC_RESLOCATION';
- ResHeader : PPResHdr = @ResHeaderVar;
- {$endif}
- {$else}
- ResHeaderVar : PResHdr = nil;
- ResHeader : PPResHdr= @ResHeaderVar;
- {$endif}
- (*****************************************************************************
- Private Helper Functions
- *****************************************************************************)
- function ExtGetResHdr(ModuleHandle : TFPResourceHMODULE):PResHdr;
- var
- p:TLibGetResHdr;
- pp:pointer;
- begin
- ExtGetResHdr:=nil;
- if ModuleHandle=0 then
- ExtGetResHdr:=ResHeader^ // internal
- else
- begin
- // 1-st way to get resource location
- p:=TLibGetResHdr(GetProcAddress(ModuleHandle,'rsrc'));
- if p<>nil then // there is public
- ExtGetResHdr:=p();
- if ExtGetResHdr=nil then // try another way
- begin
- // 2-nd way to get resource location
- pp:=GetProcAddress(ModuleHandle,'FPC_RESLOCATION');
- if pp<>nil then
- ExtGetResHdr:=PResHDR(pp^);
- end;
- end;
- end;
- //resource functions are case insensitive... copied from genstr.inc
- function ResStrIComp(Str1, Str2 : PChar): SizeInt;
- var
- counter: SizeInt;
- c1, c2: char;
- begin
- counter := 0;
- c1 := upcase(str1[counter]);
- c2 := upcase(str2[counter]);
- while c1 = c2 do
- begin
- if (c1 = #0) or (c2 = #0) then break;
- inc(counter);
- c1 := upcase(str1[counter]);
- c2 := upcase(str2[counter]);
- end;
- ResStrIComp := ord(c1) - ord(c2);
- end;
- {!fixme!}
- //function InternalIsIntResource(aStr : pchar; out aInt : PtrUint) : boolean;
- function InternalIsIntResource(aStr : pchar; var aInt : PtrUint) : boolean;
- var i : integer;
- s : shortstring;
- code : word;
- begin
- InternalIsIntResource:=((PtrUInt(aStr) shr 16)=0);
- if InternalIsIntResource then aInt:=PtrUInt(aStr)
- else
- begin
- //a string like #number specifies an integer id
- if aStr[0]='#' then
- begin
- i:=1;
- while aStr[i]<>#0 do
- inc(i);
- if i>256 then i:=256;
- s[0]:=chr(i-1);
- Move(aStr[1],s[1],i-1);
- Val(s,aInt,code);
- InternalIsIntResource:=code=0;
- end;
- end;
- end;
- function BinSearchStr(arr : PResInfoNode; query : pchar; left, right : integer)
- : PResInfoNode;
- var pivot, res : integer;
- resstr : pchar;
- begin
- BinSearchStr:=nil;
- while left<=right do
- begin
- pivot:=(left+right) div 2;
- resstr:=arr[pivot].nameid;
- res:=ResStrIComp(resstr,query);
- if res<0 then left:=pivot+1
- else if res>0 then right:=pivot-1
- else
- begin
- BinSearchStr:=@arr[pivot];
- exit;
- end;
- end;
- end;
- function BinSearchInt(arr : PResInfoNode; query : pchar; left, right : integer)
- : PResInfoNode;
- var pivot : integer;
- begin
- BinSearchInt:=nil;
- while left<=right do
- begin
- pivot:=(left+right) div 2;
- if PtrUint(arr[pivot].nameid)<PtrUInt(query) then left:=pivot+1
- else if PtrUint(arr[pivot].nameid)>PtrUInt(query) then right:=pivot-1
- else
- begin
- BinSearchInt:=@arr[pivot];
- exit;
- end;
- end;
- end;
- function BinSearchRes(root : PResInfoNode; aDesc : PChar) : PResInfoNode;
- var aID : PtrUint;
- begin
- if InternalIsIntResource(aDesc,aID) then
- BinSearchRes:=BinSearchInt(root^.subptr,PChar(aID),root^.ncounthandle,
- root^.ncounthandle+root^.idcountsize-1)
- else
- BinSearchRes:=BinSearchStr(root^.subptr,aDesc,0,root^.ncounthandle-1);
- end;
- //Returns a pointer to a name node.
- function InternalFindResource(ResHdr:PResHdr;ResourceName, ResourceType: PChar):
- PResInfoNode;
- begin
- InternalFindResource:=nil;
- if ResHdr=nil then exit;
- InternalFindResource:=ResHdr^.rootptr;
- InternalFindResource:=BinSearchRes(InternalFindResource,ResourceType);
- if InternalFindResource<>nil then
- InternalFindResource:=BinSearchRes(InternalFindResource,ResourceName);
- end;
- function FindSubLanguage(aPtr : PResInfoNode; aLangID : word; aMask: word) : PResInfoNode;
- var arr : PResInfoNode;
- i : longword;
- begin
- FindSubLanguage:=nil;
- arr:=aPtr^.subptr;
- i:=0;
- while i<aPtr^.idcountsize do
- begin
- if (PtrUInt(arr[i].nameid) and aMask)=(aLangID and aMask) then
- begin
- FindSubLanguage:=@arr[i];
- exit;
- end;
- inc(i);
- end;
- end;
- (*****************************************************************************
- Public Resource Functions
- *****************************************************************************)
- Function IntHINSTANCE : TFPResourceHMODULE;
- begin
- IntHINSTANCE:=0;
- end;
- Function IntEnumResourceTypes(ModuleHandle : TFPResourceHMODULE; EnumFunc : EnumResTypeProc; lParam : PtrInt) : LongBool;
- var ptr : PResInfoNode;
- tot, i : integer;
- res_hdr:PResHdr;
- begin
- IntEnumResourceTypes:=False;
- res_hdr:=ExtGetResHdr(ModuleHandle);
- if res_hdr=nil then exit;
- tot:=res_hdr^.rootptr^.ncounthandle+res_hdr^.rootptr^.idcountsize;
- ptr:=res_hdr^.rootptr^.subptr;
- IntEnumResourceTypes:=true;
- i:=0;
- while i<tot do
- begin
- if not EnumFunc(ModuleHandle,ptr[i].nameid,lParam) then exit;
- inc(i);
- end;
- end;
- Function IntEnumResourceNames(ModuleHandle : TFPResourceHMODULE; ResourceType : PChar; EnumFunc : EnumResNameProc; lParam : PtrInt) : LongBool;
- var ptr : PResInfoNode;
- tot, i : integer;
- res_hdr:PResHdr;
- begin
- IntEnumResourceNames:=False;
- res_hdr:=ExtGetResHdr(ModuleHandle);
- if res_hdr=nil then exit;
- ptr:=res_hdr^.rootptr;
- ptr:=BinSearchRes(ptr,ResourceType);
- if ptr=nil then exit;
-
- tot:=ptr^.ncounthandle+ptr^.idcountsize;
- ptr:=ptr^.subptr;
- IntEnumResourceNames:=true;
- i:=0;
- while i<tot do
- begin
- if not EnumFunc(ModuleHandle,ResourceType,ptr[i].nameid,lParam) then exit;
- inc(i);
- end;
- end;
- Function IntEnumResourceLanguages(ModuleHandle : TFPResourceHMODULE; ResourceType, ResourceName : PChar; EnumFunc : EnumResLangProc; lParam : PtrInt) : LongBool;
- var ptr : PResInfoNode;
- tot, i : integer;
- res_hdr:PResHdr;
- begin
- IntEnumResourceLanguages:=False;
- res_hdr:=ExtGetResHdr(ModuleHandle);
- if res_hdr=nil then exit;
- ptr:=InternalFindResource(res_hdr,ResourceName,ResourceType);
- if ptr=nil then exit;
- tot:=ptr^.idcountsize;
- ptr:=ptr^.subptr;
- IntEnumResourceLanguages:=true;
- i:=0;
- while i<tot do
- begin
- if not EnumFunc(ModuleHandle,ResourceType,ResourceName,PtrUInt(ptr[i].nameid),lParam) then exit;
- inc(i);
- end;
- end;
- Function IntFindResource(ModuleHandle: TFPResourceHMODULE; ResourceName,
- ResourceType: PChar): TFPResourceHandle;
- var ptr : PResInfoNode;
- res_hdr: PresHdr;
- begin
- IntFindResource:=0;
- res_hdr:=ExtGetResHdr(ModuleHandle);
- if res_hdr=nil then exit;
- ptr:=InternalFindResource(res_hdr,ResourceName,ResourceType);
- if ptr=nil then exit;
- //first language id
- ptr:=ptr^.subptr;
- if ptr^.ncounthandle=0 then
- begin
- res_hdr^.handles[res_hdr^.usedhandles]:=PtrUint(ptr);
- inc(res_hdr^.usedhandles);
- ptr^.ncounthandle:=res_hdr^.usedhandles;
- end;
- IntFindResource:=ptr^.ncounthandle;
- end;
- Function IntFindResourceEx(ModuleHandle: TFPResourceHMODULE; ResourceType,
- ResourceName: PChar; Language : word): TFPResourceHandle;
- const LANG_NEUTRAL = 0;
- LANG_ENGLISH = 9;
- var nameptr,ptr : PResInfoNode;
- res_hdr: PResHdr;
- begin
- IntFindResourceEx:=0;
- res_hdr:=ExtGetResHdr(ModuleHandle);
- if res_hdr=nil then exit;
- nameptr:=InternalFindResource(res_hdr,ResourceName,ResourceType);
- if nameptr=nil then exit;
- //try exact match
- ptr:=FindSubLanguage(nameptr,Language,$FFFF);
- //try primary language
- if ptr=nil then
- ptr:=FindSubLanguage(nameptr,Language,$3FF);
- //try language neutral
- if ptr=nil then
- ptr:=FindSubLanguage(nameptr,LANG_NEUTRAL,$3FF);
- //try english
- if ptr=nil then
- ptr:=FindSubLanguage(nameptr,LANG_ENGLISH,$3FF);
- //nothing found, return the first one
- if ptr=nil then
- ptr:=nameptr^.subptr;
- if ptr^.ncounthandle=0 then
- begin
- res_hdr^.handles[res_hdr^.usedhandles]:=PtrUint(ptr);
- inc(res_hdr^.usedhandles);
- ptr^.ncounthandle:=res_hdr^.usedhandles;
- end;
- IntFindResourceEx:=ptr^.ncounthandle;
- end;
- Function IntLoadResource(ModuleHandle: TFPResourceHMODULE; ResHandle: TFPResourceHandle): TFPResourceHGLOBAL;
- var res_hdr: PResHdr;
- begin
- IntLoadResource:=0;
- res_hdr:=ExtGetResHdr(ModuleHandle);
- if res_hdr=nil then exit;
- if (ResHandle<=0) or (ResHandle>res_hdr^.usedhandles) then exit;
- IntLoadResource:=TFPResourceHGLOBAL(PResInfoNode(res_hdr^.handles[ResHandle-1])^.subptr);
- end;
- Function IntSizeofResource(ModuleHandle: TFPResourceHMODULE; ResHandle: TFPResourceHandle): LongWord;
- var res_hdr: PResHdr;
- begin
- IntSizeofResource:=0;
- res_hdr:=ExtGetResHdr(ModuleHandle);
- if res_hdr=nil then exit;
- if (ResHandle<=0) or (ResHandle>res_hdr^.usedhandles) then exit;
- IntSizeofResource:=PResInfoNode(res_hdr^.handles[ResHandle-1])^.idcountsize;
- end;
- Function IntLockResource(ResData: TFPResourceHGLOBAL): Pointer;
- begin
- IntLockResource:=Nil;
- if ResHeader^=nil then exit;
- IntLockResource:=Pointer(ResData);
- end;
- Function IntUnlockResource(ResData: TFPResourceHGLOBAL): LongBool;
- begin
- IntUnlockResource:=(ResHeader^<>nil);
- end;
- Function IntFreeResource(ResData: TFPResourceHGLOBAL): LongBool;
- begin
- IntFreeResource:=(ResHeader^<>nil);
- end;
- const
- InternalResourceManager : TResourceManager =
- (
- HINSTANCEFunc : @IntHINSTANCE;
- EnumResourceTypesFunc : @IntEnumResourceTypes;
- EnumResourceNamesFunc : @IntEnumResourceNames;
- EnumResourceLanguagesFunc : @IntEnumResourceLanguages;
- FindResourceFunc : @IntFindResource;
- FindResourceExFunc : @IntFindResourceEx;
- LoadResourceFunc : @IntLoadResource;
- SizeofResourceFunc : @IntSizeofResource;
- LockResourceFunc : @IntLockResource;
- UnlockResourceFunc : @IntUnlockResource;
- FreeResourceFunc : @IntFreeResource;
- );
|