intres.inc 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2008 by Giulio Bernardi
  4. Resource support for non-PECOFF targets (ELF, Mach-O)
  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. type
  12. PResInfoNode = ^TResInfoNode;
  13. TResInfoNode = packed record
  14. nameid : PChar; //name / integer ID / languageID
  15. ncounthandle : longword; //named sub-entries count / resource handle
  16. idcountsize : longword; //id sub-entries count / resource size
  17. subptr : PResInfoNode; //first sub-entry pointer
  18. end;
  19. TResHdr = packed record
  20. rootptr : PResInfoNode; //pointer to root node
  21. count : longword; //number of resources in the file
  22. usedhandles : longword; //last resource handle used
  23. handles : PPtrUint; //pointer to handles
  24. end;
  25. PResHdr = ^TResHdr;
  26. var
  27. {$ifdef FPC_HAS_WINLIKERESOURCES}
  28. ResHeader : PResHdr; external name 'FPC_RESLOCATION';
  29. {$else}
  30. ResHeader : PResHdr= nil;
  31. {$endif}
  32. (*****************************************************************************
  33. Private Helper Functions
  34. *****************************************************************************)
  35. //resource functions are case insensitive... copied from genstr.inc
  36. function ResStrIComp(Str1, Str2 : PChar): SizeInt;
  37. var
  38. counter: SizeInt;
  39. c1, c2: char;
  40. begin
  41. counter := 0;
  42. c1 := upcase(str1[counter]);
  43. c2 := upcase(str2[counter]);
  44. while c1 = c2 do
  45. begin
  46. if (c1 = #0) or (c2 = #0) then break;
  47. inc(counter);
  48. c1 := upcase(str1[counter]);
  49. c2 := upcase(str2[counter]);
  50. end;
  51. ResStrIComp := ord(c1) - ord(c2);
  52. end;
  53. {!fixme!}
  54. //function InternalIsIntResource(aStr : pchar; out aInt : PtrUint) : boolean;
  55. function InternalIsIntResource(aStr : pchar; var aInt : PtrUint) : boolean;
  56. var i : integer;
  57. s : shortstring;
  58. code : word;
  59. begin
  60. InternalIsIntResource:=((PtrUInt(aStr) shr 16)=0);
  61. if InternalIsIntResource then aInt:=PtrUInt(aStr)
  62. else
  63. begin
  64. //a string like #number specifies an integer id
  65. if aStr[0]='#' then
  66. begin
  67. i:=1;
  68. while aStr[i]<>#0 do
  69. inc(i);
  70. if i>256 then i:=256;
  71. s[0]:=chr(i-1);
  72. Move(aStr[1],s[1],i-1);
  73. Val(s,aInt,code);
  74. InternalIsIntResource:=code=0;
  75. end;
  76. end;
  77. end;
  78. function BinSearchStr(arr : PResInfoNode; query : pchar; left, right : integer)
  79. : PResInfoNode;
  80. var pivot, res : integer;
  81. resstr : pchar;
  82. begin
  83. BinSearchStr:=nil;
  84. while left<=right do
  85. begin
  86. pivot:=(left+right) div 2;
  87. resstr:=arr[pivot].nameid;
  88. res:=ResStrIComp(resstr,query);
  89. if res<0 then left:=pivot+1
  90. else if res>0 then right:=pivot-1
  91. else
  92. begin
  93. BinSearchStr:=@arr[pivot];
  94. exit;
  95. end;
  96. end;
  97. end;
  98. function BinSearchInt(arr : PResInfoNode; query : pchar; left, right : integer)
  99. : PResInfoNode;
  100. var pivot : integer;
  101. begin
  102. BinSearchInt:=nil;
  103. while left<=right do
  104. begin
  105. pivot:=(left+right) div 2;
  106. if PtrUint(arr[pivot].nameid)<PtrUInt(query) then left:=pivot+1
  107. else if PtrUint(arr[pivot].nameid)>PtrUInt(query) then right:=pivot-1
  108. else
  109. begin
  110. BinSearchInt:=@arr[pivot];
  111. exit;
  112. end;
  113. end;
  114. end;
  115. function BinSearchRes(root : PResInfoNode; aDesc : PChar) : PResInfoNode;
  116. var aID : PtrUint;
  117. begin
  118. if InternalIsIntResource(aDesc,aID) then
  119. BinSearchRes:=BinSearchInt(root^.subptr,PChar(aID),root^.ncounthandle,
  120. root^.ncounthandle+root^.idcountsize-1)
  121. else
  122. BinSearchRes:=BinSearchStr(root^.subptr,aDesc,0,root^.ncounthandle-1);
  123. end;
  124. //Returns a pointer to a name node.
  125. function InternalFindResource(ResourceName, ResourceType: PChar):
  126. PResInfoNode;
  127. begin
  128. InternalFindResource:=nil;
  129. if ResHeader=nil then exit;
  130. InternalFindResource:=ResHeader^.rootptr;
  131. InternalFindResource:=BinSearchRes(InternalFindResource,ResourceType);
  132. if InternalFindResource<>nil then
  133. InternalFindResource:=BinSearchRes(InternalFindResource,ResourceName);
  134. end;
  135. function FindSubLanguage(aPtr : PResInfoNode; aLangID : word; aMask: word) : PResInfoNode;
  136. var arr : PResInfoNode;
  137. i : longword;
  138. begin
  139. FindSubLanguage:=nil;
  140. arr:=aPtr^.subptr;
  141. i:=0;
  142. while i<aPtr^.idcountsize do
  143. begin
  144. if (PtrUInt(arr[i].nameid) and aMask)=(aLangID and aMask) then
  145. begin
  146. FindSubLanguage:=@arr[i];
  147. exit;
  148. end;
  149. inc(i);
  150. end;
  151. end;
  152. (*****************************************************************************
  153. Public Resource Functions
  154. *****************************************************************************)
  155. Function IntHINSTANCE : TFPResourceHMODULE;
  156. begin
  157. IntHINSTANCE:=0;
  158. end;
  159. Function IntEnumResourceTypes(ModuleHandle : TFPResourceHMODULE; EnumFunc : EnumResTypeProc; lParam : PtrInt) : LongBool;
  160. var ptr : PResInfoNode;
  161. tot, i : integer;
  162. begin
  163. IntEnumResourceTypes:=False;
  164. if ResHeader=nil then exit;
  165. tot:=ResHeader^.rootptr^.ncounthandle+ResHeader^.rootptr^.idcountsize;
  166. ptr:=ResHeader^.rootptr^.subptr;
  167. IntEnumResourceTypes:=true;
  168. i:=0;
  169. while i<tot do
  170. begin
  171. if not EnumFunc(ModuleHandle,ptr[i].nameid,lParam) then exit;
  172. inc(i);
  173. end;
  174. end;
  175. Function IntEnumResourceNames(ModuleHandle : TFPResourceHMODULE; ResourceType : PChar; EnumFunc : EnumResNameProc; lParam : PtrInt) : LongBool;
  176. var ptr : PResInfoNode;
  177. tot, i : integer;
  178. begin
  179. IntEnumResourceNames:=False;
  180. if ResHeader=nil then exit;
  181. ptr:=ResHeader^.rootptr;
  182. ptr:=BinSearchRes(ptr,ResourceType);
  183. if ptr=nil then exit;
  184. tot:=ptr^.ncounthandle+ptr^.idcountsize;
  185. ptr:=ptr^.subptr;
  186. IntEnumResourceNames:=true;
  187. i:=0;
  188. while i<tot do
  189. begin
  190. if not EnumFunc(ModuleHandle,ResourceType,ptr[i].nameid,lParam) then exit;
  191. inc(i);
  192. end;
  193. end;
  194. Function IntEnumResourceLanguages(ModuleHandle : TFPResourceHMODULE; ResourceType, ResourceName : PChar; EnumFunc : EnumResLangProc; lParam : PtrInt) : LongBool;
  195. var ptr : PResInfoNode;
  196. tot, i : integer;
  197. begin
  198. IntEnumResourceLanguages:=False;
  199. ptr:=InternalFindResource(ResourceName,ResourceType);
  200. if ptr=nil then exit;
  201. tot:=ptr^.idcountsize;
  202. ptr:=ptr^.subptr;
  203. IntEnumResourceLanguages:=true;
  204. i:=0;
  205. while i<tot do
  206. begin
  207. if not EnumFunc(ModuleHandle,ResourceType,ResourceName,PtrUInt(ptr[i].nameid),lParam) then exit;
  208. inc(i);
  209. end;
  210. end;
  211. Function IntFindResource(ModuleHandle: TFPResourceHMODULE; ResourceName,
  212. ResourceType: PChar): TFPResourceHandle;
  213. var ptr : PResInfoNode;
  214. begin
  215. IntFindResource:=0;
  216. ptr:=InternalFindResource(ResourceName,ResourceType);
  217. if ptr=nil then exit;
  218. //first language id
  219. ptr:=ptr^.subptr;
  220. if ptr^.ncounthandle=0 then
  221. begin
  222. ResHeader^.handles[ResHeader^.usedhandles]:=PtrUint(ptr);
  223. inc(ResHeader^.usedhandles);
  224. ptr^.ncounthandle:=ResHeader^.usedhandles;
  225. end;
  226. IntFindResource:=ptr^.ncounthandle;
  227. end;
  228. Function IntFindResourceEx(ModuleHandle: TFPResourceHMODULE; ResourceType,
  229. ResourceName: PChar; Language : word): TFPResourceHandle;
  230. const LANG_NEUTRAL = 0;
  231. LANG_ENGLISH = 9;
  232. var nameptr,ptr : PResInfoNode;
  233. begin
  234. IntFindResourceEx:=0;
  235. nameptr:=InternalFindResource(ResourceName,ResourceType);
  236. if nameptr=nil then exit;
  237. //try exact match
  238. ptr:=FindSubLanguage(nameptr,Language,$FFFF);
  239. //try primary language
  240. if ptr=nil then
  241. ptr:=FindSubLanguage(nameptr,Language,$3FF);
  242. //try language neutral
  243. if ptr=nil then
  244. ptr:=FindSubLanguage(nameptr,LANG_NEUTRAL,$3FF);
  245. //try english
  246. if ptr=nil then
  247. ptr:=FindSubLanguage(nameptr,LANG_ENGLISH,$3FF);
  248. //nothing found, return the first one
  249. if ptr=nil then
  250. ptr:=nameptr^.subptr;
  251. if ptr^.ncounthandle=0 then
  252. begin
  253. ResHeader^.handles[ResHeader^.usedhandles]:=PtrUint(ptr);
  254. inc(ResHeader^.usedhandles);
  255. ptr^.ncounthandle:=ResHeader^.usedhandles;
  256. end;
  257. IntFindResourceEx:=ptr^.ncounthandle;
  258. end;
  259. Function IntLoadResource(ModuleHandle: TFPResourceHMODULE; ResHandle: TFPResourceHandle): TFPResourceHGLOBAL;
  260. begin
  261. IntLoadResource:=0;
  262. if ResHeader=nil then exit;
  263. if (ResHandle<=0) or (ResHandle>ResHeader^.usedhandles) then exit;
  264. IntLoadResource:=TFPResourceHGLOBAL(PResInfoNode(ResHeader^.handles[ResHandle-1])^.subptr);
  265. end;
  266. Function IntSizeofResource(ModuleHandle: TFPResourceHMODULE; ResHandle: TFPResourceHandle): LongWord;
  267. begin
  268. IntSizeofResource:=0;
  269. if ResHeader=nil then exit;
  270. if (ResHandle<=0) or (ResHandle>ResHeader^.usedhandles) then exit;
  271. IntSizeofResource:=PResInfoNode(ResHeader^.handles[ResHandle-1])^.idcountsize;
  272. end;
  273. Function IntLockResource(ResData: TFPResourceHGLOBAL): Pointer;
  274. begin
  275. IntLockResource:=Nil;
  276. if ResHeader=nil then exit;
  277. IntLockResource:=Pointer(ResData);
  278. end;
  279. Function IntUnlockResource(ResData: TFPResourceHGLOBAL): LongBool;
  280. begin
  281. IntUnlockResource:=(ResHeader<>nil);
  282. end;
  283. Function IntFreeResource(ResData: TFPResourceHGLOBAL): LongBool;
  284. begin
  285. IntFreeResource:=(ResHeader<>nil);
  286. end;
  287. const
  288. InternalResourceManager : TResourceManager =
  289. (
  290. HINSTANCEFunc : @IntHINSTANCE;
  291. EnumResourceTypesFunc : @IntEnumResourceTypes;
  292. EnumResourceNamesFunc : @IntEnumResourceNames;
  293. EnumResourceLanguagesFunc : @IntEnumResourceLanguages;
  294. FindResourceFunc : @IntFindResource;
  295. FindResourceExFunc : @IntFindResourceEx;
  296. LoadResourceFunc : @IntLoadResource;
  297. SizeofResourceFunc : @IntSizeofResource;
  298. LockResourceFunc : @IntLockResource;
  299. UnlockResourceFunc : @IntUnlockResource;
  300. FreeResourceFunc : @IntFreeResource;
  301. );