DEADSOFTWARE

system: implement zip support again
[d2df-editor.git] / src / shared / WADEDITOR.pas
1 {$INCLUDE ../shared/a_modes.inc}
3 unit WADEDITOR;
5 // TWADEditor errors:
6 // - Create = DFWAD_NOERROR
7 // - FreeWAD = DFWAD_NOERROR
8 // - ReadFile -> DFWAD_ERROR_WADNOTFOUND, DFWAD_ERROR_CANTOPENWAD, DFWAD_ERROR_FILENOTWAD, DFWAD_ERROR_WRONGVERSION, DFWAD_ERROR_READWAD, DFWAD_NOERROR
9 // - ReadMemory -> DFWAD_ERROR_FILENOTWAD, DFWAD_ERROR_WRONGVERSION, DFWAD_NOERROR
10 // - CreateImage -> DFWAD_ERROR_WADNOTLOADED, DFWAD_OPENED_MEMORY, DFWAD_ERROR_CANTOPENWAD, DFWAD_NOERROR
11 // - AddResource (pointer)
12 // - AddResource (filename) -> DFWAD_ERROR_CANTOPENWAD, DFWAD_ERROR_READWAD, DFWAD_NOERROR
13 // - AddAlias
14 // - AddSection
15 // - RemoveResource
16 // - SaveTo
17 // - HaveResource
18 // - HaveSection
19 // - GetResource -> DFWAD_ERROR_WADNOTLOADED, DFWAD_ERROR_RESOURCENOTFOUND, DFWAD_ERROR_CANTOPENWAD, DFWAD_NOERROR
20 // - GetSectionList
21 // - GetResourcesList
23 interface
25 uses Classes;
27 const
28 DFWAD_NOERROR = 0;
29 DFWAD_ERROR_WADNOTFOUND = -1;
30 DFWAD_ERROR_CANTOPENWAD = -2;
31 DFWAD_ERROR_RESOURCENOTFOUND = -3;
32 DFWAD_ERROR_FILENOTWAD = -4;
33 DFWAD_ERROR_WADNOTLOADED = -5;
34 DFWAD_ERROR_READRESOURCE = -6;
35 DFWAD_ERROR_READWAD = -7;
36 DFWAD_ERROR_WRONGVERSION = -8;
38 type
39 SArray = array of ShortString;
41 TWADEditor = class abstract(TObject)
42 public
43 function ReadFile(FileName: string): Boolean;
45 function ReadFile2(FileName: string): Boolean; virtual; abstract;
46 function ReadMemory(Data: Pointer; Len: LongWord): Boolean; virtual; abstract;
47 procedure FreeWAD(); virtual; abstract;
48 procedure CreateImage(); virtual; abstract;
49 function AddResource(Data: Pointer; Len: LongWord; Name: string; Section: string): Boolean; virtual; abstract; overload;
50 function AddResource(FileName, Name, Section: string): Boolean; overload; virtual; abstract;
51 function AddAlias(Res, Alias: string): Boolean; virtual; abstract;
52 procedure AddSection(Name: string); virtual; abstract;
53 procedure RemoveResource(Section, Resource: string); virtual; abstract;
54 procedure SaveTo(FileName: string); virtual; abstract;
55 function HaveResource(Section, Resource: string): Boolean; virtual; abstract;
56 function HaveSection(Section: string): Boolean; virtual; abstract;
57 function GetResource(Section, Resource: string; var pData: Pointer; var Len: Integer): Boolean; virtual; abstract;
58 function GetSectionList(): SArray; virtual; abstract;
59 function GetResourcesList(Section: string): SArray; virtual; abstract;
61 function GetLastError: Integer; virtual; abstract;
62 function GetLastErrorStr: String; virtual; abstract;
63 function GetResourcesCount: Word; virtual; abstract;
64 function GetVersion: Byte; virtual; abstract;
65 end;
67 TWADEditorClass = class of TWADEditor;
69 TWADEditorMapping = class sealed(TObject)
70 private
71 FName: String;
72 FWADEditorClass: TWADEditorClass;
73 public
74 constructor CreateEx(const name: String; const eclass: TWADEditorClass);
75 property Name: String read FName;
76 property WADEditorClass: TWADEditorClass read FWADEditorClass;
77 end;
79 TWADEditorFactory = class sealed(TObject)
80 private
81 FMappings: TStringList;
82 FDefault: TWADEditorClass;
83 public
84 constructor Create;
85 destructor Destroy; override;
86 procedure RegisterEditor(const name: String; const eclass: TWADEditorClass);
87 procedure SetDefaultEditor(const name: String);
88 function CreateEditor(const name: String): TWADEditor;
89 function CreateDefaultEditor(): TWADEditor;
90 function OpenFile(FileName: String): TWADEditor;
91 function OpenMemory(Data: Pointer; Len: Integer): TWADEditor;
92 procedure GetRegistredEditors(var list: TStringList);
93 end;
95 // TWADEditor_1 deprecated
96 TWADEditor_1 = class sealed(TObject)
97 private
98 FBase: TWADEditor;
99 public
100 constructor Create();
101 destructor Destroy(); override;
102 procedure FreeWAD();
103 function ReadFile(FileName: string): Boolean;
104 function ReadMemory(Data: Pointer; Len: LongWord): Boolean;
105 procedure CreateImage();
106 function AddResource(Data: Pointer; Len: LongWord; Name: string; Section: string): Boolean; overload;
107 function AddResource(FileName, Name, Section: string): Boolean; overload;
108 function AddAlias(Res, Alias: string): Boolean;
109 procedure AddSection(Name: string);
110 procedure RemoveResource(Section, Resource: string);
111 procedure SaveTo(FileName: string);
112 function HaveResource(Section, Resource: string): Boolean;
113 function HaveSection(Section: string): Boolean;
114 function GetResource(Section, Resource: string; var pData: Pointer; var Len: Integer): Boolean;
115 function GetSectionList(): SArray;
116 function GetResourcesList(Section: string): SArray;
118 function GetLastError: Integer;
119 function GetLastErrorStr: String;
120 function GetResourcesCount: Word;
121 function GetVersion: Byte;
122 end;
124 procedure g_ProcessResourceStr(ResourceStr: String; var FileName, SectionName, ResourceName: String); overload;
125 procedure g_ProcessResourceStr(ResourceStr: String; FileName, SectionName, ResourceName: PString); overload;
127 function gWADEditorFactory: TWADEditorFactory;
129 implementation
131 uses SysUtils, utils;
133 var
134 uWADEditorFactory: TWADEditorFactory;
136 procedure g_ProcessResourceStr(ResourceStr: String; var FileName, SectionName, ResourceName: String);
137 var a, i: Integer;
138 begin
139 for i := Length(ResourceStr) downto 1 do
140 if ResourceStr[i] = ':' then
141 Break;
143 FileName := Copy(ResourceStr, 1, i-1);
145 for a := i+1 to Length(ResourceStr) do
146 if (ResourceStr[a] = '\') or (ResourceStr[a] = '/') then Break;
148 ResourceName := Copy(ResourceStr, a+1, Length(ResourceStr)-Abs(a));
149 SectionName := Copy(ResourceStr, i+1, Length(ResourceStr)-Length(ResourceName)-Length(FileName)-2);
150 end;
152 procedure g_ProcessResourceStr(ResourceStr: AnsiString; FileName, SectionName, ResourceName: PAnsiString);
153 var a, i, l1, l2: Integer;
154 begin
155 for i := Length(ResourceStr) downto 1 do
156 if ResourceStr[i] = ':' then
157 Break;
159 if FileName <> nil then
160 begin
161 FileName^ := Copy(ResourceStr, 1, i-1);
162 l1 := Length(FileName^);
163 end
164 else
165 l1 := 0;
167 for a := i+1 to Length(ResourceStr) do
168 if (ResourceStr[a] = '\') or (ResourceStr[a] = '/') then Break;
170 if ResourceName <> nil then
171 begin
172 ResourceName^ := Copy(ResourceStr, a+1, Length(ResourceStr)-Abs(a));
173 l2 := Length(ResourceName^);
174 end
175 else
176 l2 := 0;
178 if SectionName <> nil then
179 SectionName^ := Copy(ResourceStr, i+1, Length(ResourceStr)-l2-l1-2);
180 end;
182 { TWADEditor }
184 function TWADEditor.ReadFile(FileName: String): Boolean;
185 var fname: String;
186 begin
187 fname := findFileCIStr(FileName);
188 Result := ReadFile2(fname);
189 end;
191 { TWADEditorMapping }
193 constructor TWADEditorMapping.CreateEx(const name: String; const eclass: TWADEditorClass);
194 begin
195 Create;
196 FName := name;
197 FWADEditorClass := eclass;
198 end;
200 { TWADEditorFactory }
202 constructor TWADEditorFactory.Create;
203 begin
204 FMappings := TStringList.Create();
205 FDefault := nil;
206 end;
208 destructor TWADEditorFactory.Destroy;
209 var i: Integer;
210 begin
211 for i := 0 to FMappings.Count - 1 do
212 FMappings.Objects[i].Free();
213 FMappings.Free();
214 FDefault := nil;
215 end;
217 procedure TWADEditorFactory.RegisterEditor(const name: String; const eclass: TWADEditorClass);
218 begin
219 if FMappings.IndexOf(UpperCase(name)) <> -1 then
220 raise Exception.Create('Registering a duplicate WAD Editor name <' + name + '>');
221 if FDefault = nil then
222 FDefault := eclass;
223 FMappings.AddObject(UpperCase(name), TWADEditorMapping.CreateEx(name, eclass));
224 end;
226 procedure TWADEditorFactory.SetDefaultEditor(const name: String);
227 var i: Integer;
228 begin
229 i := FMappings.IndexOf(UpperCase(name));
230 if i = -1 then
231 raise Exception.Create('No WAD Editor was registred by the name <' + name + '>');
232 FDefault := TWADEditorMapping(FMappings.Objects[i]).WADEditorClass;
233 end;
235 function TWADEditorFactory.CreateEditor(const name: String): TWADEditor;
236 var i: Integer;
237 begin
238 if name = '' then
239 begin
240 Result := CreateDefaultEditor();
241 end
242 else
243 begin
244 i := FMappings.IndexOf(UpperCase(name));
245 if i = -1 then
246 raise Exception.Create('No WAD Editor was registred by the name <' + name + '>');
247 Result := TWADEditorMapping(FMappings.Objects[i]).WADEditorClass.Create();
248 end;
249 end;
251 function TWADEditorFactory.CreateDefaultEditor(): TWADEditor;
252 begin
253 if FDefault = nil then
254 raise Exception.Create('No default WAD Editor was registred');
255 Result := FDefault.Create();
256 end;
258 function TWADEditorFactory.OpenFile(FileName: String): TWADEditor;
259 var i: Integer; tmp: TWADEditor; fname: String;
260 begin
261 Result := nil;
262 if FMappings <> nil then
263 begin
264 fname := findFileCIStr(FileName);
265 for i := 0 to FMappings.Count - 1 do
266 begin
267 tmp := gWADEditorFactory.CreateEditor(FMappings[i]);
268 if tmp.ReadFile2(fname) then
269 begin
270 Result := tmp;
271 break;
272 end;
273 FreeAndNil(tmp);
274 end;
275 end;
276 end;
278 function TWADEditorFactory.OpenMemory(Data: Pointer; Len: Integer): TWADEditor;
279 var i: Integer; tmp: TWADEditor;
280 begin
281 Result := nil;
282 if FMappings <> nil then
283 begin
284 for i := 0 to FMappings.Count - 1 do
285 begin
286 tmp := gWADEditorFactory.CreateEditor(FMappings[i]);
287 if tmp.ReadMemory(Data, Len) then
288 begin
289 Result := tmp;
290 break;
291 end;
292 FreeAndNil(tmp);
293 end;
294 end;
295 end;
297 procedure TWADEditorFactory.GetRegistredEditors(var list: TStringList);
298 var i: Integer;
299 begin
300 list.Clear();
301 for i := 0 to FMappings.Count - 1 do
302 list.Add(TWADEditorMapping(FMappings.Objects[i]).Name);
303 end;
305 function gWADEditorFactory: TWADEditorFactory;
306 begin
307 if not Assigned(uWADEditorFactory) then
308 uWADEditorFactory := TWADEditorFactory.Create();
309 Result := uWADEditorFactory;
310 end;
312 { TWADEditor_1 }
314 constructor TWADEditor_1.Create();
315 begin
316 FBase := gWADEditorFactory.CreateDefaultEditor();
317 end;
319 destructor TWADEditor_1.Destroy();
320 begin
321 if FBase <> nil then
322 FBase.Free();
323 inherited;
324 end;
326 procedure TWADEditor_1.CreateImage();
327 begin
328 FBase.CreateImage();
329 end;
331 procedure TWADEditor_1.FreeWAD();
332 begin
333 FBase.FreeWAD();
334 end;
336 function TWADEditor_1.ReadFile(FileName: String): Boolean;
337 var tmp: TWADEditor;
338 begin
339 Result := FBase.ReadFile(FileName);
340 if Result = False then
341 begin
342 tmp := gWADEditorFactory.OpenFile(FileName);
343 if tmp <> nil then
344 begin
345 FreeAndNil(FBase);
346 FBase := tmp;
347 Result := True;
348 end;
349 end;
350 end;
352 function TWADEditor_1.ReadMemory(Data: Pointer; Len: LongWord): Boolean;
353 var tmp: TWADEditor;
354 begin
355 Result := FBase.ReadMemory(Data, Len);
356 if Result = False then
357 begin
358 tmp := gWADEditorFactory.OpenMemory(Data, Len);
359 if tmp <> nil then
360 begin
361 FreeAndNil(FBase);
362 FBase := tmp;
363 Result := True;
364 end;
365 end;
366 end;
368 procedure TWADEditor_1.SaveTo(FileName: string);
369 var fname: AnsiString;
370 begin
371 fname := findFileCIStr(FileName);
372 FBase.SaveTo(fname);
373 end;
375 function TWADEditor_1.AddAlias(Res, Alias: string): Boolean;
376 begin
377 Result := FBase.AddAlias(Res, Alias);
378 end;
380 function TWADEditor_1.AddResource(Data: Pointer; Len: LongWord; Name: string; Section: string): Boolean;
381 begin
382 Result := FBase.AddResource(Data, Len, Name, Section);
383 end;
385 function TWADEditor_1.AddResource(FileName, Name, Section: string): Boolean;
386 var fname: AnsiString;
387 begin
388 fname := findFileCIStr(FileName);
389 Result := FBase.AddResource(fname, Name, Section);
390 end;
392 procedure TWADEditor_1.AddSection(Name: string);
393 begin
394 FBase.AddSection(Name);
395 end;
397 function TWADEditor_1.GetSectionList(): SArray;
398 begin
399 Result := FBase.GetSectionList();
400 end;
402 function TWADEditor_1.HaveSection(Section: string): Boolean;
403 begin
404 Result := FBase.HaveSection(Section);
405 end;
407 function TWADEditor_1.GetResourcesList(Section: string): SArray;
408 begin
409 Result := FBase.GetResourcesList(Section);
410 end;
412 function TWADEditor_1.HaveResource(Section, Resource: string): Boolean;
413 begin
414 Result := FBase.HaveResource(Section, Resource);
415 end;
417 function TWADEditor_1.GetResource(Section, Resource: string; var pData: Pointer; var Len: Integer): Boolean;
418 begin
419 Result := FBase.GetResource(Section, Resource, pData, Len);
420 end;
422 procedure TWADEditor_1.RemoveResource(Section, Resource: string);
423 begin
424 FBase.RemoveResource(Section, Resource);
425 end;
427 function TWADEditor_1.GetLastError: Integer;
428 begin
429 Result := FBase.GetLastError();
430 end;
432 function TWADEditor_1.GetLastErrorStr: String;
433 begin
434 Result := FBase.GetLastErrorStr();
435 end;
437 function TWADEditor_1.GetResourcesCount: Word;
438 begin
439 Result := FBase.GetResourcesCount();
440 end;
442 function TWADEditor_1.GetVersion: Byte;
443 begin
444 Result := FBase.GetVersion;
445 end;
447 finalization
448 FreeAndNil(uWADEditorFactory);
449 end.