DEADSOFTWARE

Fix typos: promt -> prompt
[d2df-editor.git] / src / editor / g_resources.pas
index 9605b1a303361b5b85a3312ccfc02ab163845520..85a78356f67bd3e6794c5394d075320b4a011f82 100644 (file)
@@ -1,8 +1,17 @@
+{$ASSERTIONS ON}
 unit g_resources;
 
 interface
 
   (**
+    g_GetResourceSection
+      Parse path in form 'path/to/file.wad:some/section/resouce' to
+      wad = 'path/to/file.wad', section = 'some/section', name = 'resource'
+
+    g_DeleteFile
+      Delete file if it exists. Make backup if enabled.
+      return true when file not exists.
+
     g_ReadResource
       Read whole file from wad
       (data <> nil) and (len > 0) when ok
@@ -26,7 +35,13 @@ interface
       res = 0 when ok
   **)
 
+  (* Editor options *)
+  var
+    Compress: Boolean;
+    Backup: Boolean;
+
   procedure g_GetResourceSection (path: String; out wad, section, name: String);
+  function  g_DeleteFile(wad: String; backupPostfix: String = '.bak'): Boolean;
 
   procedure g_ReadResource (wad, section, name: String; out data: PByte; out len: Integer);
   procedure g_ReadSubResource (wad, section0, name0, section1, name1: String; out data: PByte; out len: Integer);
@@ -84,11 +99,31 @@ implementation
     wad := Copy(path, 1, i - 1);
   end;
 
+  function g_DeleteFile (wad: String; backupPostfix: String = '.bak'): Boolean;
+    var newwad: String; ok: Boolean;
+  begin
+    SFSGCCollect;
+    SFSGCCollect;
+    SFSGCCollect;
+    ok := true;
+    if FileExists(wad) then
+    begin
+      if Backup then
+      begin
+        newwad := wad + backupPostfix;
+        if FileExists(newwad) then ok := DeleteFile(newwad);
+        if ok then ok := RenameFile(wad, newwad);
+      end
+      else
+        ok := DeleteFile(wad);
+    end;
+    result := ok;
+  end;
+
   procedure g_AddResourceToDFWAD (wad, section, name: String; const data: PByte; len: Integer; out res: Integer);
     var f: TWADEditor_1;
   begin
     res := 1; (* error *)
-    wad := utf2win(wad);
     section := utf2win(NoTrailing(section));
     name := utf2win(name);
     ASSERT(name <> '');
@@ -100,12 +135,7 @@ implementation
     f.CreateImage;
     f.RemoveResource(section, name);
     f.AddResource(data, len, name, section);
-    if FileExists(wad) then
-    begin
-      if FileExists(wad + '.bak') then
-        ASSERT(DeleteFile(wad + '.bak'));
-      ASSERT(RenameFile(wad, wad + '.bak'))
-    end;
+    g_DeleteFile(wad);
     f.SaveTo(wad);
     f.Free;
     res := 0
@@ -119,13 +149,14 @@ implementation
       tmp, path: String;
       ts: TFileStream;
       dir: array of TFileInfo;
+      ok: Boolean;
 
     procedure Add (name: String; data: PByte; len: Integer);
       var ds: TSFSMemoryChunkStream;
     begin
       SetLength(dir, n + 1);
-      ds := TSFSMemoryChunkStream.Create(data, len, false);
-      dir[n] := dfzip.ZipOne(ts, name, ds);
+      ds := TSFSMemoryChunkStream.Create(data, len, False);
+      dir[n] := dfzip.ZipOne(ts, name, ds, Compress);
       ds.Free;
       INC(n);
     end;
@@ -146,9 +177,9 @@ implementation
       for i := 0 to list.Count - 1 do
       begin
         path := NoTrailing(list.Files[i].path);
-        if (path <> section) or (list.Files[i].name <> section) then
+        if (path <> section) or (list.Files[i].name <> name) then
         begin
-          g_ReadResource(wad, path, list.Files[i].name, data0, len0);
+          g_ReadResource(wad, win2utf(path), win2utf(list.Files[i].name), data0, len0);
           ASSERT(data0 <> nil);
           if path = '' then
             path := list.Files[i].name
@@ -170,14 +201,11 @@ implementation
     dfzip.writeCentralDir(ts, dir);
     ts.Free;
 
-    if FileExists(wad) then
-    begin
-      if FileExists(wad + '.bak') then
-        ASSERT(DeleteFile(wad + '.bak'));
-      ASSERT(RenameFile(wad, wad + '.bak'))
-    end;
-    ASSERT(RenameFile(tmp, wad));
-    res := 0
+    ok := g_DeleteFile(wad);
+    if not ok then e_WriteLog('Cant delete older wad [' + wad + ']', TRecordCategory.MSG_WARNING);
+    ok := RenameFile(tmp, wad);
+    if not ok then e_WriteLog('ERROR: Cant rename [' + tmp + '] -> [' + wad + ']', TRecordCategory.MSG_WARNING);
+    if ok then res := 0 else res := 2;
   end;
 
   procedure g_AddResource (wad, section, name: String; const data: PByte; len: Integer; out res: Integer);
@@ -189,7 +217,7 @@ implementation
     e_WriteLog('g_AddResource "' + wad + '" "' + section + '" "' + name + '"', MSG_NOTIFY);
     if ext = '.wad' then
       g_AddResourceToDFWAD(wad, section, name, data, len, res)
-    else if (ext = '.pk3') or (ext = '.zip') or (ext = '.dfzip') then
+    else
       g_AddResourceToZip(wad, section, name, data, len, res)
   end;
 
@@ -208,6 +236,7 @@ implementation
     end;
     f.CreateImage;
     f.RemoveResource(section, name);
+    g_DeleteFile(wad);
     f.SaveTo(wad);
     f.Free;
     res := 0 (* ok *)
@@ -221,13 +250,14 @@ implementation
       tmp, path: String;
       ts: TFileStream;
       dir: array of TFileInfo;
+      ok: Boolean;
 
     procedure Add (name: String; data: PByte; len: Integer);
       var ds: TSFSMemoryChunkStream;
     begin
       SetLength(dir, n + 1);
-      ds := TSFSMemoryChunkStream.Create(data, len, false);
-      dir[n] := dfzip.ZipOne(ts, name, ds);
+      ds := TSFSMemoryChunkStream.Create(data, len, False);
+      dir[n] := dfzip.ZipOne(ts, name, ds, Compress);
       ds.Free;
       INC(n);
     end;
@@ -248,9 +278,9 @@ implementation
       for i := 0 to list.Count - 1 do
       begin
         path := NoTrailing(list.Files[i].path);
-        if (path <> section) or (list.Files[i].name <> section) then
+        if (path <> section) or (list.Files[i].name <> name) then
         begin
-          g_ReadResource(wad, path, list.Files[i].name, data0, len0);
+          g_ReadResource(wad, win2utf(path), win2utf(list.Files[i].name), data0, len0);
           ASSERT(data0 <> nil);
           if path = '' then
             path := list.Files[i].name
@@ -266,14 +296,11 @@ implementation
     dfzip.writeCentralDir(ts, dir);
     ts.Free;
 
-    if FileExists(wad) then
-    begin
-      if FileExists(wad + '.bak') then
-        ASSERT(DeleteFile(wad + '.bak'));
-      ASSERT(RenameFile(wad, wad + '.bak'))
-    end;
-    ASSERT(RenameFile(tmp, wad));
-    res := 0
+    ok := g_DeleteFile(wad);
+    if not ok then e_WriteLog('Cant delete older wad [' + wad + ']', TRecordCategory.MSG_WARNING);
+    ok := RenameFile(tmp, wad);
+    if not ok then e_WriteLog('ERROR: Cant rename [' + tmp + '] -> [' + wad + ']', TRecordCategory.MSG_WARNING);
+    if ok then res := 0 else res := 2;
   end;
 
   procedure g_DeleteResource (wad, section, name: String; out res: Integer);
@@ -284,7 +311,7 @@ implementation
     ext := LowerCase(SysUtils.ExtractFileExt(wad));
     if ext = '.wad' then
       g_DeleteResourceFromDFWAD(wad, section, name, res)
-    else if (ext = '.dfz') or (ext = '.pk3') or (ext = '.zip') or (ext = '.dfzip') then
+    else
       g_DeleteResourceFromZip(wad, section, name, res)
   end;
 
@@ -367,12 +394,17 @@ implementation
             for i := 0 to len - 1 do
               data[i] := stream1.ReadByte();
             stream1.Destroy
+            //stream0.Destroy (* leads to memory corruption, it destroyed with stream1? *)
+          end
+          else
+          begin
+            stream0.Destroy
           end
         end
-      end
-      else
-      begin
-        stream0.Destroy
+        else
+        begin
+          stream0.Destroy
+        end
       end
     end;
     SFSGCCollect