mirror of
https://github.com/kevinbentley/Descent3.git
synced 2025-01-22 11:28:56 +00:00
468 lines
12 KiB
C++
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(); }
|