fpc/rtl/darwin/extres_multiarch.inc
michael 174de3eab1 Merged revisions 9693-10480 via svnmerge from
svn+ssh://svn.freepascal.org/FPC/svn/fpc/branches/resources

........
  r9694 | michael | 2008-01-09 21:31:18 +0100 (Wed, 09 Jan 2008) | 1 line
  
  * Initial check-in
........
  r9695 | michael | 2008-01-09 21:35:58 +0100 (Wed, 09 Jan 2008) | 1 line
  
  * New version from Giulio Bernardi
........
  r9697 | michael | 2008-01-09 21:41:54 +0100 (Wed, 09 Jan 2008) | 1 line
  
  * Patch from Giulio Bernardi with resource support
........
  r9698 | michael | 2008-01-09 21:46:33 +0100 (Wed, 09 Jan 2008) | 1 line
  
  * Patch from Giulio Bernardi to add more resource testing
........
  r9699 | michael | 2008-01-09 21:57:26 +0100 (Wed, 09 Jan 2008) | 1 line
  
  * New tool from Giulio Bernardi
........
  r9700 | michael | 2008-01-09 21:58:23 +0100 (Wed, 09 Jan 2008) | 1 line
  
  * New tool from Giulio Bernardi
........
  r9701 | michael | 2008-01-09 22:01:54 +0100 (Wed, 09 Jan 2008) | 1 line
  
  * Added fcl-res
........
  r9702 | michael | 2008-01-09 22:01:58 +0100 (Wed, 09 Jan 2008) | 1 line
  
  * Added fcl-res
........
  r9703 | michael | 2008-01-10 08:54:26 +0100 (Thu, 10 Jan 2008) | 1 line
  
  * Fixed double code
........
  r9704 | jonas | 2008-01-10 10:59:20 +0100 (Thu, 10 Jan 2008) | 2 lines
  
    - removed duplicate code
........
  r9705 | jonas | 2008-01-10 11:25:21 +0100 (Thu, 10 Jan 2008) | 2 lines
  
    + added missing fcl-res dependencies
........
  r9706 | jonas | 2008-01-10 11:58:30 +0100 (Thu, 10 Jan 2008) | 2 lines
  
    + dependencies for fpintres and fpextres
........
  r9707 | yury | 2008-01-10 12:47:51 +0100 (Thu, 10 Jan 2008) | 3 lines
  
  * Fixed compilation of resource, which is included in a unit located in different folder than main source.
  * .res files must be copied to units output folder, otherwise .res files will not be found when only compiled units path is available and compiler does not know anything about sources folder.
  * Improved resource related error messages.
........
  r9708 | michael | 2008-01-10 12:52:13 +0100 (Thu, 10 Jan 2008) | 1 line
  
  * Removed double source after end.
........
  r9709 | michael | 2008-01-10 12:52:48 +0100 (Thu, 10 Jan 2008) | 1 line
  
  * No longer needed
........
  r9710 | tom_at_work | 2008-01-10 22:09:08 +0100 (Thu, 10 Jan 2008) | 1 line
  
  * properly align FPC_RESLOCATION so that linking does not fail on some architectures (e.g. ppc64)
........
  r9711 | tom_at_work | 2008-01-10 23:53:12 +0100 (Thu, 10 Jan 2008) | 1 line
  
  * fix splitting of 64 bit load/stores from/to unaligned memory locations into multiple load/stores, which in some cases generated wrong code
........
  r9712 | michael | 2008-01-11 11:00:08 +0100 (Fri, 11 Jan 2008) | 1 line
  
  * Fixed bug in BSS section on 64-bit platforms
........
  r9720 | giulio | 2008-01-12 10:02:04 +0100 (Sat, 12 Jan 2008) | 1 line
  
  Updated fcl-res documentation: occurrences of reslib changed to fcl-res.
........
  r9740 | giulio | 2008-01-13 19:36:44 +0100 (Sun, 13 Jan 2008) | 3 lines
  
   - Don't try to compile resources on systems with a non windows-like resource support.
   - Don't add the .or file to the list of object files if resource compiling failed.
........
  r10201 | giulio | 2008-02-04 11:35:44 +0100 (Mon, 04 Feb 2008) | 5 lines
  
  * resource compiling supported on OS/2 via wrc
  * CompileResourceFiles and CollectResourceFiles don't do target-specific checks anymore
  * refactored a bit
........
  r10389 | giulio | 2008-02-25 21:32:52 +0100 (Mon, 25 Feb 2008) | 2 lines
  
  Deleted test file which was committed by mistake
........
  r10472 | giulio | 2008-03-10 12:22:18 +0100 (Mon, 10 Mar 2008) | 2 lines
  
  changed define FPC_HAS_RESOURCES to FPC_HAS_WINLIKERESOURCES
........

git-svn-id: trunk@10481 -
2008-03-12 21:33:48 +00:00

691 lines
21 KiB
PHP

{
This file is part of the Free Pascal run time library.
Copyright (c) 2008 by Giulio Bernardi
Resource support as external files, for Mac OS X
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.
**********************************************************************}
{
This file is similar to extres.inc when EXTRES_MMAP is defined.
However, two files are searched (an architecture-dependent one and a shared
one). They are searched first in Contents/Resources directory of the program
application bundle and then in the same directory of the program.
}
const
FPCRES_MAGIC = 'FPCRES';
FPCRES_VERSION = 1;
{$IFDEF ENDIAN_BIG}
FPCRES_ENDIAN = 1;
{$ENDIF}
{$IFDEF ENDIAN_LITTLE}
FPCRES_ENDIAN = 2;
{$ENDIF}
FPCRES_EXT = '.fpcres';
FPCRES_ARCH =
{$IFDEF CPUI386}
'.i386';
{$ELSE}
{$IFDEF CPUX86_64}
'.x86_64';
{$ELSE}
{$IFDEF CPUPOWERPC32}
'.powerpc';
{$ELSE}
{$IFDEF CPUPOWERPC64}
'.powerpc64';
{$ELSE}
'';
{$ENDIF}
{$ENDIF}
{$ENDIF}
{$ENDIF}
type
TExtHeader = packed record
magic : array[0..5] of char;//'FPCRES'
version : byte; //EXT_CURRENT_VERSION
endianess : byte; //EXT_ENDIAN_BIG or EXT_ENDIAN_LITTLE
count : longword; //resource count
nodesize : longword; //size of header (up to string table, excluded)
hdrsize : longword; //size of header (up to string table, included)
reserved1 : longword;
reserved2 : longword;
reserved3 : longword;
end;
PExtHeader = ^TExtHeader;
TResInfoNode = packed record
nameid : longword; //name offset / integer ID / languageID
ncounthandle : longword; //named sub-entries count/resource handle
idcountsize : longword; //id sub-entries count / resource size
subptr : longword; //first sub-entry offset
end;
PResInfoNode = ^TResInfoNode;
TResFileInfo = record
ResHeader : PExtHeader;
fd : integer;
size : longword;
end;
var
ResFileInfo : TResFileInfo = (ResHeader : nil; fd : 0; size : 0);
ResFileInfoArch : TResFileInfo = (ResHeader : nil; fd : 0; size : 0);
reshandles : PPointer = nil;
usedhandles : longword = 0;
rescount : longword = 0;
(*****************************************************************************
Private Helper Functions
*****************************************************************************)
//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 GetResInfoPtr(base : PExtHeader; const offset : longword) : PResInfoNode; inline;
begin
GetResInfoPtr:=PResInfoNode(PtrUInt(base)+offset);
end;
function GetPchar(base : PExtHeader; const offset : longword) : Pchar; inline;
begin
GetPchar:=Pchar(PtrUInt(base)+offset);
end;
function GetPtr(base : PExtHeader; const offset : longword) : Pointer; inline;
begin
GetPtr:=Pointer(PtrUInt(base)+offset);
end;
procedure FixResEndian(ResHeader : PExtHeader);
var ptr : plongword;
blockend : plongword;
begin
//all info nodes reside in a contiguos block of memory.
//they are all 16 bytes long and made by longwords
//so, simply swap each longword in the block
ptr:=GetPtr(ResHeader,sizeof(TExtHeader));
blockend:=GetPtr(ResHeader,ResHeader^.nodesize);
while ptr<blockend do
begin
ptr^:=SwapEndian(ptr^);
inc(ptr);
end;
end;
function GetExtResBasePath : shortstring;
var exename : shortstring;
len, i, extpos, namepos: integer;
begin
GetExtResBasePath:=paramstr(0);
len:=byte(GetExtResBasePath[0]);
i:=len;
// writeln('exe name is ',GetExtResBasePath);
//find position of extension
while (i>0) and (not (GetExtResBasePath[i] in ['.',DirectorySeparator])) do
dec(i);
//find position of last directory separator
if (i>0) and (GetExtResBasePath[i]='.') then extpos:=i-1
else extpos:=len;
while (i>0) and (GetExtResBasePath[i] <> DirectorySeparator) do
dec(i);
namepos:=i;
exename:=copy(GetExtResBasePath,i+1,extpos-i);
dec(i);
//is executable in 'MacOS' directory? find previous dir separator...
while (i>0) and (GetExtResBasePath[i] <> DirectorySeparator) do
dec(i);
if i<0 then i:=0;
//yes, search file in <bundle>/Contents/Resources directory
if (namepos>i) and (copy(GetExtResBasePath,i+1,namepos-i-1)='MacOS') then
begin
GetExtResBasePath[0]:=Chr(i);
GetExtResBasePath:=GetExtResBasePath+'Resources'+DirectorySeparator+exename;
end
else //no, search file in exe directory
GetExtResBasePath[0]:=Chr(extpos);
// writeln('base path is ',GetExtResBasePath);
end;
function GetExtResPathArch(const base : shortstring) : pchar;
var len : integer;
begin
len:=byte(base[0]);
GetExtResPathArch:=GetMem(len+length(FPCRES_ARCH)+length(FPCRES_EXT)+1);
Move(base[1],GetExtResPathArch[0],len);
Move(FPCRES_ARCH[1],GetExtResPathArch[len],length(FPCRES_ARCH));
inc(len,length(FPCRES_ARCH));
Move(FPCRES_EXT[1],GetExtResPathArch[len],length(FPCRES_EXT));
inc(len,length(FPCRES_EXT));
GetExtResPathArch[len]:=#0;
// writeln('Arch-dependent resource file is ',GetExtResPathArch);
end;
function GetExtResPath(const base : shortstring) : pchar;
var len : integer;
begin
len:=byte(base[0]);
GetExtResPath:=GetMem(len+length(FPCRES_EXT)+1);
Move(base[1],GetExtResPath[0],len);
Move(FPCRES_EXT[1],GetExtResPath[len],length(FPCRES_EXT));
inc(len,length(FPCRES_EXT));
GetExtResPath[len]:=#0;
// writeln('Shared resource file is ',GetExtResPath);
end;
procedure MapResFile(var aInfo : TResFileInfo; aName : pchar);
const
PROT_READ = 1;
PROT_WRITE = 2;
var fdstat : stat;
begin
aInfo.fd:=FpOpen(aName,O_RDONLY,0);
FreeMem(aName);
// writeln('fpopen returned ',aInfo.fd);
if (aInfo.fd=-1) then exit;
if FpFStat(aInfo.fd,fdstat)<>0 then
begin
// writeln('fpfstat failed');
FpClose(aInfo.fd);
exit;
end;
// writeln('fpfstat suceeded');
aInfo.size:=fdstat.st_size;
aInfo.ResHeader:=PExtHeader(Fpmmap(nil,aInfo.size,PROT_READ or PROT_WRITE,
MAP_PRIVATE,aInfo.fd,0));
// writeln('fpmmap returned ',PtrInt(aInfo.ResHeader));
if PtrInt(aInfo.ResHeader)=-1 then
begin
FpClose(aInfo.fd);
exit;
end;
if (aInfo.ResHeader^.magic<>FPCRES_MAGIC) or
(aInfo.ResHeader^.version<>FPCRES_VERSION) then
begin
FpClose(aInfo.fd);
exit;
end;
// writeln('magic ok');
if aInfo.ResHeader^.endianess<>FPCRES_ENDIAN then
begin
aInfo.ResHeader^.count:=SwapEndian(aInfo.ResHeader^.count);
aInfo.ResHeader^.nodesize:=SwapEndian(aInfo.ResHeader^.nodesize);
aInfo.ResHeader^.hdrsize:=SwapEndian(aInfo.ResHeader^.hdrsize);
FixResEndian(aInfo.ResHeader);
end;
inc(rescount,aInfo.ResHeader^.count);
end;
procedure InitResources;
var respathArch : pchar;
respath : pchar;
basepath : shortstring;
begin
basepath:=GetExtResBasePath;
respathArch:=GetExtResPathArch(basepath);
respath:=GetExtResPath(basepath);
MapResFile(ResFileInfoArch,respathArch);
MapResFile(ResFileInfo,respath);
if rescount=0 then exit;
reshandles:=GetMem(sizeof(Pointer)*rescount);
FillByte(reshandles^,sizeof(Pointer)*rescount,0);
end;
procedure FinalizeResources;
begin
if (ResFileInfoArch.Resheader=nil) and (ResFileInfo.Resheader=nil) then exit;
FreeMem(reshandles);
if ResFileInfoArch.Resheader<>nil then
begin
Fpmunmap(ResFileInfoArch.ResHeader,ResFileInfoArch.size);
FpClose(ResFileInfoArch.fd);
end;
if ResFileInfo.Resheader<>nil then
begin
Fpmunmap(ResFileInfo.ResHeader,ResFileInfo.size);
FpClose(ResFileInfo.fd);
end;
end;
function BinSearchStr(base : PExtHeader; 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:=GetPchar(base,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 arr[pivot].nameid<PtrUInt(query) then left:=pivot+1
else if arr[pivot].nameid>PtrUInt(query) then right:=pivot-1
else
begin
BinSearchInt:=@arr[pivot];
exit;
end;
end;
end;
function BinSearchRes(base : PExtHeader; root : PResInfoNode; aDesc : PChar)
: PResInfoNode;
var aID : PtrUint;
begin
if InternalIsIntResource(aDesc,aID) then
BinSearchRes:=BinSearchInt(GetResInfoPtr(base,root^.subptr),PChar(aID),
root^.ncounthandle,root^.ncounthandle+root^.idcountsize-1)
else
BinSearchRes:=BinSearchStr(base,GetResInfoPtr(base,root^.subptr),aDesc,0,
root^.ncounthandle-1);
end;
function FindSubLanguage(base : PExtHeader; aPtr : PResInfoNode; aLangID : word;
aMask: word) : PResInfoNode;
var arr : PResInfoNode;
i : longword;
begin
FindSubLanguage:=nil;
arr:=GetResInfoPtr(base,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;
//Returns a pointer to a name node.
function InternalFindResource(base : PExtHeader; ResourceName, ResourceType: PChar):
PResInfoNode;
begin
InternalFindResource:=nil;
if base=nil then exit;
InternalFindResource:=GetResInfoPtr(base,sizeof(TExtHeader));
InternalFindResource:=BinSearchRes(base,InternalFindResource,ResourceType);
if InternalFindResource<>nil then
InternalFindResource:=BinSearchRes(base,InternalFindResource,ResourceName);
end;
function FindResourceSingleFile(ResHeader : PExtHeader; ResourceName,
ResourceType: PChar) : TFPResourceHandle;
var ptr : PResInfoNode;
begin
FindResourceSingleFile:=0;
ptr:=InternalFindResource(ResHeader,ResourceName,ResourceType);
if ptr=nil then exit;
//first language id
ptr:=GetResInfoPtr(ResHeader,ptr^.subptr);
if ptr^.ncounthandle=0 then
begin
reshandles[usedhandles]:=ptr;
inc(usedhandles);
ptr^.ncounthandle:=usedhandles;
end;
FindResourceSingleFile:=ptr^.ncounthandle;
end;
{!fixme!}
//function FindResourceExSingleFile(ResHeader : PExtHeader; ResourceType,
// ResourceName: PChar; Language : word; out precision : integer): TFPResourceHandle;
function FindResourceExSingleFile(ResHeader : PExtHeader; ResourceType,
ResourceName: PChar; Language : word; var precision : integer): TFPResourceHandle;
const LANG_NEUTRAL = 0;
LANG_ENGLISH = 9;
var nameptr,ptr : PResInfoNode;
begin
FindResourceExSingleFile:=0;
precision:=-1;
nameptr:=InternalFindResource(ResHeader,ResourceName,ResourceType);
if nameptr=nil then exit;
precision:=4;
//try exact match
ptr:=FindSubLanguage(ResHeader,nameptr,Language,$FFFF);
//try primary language
if ptr=nil then
begin
dec(precision);
ptr:=FindSubLanguage(ResHeader,nameptr,Language,$3FF);
end;
//try language neutral
if ptr=nil then
begin
dec(precision);
ptr:=FindSubLanguage(ResHeader,nameptr,LANG_NEUTRAL,$3FF);
end;
//try english
if ptr=nil then
begin
dec(precision);
ptr:=FindSubLanguage(ResHeader,nameptr,LANG_ENGLISH,$3FF);
end;
//nothing found, return the first one
if ptr=nil then
begin
dec(precision);
ptr:=GetResInfoPtr(ResHeader,nameptr^.subptr);
end;
if ptr^.ncounthandle=0 then
begin
reshandles[usedhandles]:=ptr;
inc(usedhandles);
ptr^.ncounthandle:=usedhandles;
end;
FindResourceExSingleFile:=ptr^.ncounthandle;
end;
function EnumResourceTypesSingleFile(ResHeader,Other : PExtHeader; ModuleHandle
: TFPResourceHMODULE; EnumFunc : EnumResTypeProc; lParam : PtrInt) : LongBool;
var ptr,otarr : PResInfoNode;
totn, totid, ottotn, ottotid, i : longword;
pc : pchar;
begin
EnumResourceTypesSingleFile:=false;
if ResHeader=nil then exit;
ptr:=GetResInfoPtr(Resheader,sizeof(TExtHeader));
totn:=ptr^.ncounthandle;
totid:=totn+ptr^.idcountsize;
ptr:=GetResInfoPtr(Resheader,ptr^.subptr);
if Other<>nil then
begin
otarr:=GetResInfoPtr(Other,sizeof(TExtHeader));
ottotn:=otarr^.ncounthandle;
ottotid:=ottotn+otarr^.idcountsize-1;
otarr:=GetResInfoPtr(Other,otarr^.subptr)
end;
EnumResourceTypesSingleFile:=true;
i:=0;
while i<totn do //named entries
begin
pc:=GetPChar(Resheader,ptr[i].nameid);
if (Other=nil) or (BinSearchStr(Other,otarr,pc,0,ottotn-1)=nil) then
if not EnumFunc(ModuleHandle,pc,lParam) then exit;
inc(i);
end;
while i<totid do
begin
if (Other=nil) or (BinSearchInt(otarr,PChar(ptr[i].nameid),ottotn,ottotid)=nil) then
if not EnumFunc(ModuleHandle,PChar(ptr[i].nameid),lParam) then exit;
inc(i);
end;
end;
function EnumResourceNamesSingleFile(ResHeader,Other : PExtHeader;
ModuleHandle : TFPResourceHMODULE; ResourceType : PChar;
EnumFunc : EnumResNameProc; lParam : PtrInt) : LongBool;
var ptr,otarr : PResInfoNode;
totn, totid, ottotn, ottotid, i : longword;
pc : pchar;
begin
EnumResourceNamesSingleFile:=False;
if ResHeader=nil then exit;
ptr:=GetResInfoPtr(ResHeader,sizeof(TExtHeader));
ptr:=BinSearchRes(ResHeader,ptr,ResourceType);
if ptr=nil then exit;
totn:=ptr^.ncounthandle;
totid:=totn+ptr^.idcountsize;
ptr:=GetResInfoPtr(ResHeader,ptr^.subptr);
if Other<>nil then
begin
otarr:=GetResInfoPtr(Other,sizeof(TExtHeader));
otarr:=BinSearchRes(Other,otarr,ResourceType);
if otarr<>nil then
begin
ottotn:=otarr^.ncounthandle;
ottotid:=ottotn+otarr^.idcountsize-1;
otarr:=GetResInfoPtr(Other,otarr^.subptr)
end;
end
else otarr:=nil;
EnumResourceNamesSingleFile:=true;
i:=0;
while i<totn do //named entries
begin
pc:=GetPChar(ResHeader,ptr[i].nameid);
if (otarr=nil) or (BinSearchStr(Other,otarr,pc,0,ottotn-1)=nil) then
if not EnumFunc(ModuleHandle,ResourceType,pc,lParam) then exit;
inc(i);
end;
while i<totid do
begin
if (otarr=nil) or (BinSearchInt(otarr,PChar(ptr[i].nameid),ottotn,ottotid)=nil) then
if not EnumFunc(ModuleHandle,ResourceType,PChar(ptr[i].nameid),lParam) then exit;
inc(i);
end;
end;
function EnumResourceLanguagesSingleFile(ResHeader,Other : PExtHeader;
ModuleHandle : TFPResourceHMODULE; ResourceType, ResourceName : PChar;
EnumFunc : EnumResLangProc; lParam : PtrInt) : LongBool;
var ptr, otarr : PResInfoNode;
tot, ottot, i : integer;
begin
EnumResourceLanguagesSingleFile:=False;
ptr:=InternalFindResource(ResHeader,ResourceName,ResourceType);
if ptr=nil then exit;
tot:=ptr^.idcountsize;
ptr:=GetResInfoPtr(ResHeader,ptr^.subptr);
if Other<>nil then
begin
otarr:=InternalFindResource(Other,ResourceName,ResourceType);
if otarr<>nil then
begin
ottot:=otarr^.idcountsize-1;
otarr:=GetResInfoPtr(Other,otarr^.subptr)
end;
end
else otarr:=nil;
EnumResourceLanguagesSingleFile:=true;
i:=0;
while i<tot do
begin
if (otarr=nil) or (BinSearchInt(otarr,PChar(ptr[i].nameid),0,ottot)=nil) then
if not EnumFunc(ModuleHandle,ResourceType,ResourceName,PtrUInt(
ptr[i].nameid),lParam) then exit;
inc(i);
end;
end;
(*****************************************************************************
Public Resource Functions
*****************************************************************************)
function ExtHINSTANCE : TFPResourceHMODULE;
begin
ExtHINSTANCE:=0;
end;
function ExtEnumResourceTypes(ModuleHandle : TFPResourceHMODULE; EnumFunc : EnumResTypeProc; lParam : PtrInt) : LongBool;
begin
ExtEnumResourceTypes:=false;
if EnumResourceTypesSingleFile(ResFileInfoArch.Resheader,nil,ModuleHandle,
EnumFunc,lParam) then ExtEnumResourceTypes:=true;
if EnumResourceTypesSingleFile(ResFileInfo.Resheader,
ResFileInfoArch.Resheader,ModuleHandle,EnumFunc,lParam) then ExtEnumResourceTypes:=true;
end;
function ExtEnumResourceNames(ModuleHandle : TFPResourceHMODULE; ResourceType : PChar; EnumFunc : EnumResNameProc; lParam : PtrInt) : LongBool;
begin
ExtEnumResourceNames:=False;
if EnumResourceNamesSingleFile(ResFileInfoArch.Resheader,nil,ModuleHandle,
ResourceType,EnumFunc,lParam) then ExtEnumResourceNames:=true;
if EnumResourceNamesSingleFile(ResFileInfo.Resheader,
ResFileInfoArch.Resheader,ModuleHandle,ResourceType,EnumFunc,lParam) then ExtEnumResourceNames:=true;
end;
function ExtEnumResourceLanguages(ModuleHandle : TFPResourceHMODULE; ResourceType, ResourceName : PChar; EnumFunc : EnumResLangProc; lParam : PtrInt) : LongBool;
begin
ExtEnumResourceLanguages:=False;
if EnumResourceLanguagesSingleFile(ResFileInfoArch.Resheader,nil,ModuleHandle,
ResourceType,ResourceName,EnumFunc,lParam) then ExtEnumResourceLanguages:=true;
if EnumResourceLanguagesSingleFile(ResFileInfo.Resheader,
ResFileInfoArch.Resheader,ModuleHandle,ResourceType,ResourceName,EnumFunc,
lParam) then ExtEnumResourceLanguages:=true;
end;
function ExtFindResource(ModuleHandle: TFPResourceHMODULE; ResourceName, ResourceType: PChar): TFPResourceHandle;
begin
//search for resource in architecture-dependent res file first
ExtFindResource:=FindResourceSingleFile(ResFileInfoArch.ResHeader,ResourceName,ResourceType);
if ExtFindResource=0 then
ExtFindResource:=FindResourceSingleFile(ResFileInfo.ResHeader,ResourceName,ResourceType);
end;
function ExtFindResourceEx(ModuleHandle: TFPResourceHMODULE; ResourceType, ResourceName: PChar; Language : word): TFPResourceHandle;
var precar, precsh : integer;
handlear, handlesh : TResourceHandle;
begin
//architecture-dependent res file
handlear:=FindResourceExSingleFile(ResFileInfoArch.ResHeader,ResourceType,
ResourceName,Language,precar);
//architecture-independent res file
handlesh:=FindResourceExSingleFile(ResFileInfo.ResHeader,ResourceType,
ResourceName,Language,precsh);
//return architecture-independent resource only if its language id is closer
//to the one user asked for
if precsh>precar then ExtFindResourceEx:=handlesh
else ExtFindResourceEx:=handlear;
end;
function ExtLoadResource(ModuleHandle: TFPResourceHMODULE; ResHandle: TFPResourceHandle): TFPResourceHGLOBAL;
var ptr : PResInfoNode;
base : PExtHeader;
begin
ExtLoadResource:=0;
if (ResHandle<=0) or (ResHandle>usedhandles) then exit;
ptr:=PResInfoNode(reshandles[ResHandle-1]);
base:=ResFileInfoArch.ResHeader;
//if ptr isn't in architecture-dependent file memory area...
if (base=nil) or (pointer(ptr)<=pointer(base))
or (pointer(ptr)>=GetPtr(base,base^.hdrsize)) then
base:=ResFileInfo.ResHeader;
ExtLoadResource:=TFPResourceHGLOBAL(GetPtr(base,ptr^.subptr));
end;
function ExtSizeofResource(ModuleHandle: TFPResourceHMODULE; ResHandle: TFPResourceHandle): LongWord;
begin
ExtSizeofResource:=0;
if (ResHandle<=0) or (ResHandle>usedhandles) then exit;
ExtSizeofResource:=PResInfoNode(reshandles[ResHandle-1])^.idcountsize;
end;
function ExtLockResource(ResData: TFPResourceHGLOBAL): Pointer;
begin
ExtLockResource:=Nil;
if (ResFileInfoArch.Resheader=nil) and (ResFileInfo.Resheader=nil) then exit;
ExtLockResource:=Pointer(ResData);
end;
function ExtUnlockResource(ResData: TFPResourceHGLOBAL): LongBool;
begin
ExtUnlockResource:=(ResFileInfoArch.Resheader<>nil) or (ResFileInfo.Resheader<>nil);
end;
function ExtFreeResource(ResData: TFPResourceHGLOBAL): LongBool;
begin
ExtFreeResource:=(ResFileInfoArch.Resheader<>nil) or (ResFileInfo.Resheader<>nil);
end;
const
ExternalResourceManager : TResourceManager =
(
HINSTANCEFunc : @ExtHINSTANCE;
EnumResourceTypesFunc : @ExtEnumResourceTypes;
EnumResourceNamesFunc : @ExtEnumResourceNames;
EnumResourceLanguagesFunc : @ExtEnumResourceLanguages;
FindResourceFunc : @ExtFindResource;
FindResourceExFunc : @ExtFindResourceEx;
LoadResourceFunc : @ExtLoadResource;
SizeofResourceFunc : @ExtSizeofResource;
LockResourceFunc : @ExtLockResource;
UnlockResourceFunc : @ExtUnlockResource;
FreeResourceFunc : @ExtFreeResource;
);