DEADSOFTWARE

Fix memory leaks when managing the undo buffer
[d2df-editor.git] / src / editor / f_main.pas
index bf92c229531d27eacc2a0bb83561c9ed3bcb9dd4..e4e0643b38045f34c23e8ea78a81895c00965736 100644 (file)
@@ -271,6 +271,7 @@ type
     procedure FormKeyUp(Sender: TObject; var Key: Word;
       Shift: TShiftState);
   private
+    LastDrawTime: UInt64;
     procedure Draw();
     procedure OnIdle(Sender: TObject; var Done: Boolean);
     procedure RefillRecentMenu (menu: TMenuItem; start: Integer; fmt: AnsiString);
@@ -1825,16 +1826,28 @@ begin
   end;
 
   UndoBuffer[i, ii].AddID := ID;
-
   MainForm.miUndo.Enabled := UndoBuffer <> nil;
 end;
 
+procedure DiscardUndoBuffer();
+var
+  i, k: Integer;
+begin
+  for i := 0 to High(UndoBuffer) do
+    for k := 0 to High(UndoBuffer[i]) do
+      with UndoBuffer[i][k] do
+        if UndoType = UNDO_DELETE_PANEL then
+          Dispose(Panel);
+
+  UndoBuffer := nil;
+end;
+
 procedure FullClear();
 begin
   RemoveSelectFromObjects();
   ClearMap();
   LoadSky(gMapInfo.SkyName);
-  UndoBuffer := nil;
+  DiscardUndoBuffer();
   slInvalidTextures.Clear();
   MapCheckForm.lbErrorList.Clear();
   MapCheckForm.mErrorDescription.Clear();
@@ -2547,7 +2560,7 @@ begin
   if FileExists(fn) then
     OpenMap(fn, g_ExtractFilePathName(s))
   else
-    Application.MessageBox('', 'File not available anymore', MB_OK);
+    Application.MessageBox('File not available anymore', '', MB_OK);
 //  if Application.MessageBox(PChar(MsgMsgDelRecentPrompt), PChar(MsgMsgDelRecent), MB_ICONQUESTION or MB_YESNO) = idYes then
 //  begin
 //    RecentFiles.Delete(n);
@@ -2671,6 +2684,7 @@ var
   s: String;
 begin
   Randomize();
+  LastDrawTime := 0;
 
   {$IFDEF DARWIN}
     miApple.Enabled := True;
@@ -2891,6 +2905,7 @@ var
   ObjCount: Word;
   aX, aY, aX2, aY2, XX, ScaleSz: Integer;
 begin
+  LastDrawTime := GetTickCount64();
   ID := 0;
   PID := 0;
   Width := 0;
@@ -4432,7 +4447,8 @@ begin
   config.SaveFile(CfgFileName);
   config.Free();
 
-  slInvalidTextures.Free;
+  slInvalidTextures.Free();
+  DiscardUndoBuffer();
 end;
 
 procedure TMainForm.FormDropFiles(Sender: TObject;
@@ -4683,8 +4699,7 @@ begin
   end;
 
 // Удалить выделенные объекты:
-  if (Key = VK_DELETE) and (SelectedObjects <> nil) and
-     RenderPanel.Focused() then
+  if (Key = VK_DELETE) and (SelectedObjects <> nil) and RenderPanel.Focused() then
     DeleteSelectedObjects();
 
 // Снять выделение:
@@ -5583,7 +5598,7 @@ begin
         UNDO_DELETE_PANEL:
           begin
             AddPanel(Panel^);
-            Panel := nil;
+            Dispose(Panel);
           end;
         UNDO_DELETE_ITEM: AddItem(Item);
         UNDO_DELETE_AREA: AddArea(Area);
@@ -5598,9 +5613,7 @@ begin
     end;
 
   SetLength(UndoBuffer, Length(UndoBuffer)-1);
-
   RemoveSelectFromObjects();
-
   miUndo.Enabled := UndoBuffer <> nil;
 end;
 
@@ -6719,8 +6732,15 @@ begin
 end;
 
 procedure TMainForm.OnIdle(Sender: TObject; var Done: Boolean);
+  const MaxFPS = 60;
   var f: AnsiString;
 begin
+  // TODO: move refresh to user actions (ask to repaint only when something changed)
+  if GetTickCount64() - LastDrawTime >= 1000 div MaxFPS then
+  begin
+    PanelMap.Refresh;
+  end;
+
   if StartMap <> '' then
   begin
     f := StartMap;