stringtableresource.pp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2008 by Giulio Bernardi
  4. String table resource type
  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. {$IFNDEF FPC_DOTTEDUNITS}
  12. unit stringtableresource;
  13. {$ENDIF FPC_DOTTEDUNITS}
  14. {$MODE OBJFPC}
  15. interface
  16. {$IFDEF FPC_DOTTEDUNITS}
  17. uses
  18. System.Classes, System.SysUtils, System.Resources.Resource;
  19. {$ELSE FPC_DOTTEDUNITS}
  20. uses
  21. Classes, SysUtils, resource;
  22. {$ENDIF FPC_DOTTEDUNITS}
  23. type
  24. EStringTableResourceException = class(EResourceException);
  25. EStringTableNameNotAllowedException = class(EStringTableResourceException);
  26. EStringTableIndexOutOfBoundsException = class(EStringTableResourceException);
  27. resourcestring
  28. SNameNotAllowed = 'Resource ID must be an ordinal in the range 1-4096';
  29. SIndexOutOfBounds = 'String ID out of bounds: %d';
  30. type
  31. { TStringTableResource }
  32. TStringTableResource = class(TAbstractResource)
  33. private
  34. fType : TResourceDesc;
  35. fName : TResourceDesc;
  36. fFirstID : word;
  37. fCount : integer;
  38. fList : array of UnicodeString;
  39. fCanChangeDesc : boolean;
  40. function IDtoIndex(const aId : word) : integer;
  41. procedure CheckListLoaded;
  42. function ReadWideString : string;
  43. procedure WriteWideString(const aString : string);
  44. function GetLastID : word;
  45. procedure SetFirstID(aId : word);
  46. function GetString(id : word) : string;
  47. procedure SetString(id : word; aString : string);
  48. procedure CheckIndex(const aIndex : word);
  49. protected
  50. function GetType : TResourceDesc; override;
  51. function GetName : TResourceDesc; override;
  52. function ChangeDescTypeAllowed(aDesc : TResourceDesc) : boolean; override;
  53. function ChangeDescValueAllowed(aDesc : TResourceDesc) : boolean; override;
  54. procedure NotifyResourcesLoaded; override;
  55. public
  56. constructor Create; override;
  57. constructor Create(aType,aName : TResourceDesc); override;
  58. destructor Destroy; override;
  59. procedure UpdateRawData; override;
  60. property FirstID : word read fFirstID write SetFirstID;
  61. property LastID : word read GetLastID;
  62. property Count : integer read fCount;
  63. property Strings[id : word] : string read GetString write SetString; default;
  64. end;
  65. implementation
  66. {$IFDEF FPC_DOTTEDUNITS}
  67. uses
  68. System.Resources.Factory;
  69. {$ELSE FPC_DOTTEDUNITS}
  70. uses
  71. resfactory;
  72. {$ENDIF FPC_DOTTEDUNITS}
  73. { TStringTableResource }
  74. function TStringTableResource.IDtoIndex(const aId: word): integer;
  75. begin
  76. Result:=aID-fFirstID;
  77. end;
  78. procedure TStringTableResource.CheckListLoaded;
  79. var i : integer;
  80. begin
  81. if Length(fList) <> 0 then exit;
  82. SetLength(fList, fCount);
  83. for i:=0 to high(fList) do
  84. fList[i]:= '';
  85. if RawData.Size=0 then exit;
  86. RawData.Position:=0;
  87. for i:=0 to high(fList) do
  88. fList[i]:= ReadWideString;
  89. end;
  90. function TStringTableResource.ReadWideString: string;
  91. var ws : unicodestring;
  92. w : word;
  93. i : integer;
  94. begin
  95. RawData.ReadBuffer(w,2);
  96. w:= LEtoN(w);
  97. setlength(ws,w);
  98. for i:=1 to length(ws) do
  99. begin
  100. RawData.ReadBuffer(w,2);
  101. w:= LEtoN(w);
  102. ws[i]:=widechar(w);
  103. end;
  104. Result:=ws;
  105. end;
  106. procedure TStringTableResource.WriteWideString(const aString: string);
  107. var ws : unicodestring;
  108. w : word;
  109. i : integer;
  110. begin
  111. w:=length(aString);
  112. w:= NtoLE(w);
  113. RawData.WriteBuffer(w,2);
  114. ws:=aString;
  115. for i:=1 to length(ws) do
  116. begin
  117. w:=word(ws[i]);
  118. w:= NtoLE(w);
  119. RawData.WriteBuffer(w,2);
  120. end;
  121. end;
  122. function TStringTableResource.GetLastID: word;
  123. begin
  124. Result:=fFirstID+15;
  125. end;
  126. procedure TStringTableResource.SetFirstID(aId: word);
  127. begin
  128. aId:=aID and $FFF0;
  129. fFirstID:=aID;
  130. fCanChangeDesc:=true;
  131. fName.ID:=(aID div 16)+1;
  132. fCanChangeDesc:=false;
  133. end;
  134. function TStringTableResource.GetString(id: word): string;
  135. var idx : integer;
  136. begin
  137. CheckIndex(id);
  138. CheckListLoaded;
  139. idx:=IDtoIndex(id);
  140. if idx>high(fList) then Result:= ''
  141. else Result:= fList[idx];
  142. end;
  143. procedure TStringTableResource.SetString(id: word; aString: string);
  144. var idx,i : integer;
  145. begin
  146. CheckIndex(id);
  147. CheckListLoaded;
  148. idx:=IDtoIndex(id);
  149. fList[idx]:= aString;
  150. end;
  151. procedure TStringTableResource.UpdateRawData;
  152. var i : integer;
  153. begin
  154. if fList=nil then exit;
  155. RawData.Size:=0;
  156. RawData.Position:=0;
  157. for i:=FirstID to LastID do
  158. WriteWideString(Strings[i]);
  159. fList:= nil;
  160. end;
  161. function TStringTableResource.GetType: TResourceDesc;
  162. begin
  163. Result:=fType;
  164. end;
  165. function TStringTableResource.GetName: TResourceDesc;
  166. begin
  167. Result:=fName;
  168. end;
  169. function TStringTableResource.ChangeDescTypeAllowed(aDesc: TResourceDesc
  170. ): boolean;
  171. begin
  172. Result:=fCanChangeDesc;
  173. end;
  174. function TStringTableResource.ChangeDescValueAllowed(aDesc: TResourceDesc
  175. ): boolean;
  176. begin
  177. Result:=fCanChangeDesc;
  178. end;
  179. procedure TStringTableResource.NotifyResourcesLoaded;
  180. begin
  181. end;
  182. procedure TStringTableResource.CheckIndex(const aIndex: word);
  183. begin
  184. if (aIndex<FirstID) or (aIndex>LastID) then
  185. raise EStringTableIndexOutOfBoundsException.CreateFmt(SIndexOutOfBounds,[aIndex])
  186. end;
  187. constructor TStringTableResource.Create;
  188. begin
  189. inherited Create;
  190. fCanChangeDesc:=false;
  191. fList:= nil;
  192. fType:=TResourceDesc.Create(RT_STRING);
  193. fName:=TResourceDesc.Create(1);
  194. fCount:=16;
  195. fFirstID:=0;
  196. SetDescOwner(fType);
  197. SetDescOwner(fName);
  198. end;
  199. constructor TStringTableResource.Create(aType, aName: TResourceDesc);
  200. begin
  201. Create;
  202. if (aName.DescType<>dtId) or ((aName.ID <1) or (aName.ID >4096)) then
  203. raise EStringTableNameNotAllowedException.Create(SNameNotAllowed);
  204. fCanChangeDesc:=true;
  205. fName.Assign(aName);
  206. fCanChangeDesc:=false;
  207. fCount:=16;
  208. fFirstID:=(fName.ID-1) * 16;
  209. end;
  210. destructor TStringTableResource.Destroy;
  211. begin
  212. fType.Free;
  213. fName.Free;
  214. SetLength(fList, 0);
  215. inherited Destroy;
  216. end;
  217. initialization
  218. TResourceFactory.RegisterResourceClass(RT_STRING,TStringTableResource);
  219. end.