Descent3/editor/OrphanRemoveDlg.cpp
2024-09-25 23:47:03 +03:00

468 lines
12 KiB
C++

/*
* Descent 3
* Copyright (C) 2024 Parallax Software
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
--- HISTORICAL COMMENTS FOLLOW ---
* $Logfile: /DescentIII/Main/editor/OrphanRemoveDlg.cpp $
* $Revision: 1.1.1.1 $
* $Date: 2003-08-26 03:57:38 $
* $Author: kevinb $
*
* Orphan file delete
*
* $Log: not supported by cvs2svn $
*
* 4 4/09/99 3:46p Jeff
* handle new texture sound names
*
* 3 3/19/99 10:34a Jeff
* enable/disable controls when thinking
*
* 2 3/18/99 8:41p Jeff
* created orphan hunter dialog
*
* $NoKeywords: $
*/
// OrphanRemoveDlg.cpp : implementation file
//
#include <filesystem>
#include <regex>
#include "stdafx.h"
#include "editor.h"
#include "OrphanRemoveDlg.h"
#include "manage.h"
#include "doorpage.h"
#include "gamefilepage.h"
#include "genericpage.h"
#include "shippage.h"
#include "soundpage.h"
#include "texpage.h"
#include "weaponpage.h"
#include "ddio.h"
#include "mem.h"
#include "pserror.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// COrphanRemoveDlg dialog
COrphanRemoveDlg::COrphanRemoveDlg(CWnd *pParent /*=NULL*/) : CDialog(COrphanRemoveDlg::IDD, pParent) {
//{{AFX_DATA_INIT(COrphanRemoveDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}
void COrphanRemoveDlg::DoDataExchange(CDataExchange *pDX) {
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(COrphanRemoveDlg)
DDX_Control(pDX, IDC_LIST, m_List);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(COrphanRemoveDlg, CDialog)
//{{AFX_MSG_MAP(COrphanRemoveDlg)
ON_CBN_SELCHANGE(IDC_DIRECTORY, OnSelchangeDirectory)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// COrphanRemoveDlg message handlers
bool HasFilesCheckedOut(void) {
int i;
for (i = 0; i < MAX_TRACKLOCKS; i++) {
if (GlobalTrackLocks[i].used) {
return true;
}
}
return false;
}
bool IsFileInGameFile(const char *filename) {
int i;
for (i = 0; i < MAX_GAMEFILES; i++) {
if (Gamefiles[i].used) {
if (!stricmp(Gamefiles[i].name, filename)) {
return true;
}
}
}
return false;
}
bool IsFileInDoorPage(const char *filename) {
mngs_door_page doorpage;
int i;
for (i = 0; i < MAX_DOORS; i++) {
if (Doors[i].used) {
mng_AssignDoorToDoorPage(i, &doorpage);
if (!stricmp(doorpage.close_sound_name, filename))
return true;
if (!stricmp(doorpage.image_name, filename))
return true;
if (!stricmp(doorpage.open_sound_name, filename))
return true;
}
}
return false;
}
bool IsFileInGenericPage(const char *filename) {
mngs_generic_page genericpage;
int i;
int j, x;
for (i = 0; i < MAX_OBJECT_IDS; i++) {
if (Object_info[i].type != OBJ_NONE) {
mng_AssignObjInfoToGenericPage(i, &genericpage);
if (!stricmp(filename, genericpage.image_name))
return true;
if (!stricmp(filename, genericpage.med_image_name))
return true;
if (!stricmp(filename, genericpage.lo_image_name))
return true;
for (j = 0; j < MAX_OBJ_SOUNDS; j++) {
if (!stricmp(filename, genericpage.sound_name[j]))
return true;
}
for (j = 0; j < MAX_AI_SOUNDS; j++) {
if (!stricmp(filename, genericpage.ai_sound_name[j]))
return true;
}
for (x = 0; x < MAX_WBS_PER_OBJ; x++) {
for (j = 0; j < MAX_WB_FIRING_MASKS; j++) {
if (!stricmp(filename, genericpage.fire_sound_name[x][j]))
return true;
}
for (j = 0; j < MAX_WB_GUNPOINTS; j++) {
if (!stricmp(filename, genericpage.weapon_name[x][j]))
return true;
}
}
for (x = 0; x < NUM_MOVEMENT_CLASSES; x++)
for (j = 0; j < NUM_ANIMS_PER_CLASS; j++) {
if (!stricmp(filename, genericpage.anim_sound_name[x][j]))
return true;
}
for (j = 0; j < MAX_DSPEW_TYPES; j++) {
if (!stricmp(filename, genericpage.dspew_name[j]))
return true;
}
if (genericpage.objinfo_struct.description) {
mem_free(genericpage.objinfo_struct.description);
}
}
}
return false;
}
bool IsFileInShipPage(const char *filename) {
mngs_ship_page shippage;
int i;
int j;
int x;
for (i = 0; i < MAX_SHIPS; i++) {
if (Ships[i].used) {
mng_AssignShipToShipPage(i, &shippage);
if (!stricmp(filename, shippage.image_name))
return true;
if (!stricmp(filename, shippage.dying_image_name))
return true;
if (!stricmp(filename, shippage.med_image_name))
return true;
if (!stricmp(filename, shippage.lo_image_name))
return true;
for (j = 0; j < MAX_PLAYER_WEAPONS; j++) {
for (x = 0; x < MAX_WB_GUNPOINTS; x++) {
if (!stricmp(filename, shippage.weapon_name[j][x]))
return true;
}
for (x = 0; x < MAX_WB_FIRING_MASKS; x++) {
if (!stricmp(filename, shippage.fire_sound_name[j][x]))
return true;
}
if (!stricmp(filename, shippage.firing_sound_name[j]))
return true;
if (!stricmp(filename, shippage.release_sound_name[j]))
return true;
if (!stricmp(filename, shippage.spew_powerup_name[j]))
return true;
}
}
}
return false;
}
bool IsFileInSoundPage(const char *filename) {
mngs_sound_page soundpage;
int i;
for (i = 0; i < MAX_SOUNDS; i++) {
if (Sounds[i].used) {
mng_AssignSoundToSoundPage(i, &soundpage);
if (!stricmp(filename, soundpage.raw_name))
return true;
}
}
return false;
}
bool IsFileInTexturePage(const char *filename) {
mngs_texture_page texpage;
int i;
for (i = 0; i < MAX_TEXTURES; i++) {
if (GameTextures[i].used) {
mng_AssignTextureToTexPage(i, &texpage);
if (!stricmp(filename, texpage.bitmap_name))
return true;
if (!stricmp(filename, texpage.destroy_name))
return true;
if (!stricmp(filename, texpage.sound_name))
return true;
}
}
return false;
}
bool IsFileInWeaponPage(const char *filename) {
mngs_weapon_page weappage;
int i, j;
for (i = 0; i < MAX_WEAPONS; i++) {
if (Weapons[i].used) {
mng_AssignWeaponToWeaponPage(i, &weappage);
if (!stricmp(filename, weappage.hud_image_name))
return true;
if (!stricmp(filename, weappage.fire_image_name))
return true;
if (!stricmp(filename, weappage.explode_image_name))
return true;
if (!stricmp(filename, weappage.smoke_image_name))
return true;
if (!stricmp(filename, weappage.scorch_image_name))
return true;
if (!stricmp(filename, weappage.icon_name))
return true;
if (!stricmp(filename, weappage.spawn_name))
return true;
if (!stricmp(filename, weappage.alternate_spawn_name))
return true;
if (!stricmp(filename, weappage.particle_name))
return true;
if (!stricmp(filename, weappage.robot_spawn_name))
return true;
for (j = 0; j < MAX_WEAPON_SOUNDS; j++) {
if (!stricmp(filename, weappage.sound_name[j]))
return true;
}
}
}
return false;
}
void COrphanRemoveDlg::Enable(bool enable) {
CWnd *wnd;
wnd = (CWnd *)GetDlgItem(IDOK);
wnd->EnableWindow(enable);
wnd = (CWnd *)GetDlgItem(IDCANCEL);
wnd->EnableWindow(enable);
wnd = (CWnd *)GetDlgItem(IDC_DIRECTORY);
wnd->EnableWindow(enable);
}
void COrphanRemoveDlg::SetStatus(const char *status) {
CWnd *stat = (CWnd *)GetDlgItem(IDC_STATUS);
stat->SetWindowText(status);
Descent->defer();
}
void COrphanRemoveDlg::OnOK() {
if (HasFilesCheckedOut()) {
OutrageMessageBox("You can't have any files checked out file doing this operation");
return;
}
if (MessageBox("Are you sure you want to remove the orphans permanently?", NULL, MB_YESNO) != IDYES)
return;
SetStatus("Deleting Files");
char directory[_MAX_PATH];
CString dir;
CComboBox *combo = (CComboBox *)GetDlgItem(IDC_DIRECTORY);
int sel = combo->GetCurSel();
if (sel == -1)
return;
combo->GetLBText(sel, dir);
ddio_MakePath(directory, LocalD3Dir, "data", dir.GetBuffer(0), NULL);
char fullpath[_MAX_PATH];
int size = m_List.GetCount();
for (int i = 0; i < size; i++) {
if (m_List.GetCheck(i)) {
// it's checked...delete!
m_List.GetText(i, dir);
ddio_MakePath(fullpath, directory, dir.GetBuffer(0), NULL);
ddio_DeleteFile(fullpath);
}
}
SetStatus("Ready...");
OnSelchangeDirectory();
}
const char *orphan_ignore[] = {
".", "..", "dallasfuncs.cpp", "osiris_common.h", "osiris_import.h", "osiris_vector.h",
"anarchy.str", "coop.str", "ctf.str", "entropy.str", "dmfc.str", "d3.str",
"hoard.str", "dp_modem.str", "dp_serial.str", "hyper.str", "ipxclient.str", "lanclient.str",
"monster.str", "mtclient.str", "tanarchy.str"};
int num_orphan_ignore = sizeof(orphan_ignore) / sizeof(char *);
bool IsFileUsed(const char *filename) {
bool found = false;
for (int i = 0; i < num_orphan_ignore; i++) {
if (!stricmp(filename, orphan_ignore[i])) {
found = true;
goto done;
}
}
if (!found)
found = IsFileInGameFile(filename);
if (!found)
found = IsFileInWeaponPage(filename);
if (!found)
found = IsFileInSoundPage(filename);
if (!found)
found = IsFileInShipPage(filename);
if (!found)
found = IsFileInDoorPage(filename);
if (!found)
found = IsFileInTexturePage(filename);
if (!found)
found = IsFileInGenericPage(filename);
done:
Descent->defer();
return found;
}
int filelen(const std::filesystem::path &filename, const std::filesystem::path &dir) {
CFILE *cf = cfopen(dir / filename, "rb");
if (!cf)
return 0;
int len = cfilelength(cf);
cfclose(cf);
return len;
}
void COrphanRemoveDlg::OnSelchangeDirectory() {
CString dir;
CComboBox *combo = (CComboBox *)GetDlgItem(IDC_DIRECTORY);
int sel = combo->GetCurSel();
if (sel == -1)
return;
SetStatus("Updating File List");
Enable(false);
combo->GetLBText(sel, dir);
m_List.ResetContent();
int num_files = 0;
int total_filesize = 0;
CWnd *stats = (CWnd *)GetDlgItem(IDC_STATS);
char data[256];
sprintf(data, "Num Files: %d\r\nSize: %dK", 0, 0);
stats->SetWindowText(data);
std::filesystem::path fullpath = std::filesystem::path(LocalD3Dir) / "data" / dir.GetBuffer(0);
ddio_DoForeachFile(fullpath, std::regex(".+"),
[this, &num_files, &total_filesize, &data, &stats](const std::filesystem::path &path) {
if (!IsFileUsed(path.filename().u8string().c_str())) {
m_List.AddString(path.filename().u8string().c_str());
num_files++;
total_filesize += filelen(path.filename(), path.parent_path());
sprintf(data, "Num Files: %d\r\nSize: %dK", num_files, total_filesize / 1024);
stats->SetWindowText(data);
}
});
// select all
for (int i = 0; i < num_files; i++) {
m_List.SetCheck(i, 1);
m_List.SetSel(i, TRUE);
}
SetStatus("Ready...");
Enable(true);
}
extern char *DirectoryNames[];
extern int NumDirectoryNames;
BOOL COrphanRemoveDlg::OnInitDialog() {
CDialog::OnInitDialog();
CComboBox *combo = (CComboBox *)GetDlgItem(IDC_DIRECTORY);
for (int i = 0; i < NumDirectoryNames; i++) {
combo->AddString(DirectoryNames[i]);
}
Enable(true);
SetStatus("Ready...");
return TRUE;
}
void COrphanRemoveDlg::OnCancel() { CDialog::OnCancel(); }