// ----------------------------------------------------------------------------- // Opens [dir] as a DirArchive and adds it to the list. // Returns a pointer to the archive or nullptr if an error occurred. // ----------------------------------------------------------------------------- Archive* ArchiveManager::openDirArchive(const string& dir, bool manage, bool silent) { auto new_archive = getArchive(dir); LOG_MESSAGE(1, "Opening directory %s as archive", dir); // If the archive is already open, just return it if (new_archive) { // Announce open if (!silent) { MemChunk mc; uint32_t index = archiveIndex(new_archive); mc.write(&index, 4); announce("archive_opened", mc); } return new_archive; } new_archive = new DirArchive(); // If it opened successfully, add it to the list if needed & return it, // Otherwise, delete it and return nullptr if (new_archive->open(dir)) { if (manage) { // Add the archive addArchive(new_archive); // Announce open if (!silent) { MemChunk mc; uint32_t index = archiveIndex(new_archive); mc.write(&index, 4); announce("archive_opened", mc); } // Add to recent files addRecentFile(dir); } // Return the opened archive return new_archive; } else { LOG_MESSAGE(1, "Error: " + Global::error); delete new_archive; return nullptr; } }
// ----------------------------------------------------------------------------- // Called when an announcement is recieved from one of the archives in the list // ----------------------------------------------------------------------------- void ArchiveManager::onAnnouncement(Announcer* announcer, const string& event_name, MemChunk& event_data) { // Reset event data for reading event_data.seek(0, SEEK_SET); // Check that the announcement came from an archive in the list int32_t index = archiveIndex((Archive*)announcer); if (index >= 0) { // If the archive was saved if (event_name == "saved") { MemChunk mc; mc.write(&index, 4); announce("archive_saved", mc); } // If the archive was modified if (event_name == "modified" || event_name == "entry_modified") { MemChunk mc; mc.write(&index, 4); announce("archive_modified", mc); } } }
// ----------------------------------------------------------------------------- // Returns true if [archive] is set to be used as a resource, false otherwise // ----------------------------------------------------------------------------- bool ArchiveManager::archiveIsResource(Archive* archive) { int index = archiveIndex(archive); if (index < 0) return false; else return open_archives_[index].resource; }
// ----------------------------------------------------------------------------- // Returns all open archives that live inside this one, recursively. // ----------------------------------------------------------------------------- // This is the recursive bit, separate from the public entry point void ArchiveManager::getDependentArchivesInternal(Archive* archive, vector<Archive*>& vec) { int ai = archiveIndex(archive); for (auto& child : open_archives_[ai].open_children) { vec.push_back(child); getDependentArchivesInternal(child, vec); } }
// This is the recursive bit, separate from the public entry point void ArchiveManager::getDependentArchivesInternal(Archive* archive, vector<Archive*>& vec) { Archive* child; int ai = archiveIndex(archive); for (size_t a = 0; a < open_archives[ai].open_children.size(); a++) { child = open_archives[ai].open_children[a]; vec.push_back(child); getDependentArchivesInternal(child, vec); } }
// ----------------------------------------------------------------------------- // Sets/unsets [archive] to be used as a resource // ----------------------------------------------------------------------------- void ArchiveManager::setArchiveResource(Archive* archive, bool resource) { int index = archiveIndex(archive); if (index >= 0) { bool was_resource = open_archives_[index].resource; open_archives_[index].resource = resource; // Update resource manager if (resource && !was_resource) theResourceManager->addArchive(archive); else if (!resource && was_resource) theResourceManager->removeArchive(archive); } }
// ----------------------------------------------------------------------------- // Closes the archive at index, and removes it from the list if the index is // valid. Returns false on invalid index, true otherwise // ----------------------------------------------------------------------------- bool ArchiveManager::closeArchive(int index) { // Check for invalid index if (index < 0 || index >= (int)open_archives_.size()) return false; // Announce archive closing MemChunk mc; int32_t temp = index; mc.write(&temp, 4); announce("archive_closing", mc); // Delete any bookmarked entries contained in the archive deleteBookmarksInArchive(open_archives_[index].archive); // Remove from resource manager theResourceManager->removeArchive(open_archives_[index].archive); // Close any open child archives // Clear out the open_children vector first, lest the children try to remove themselves from it auto open_children = open_archives_[index].open_children; open_archives_[index].open_children.clear(); for (auto& archive : open_children) { int ci = archiveIndex(archive); if (ci >= 0) closeArchive(ci); } // Remove ourselves from our parent's open-child list auto parent = open_archives_[index].archive->parentEntry(); if (parent) { auto gp = parent->parent(); if (gp) { int pi = archiveIndex(gp); if (pi >= 0) { auto& children = open_archives_[pi].open_children; for (auto it = children.begin(); it < children.end(); ++it) { if (*it == open_archives_[index].archive) { children.erase(it, it + 1); break; } } } } } // Close the archive open_archives_[index].archive->close(); // Delete the archive object delete open_archives_[index].archive; // Remove the archive at index from the list open_archives_.erase(open_archives_.begin() + index); // Announce closed announce("archive_closed", mc); return true; }
// ----------------------------------------------------------------------------- // Same as the above function, except it opens from an ArchiveEntry // ----------------------------------------------------------------------------- Archive* ArchiveManager::openArchive(ArchiveEntry* entry, bool manage, bool silent) { // Check entry was given if (!entry) return nullptr; // Check if the entry is already opened for (auto& open_archive : open_archives_) { if (open_archive.archive->parentEntry() == entry) { // Announce open if (!silent) { MemChunk mc; uint32_t index = archiveIndex(open_archive.archive); mc.write(&index, 4); announce("archive_opened", mc); } return open_archive.archive; } } // Check entry type Archive* new_archive; if (WadArchive::isWadArchive(entry->data())) new_archive = new WadArchive(); else if (ZipArchive::isZipArchive(entry->data())) new_archive = new ZipArchive(); else if (ResArchive::isResArchive(entry->data())) new_archive = new ResArchive(); else if (LibArchive::isLibArchive(entry->data())) new_archive = new LibArchive(); else if (DatArchive::isDatArchive(entry->data())) new_archive = new DatArchive(); else if (PakArchive::isPakArchive(entry->data())) new_archive = new PakArchive(); else if (BSPArchive::isBSPArchive(entry->data())) new_archive = new BSPArchive(); else if (GrpArchive::isGrpArchive(entry->data())) new_archive = new GrpArchive(); else if (RffArchive::isRffArchive(entry->data())) new_archive = new RffArchive(); else if (GobArchive::isGobArchive(entry->data())) new_archive = new GobArchive(); else if (LfdArchive::isLfdArchive(entry->data())) new_archive = new LfdArchive(); else if (HogArchive::isHogArchive(entry->data())) new_archive = new HogArchive(); else if (ADatArchive::isADatArchive(entry->data())) new_archive = new ADatArchive(); else if (Wad2Archive::isWad2Archive(entry->data())) new_archive = new Wad2Archive(); else if (WadJArchive::isWadJArchive(entry->data())) new_archive = new WadJArchive(); else if (WolfArchive::isWolfArchive(entry->data())) new_archive = new WolfArchive(); else if (GZipArchive::isGZipArchive(entry->data())) new_archive = new GZipArchive(); else if (BZip2Archive::isBZip2Archive(entry->data())) new_archive = new BZip2Archive(); else if (TarArchive::isTarArchive(entry->data())) new_archive = new TarArchive(); else if (DiskArchive::isDiskArchive(entry->data())) new_archive = new DiskArchive(); else if (entry->name().Lower().EndsWith(".pod") && PodArchive::isPodArchive(entry->data())) new_archive = new PodArchive(); else if (ChasmBinArchive::isChasmBinArchive(entry->data())) new_archive = new ChasmBinArchive(); else if (SiNArchive::isSiNArchive(entry->data())) new_archive = new SiNArchive(); else { // Unsupported format Global::error = "Unsupported or invalid Archive format"; return nullptr; } // If it opened successfully, add it to the list & return it, // Otherwise, delete it and return nullptr if (new_archive->open(entry)) { if (manage) { // Add to parent's child list if parent is open in the manager (it should be) int index_parent = -1; if (entry->parent()) index_parent = archiveIndex(entry->parent()); if (index_parent >= 0) open_archives_[index_parent].open_children.push_back(new_archive); // Add the new archive addArchive(new_archive); // Announce open if (!silent) { MemChunk mc; uint32_t index = archiveIndex(new_archive); mc.write(&index, 4); announce("archive_opened", mc); } } return new_archive; } else { LOG_MESSAGE(1, "Error: " + Global::error); delete new_archive; return nullptr; } }
// ----------------------------------------------------------------------------- // Opens and adds a archive to the list, returns a pointer to the newly opened // and added archive, or nullptr if an error occurred // ----------------------------------------------------------------------------- Archive* ArchiveManager::openArchive(const string& filename, bool manage, bool silent) { // Check for directory if (!wxFile::Exists(filename) && wxDirExists(filename)) return openDirArchive(filename, manage, silent); auto new_archive = getArchive(filename); LOG_MESSAGE(1, "Opening archive %s", filename); // If the archive is already open, just return it if (new_archive) { // Announce open if (!silent) { MemChunk mc; uint32_t index = archiveIndex(new_archive); mc.write(&index, 4); announce("archive_opened", mc); } return new_archive; } // Determine file format if (WadArchive::isWadArchive(filename)) new_archive = new WadArchive(); else if (ZipArchive::isZipArchive(filename)) new_archive = new ZipArchive(); else if (ResArchive::isResArchive(filename)) new_archive = new ResArchive(); else if (DatArchive::isDatArchive(filename)) new_archive = new DatArchive(); else if (LibArchive::isLibArchive(filename)) new_archive = new LibArchive(); else if (PakArchive::isPakArchive(filename)) new_archive = new PakArchive(); else if (BSPArchive::isBSPArchive(filename)) new_archive = new BSPArchive(); else if (GrpArchive::isGrpArchive(filename)) new_archive = new GrpArchive(); else if (RffArchive::isRffArchive(filename)) new_archive = new RffArchive(); else if (GobArchive::isGobArchive(filename)) new_archive = new GobArchive(); else if (LfdArchive::isLfdArchive(filename)) new_archive = new LfdArchive(); else if (HogArchive::isHogArchive(filename)) new_archive = new HogArchive(); else if (ADatArchive::isADatArchive(filename)) new_archive = new ADatArchive(); else if (Wad2Archive::isWad2Archive(filename)) new_archive = new Wad2Archive(); else if (WadJArchive::isWadJArchive(filename)) new_archive = new WadJArchive(); else if (WolfArchive::isWolfArchive(filename)) new_archive = new WolfArchive(); else if (GZipArchive::isGZipArchive(filename)) new_archive = new GZipArchive(); else if (BZip2Archive::isBZip2Archive(filename)) new_archive = new BZip2Archive(); else if (TarArchive::isTarArchive(filename)) new_archive = new TarArchive(); else if (DiskArchive::isDiskArchive(filename)) new_archive = new DiskArchive(); else if (PodArchive::isPodArchive(filename)) new_archive = new PodArchive(); else if (ChasmBinArchive::isChasmBinArchive(filename)) new_archive = new ChasmBinArchive(); else if (SiNArchive::isSiNArchive(filename)) new_archive = new SiNArchive(); else { // Unsupported format Global::error = "Unsupported or invalid Archive format"; return nullptr; } // If it opened successfully, add it to the list if needed & return it, // Otherwise, delete it and return nullptr if (new_archive->open(filename)) { if (manage) { // Add the archive addArchive(new_archive); // Announce open if (!silent) { MemChunk mc; uint32_t index = archiveIndex(new_archive); mc.write(&index, 4); announce("archive_opened", mc); } // Add to recent files addRecentFile(filename); } // Return the opened archive return new_archive; } else { LOG_MESSAGE(1, "Error: " + Global::error); delete new_archive; return nullptr; } }
/* ArchiveManager::closeArchive * Closes the archive at index, and removes it from the list if the * index is valid. Returns false on invalid index, true otherwise *******************************************************************/ bool ArchiveManager::closeArchive(int index) { // Check for invalid index if (index < 0 || index >= (int) open_archives.size()) return false; // Announce archive closing MemChunk mc; int32_t temp = index; mc.write(&temp, 4); announce("archive_closing", mc); // Delete any bookmarked entries contained in the archive deleteBookmarksInArchive(open_archives[index].archive); // Remove from resource manager theResourceManager->removeArchive(open_archives[index].archive); // Delete any embedded configuration //theGameConfiguration->removeEmbeddedConfig(open_archives[index].archive->getFilename()); // Close any open child archives // Clear out the open_children vector first, lest the children try to // remove themselves from it vector<Archive*> open_children = open_archives[index].open_children; open_archives[index].open_children.clear(); for (size_t a = 0; a < open_children.size(); a++) { int ci = archiveIndex(open_children[a]); if (ci >= 0) closeArchive(ci); } // Remove ourselves from our parent's open-child list ArchiveEntry* parent = open_archives[index].archive->getParent(); if (parent) { Archive* gp = parent->getParent(); if (gp) { int pi = archiveIndex(gp); if (pi >= 0) { vector<Archive*>& children = open_archives[pi].open_children; for (vector<Archive*>::iterator it = children.begin(); it < children.end(); it++) { if (*it == open_archives[index].archive) { children.erase(it, it + 1); break; } } } } } // Close the archive open_archives[index].archive->close(); // Delete the archive object delete open_archives[index].archive; // Remove the archive at index from the list open_archives.erase(open_archives.begin() + index); // Announce closed announce("archive_closed", mc); return true; }
/* ArchiveManager::openArchive * Same as the above function, except it opens from an ArchiveEntry *******************************************************************/ Archive* ArchiveManager::openArchive(ArchiveEntry* entry, bool manage, bool silent) { Archive* new_archive = NULL; // Check entry was given if (!entry) return NULL; // Check if the entry is already opened for (size_t a = 0; a < open_archives.size(); a++) { if (open_archives[a].archive->getParent() == entry) { // Announce open if (!silent) { MemChunk mc; uint32_t index = archiveIndex(open_archives[a].archive); mc.write(&index, 4); announce("archive_opened", mc); } return open_archives[a].archive; } } // Check entry type if (WadArchive::isWadArchive(entry->getMCData())) new_archive = new WadArchive(); else if (ZipArchive::isZipArchive(entry->getMCData())) new_archive = new ZipArchive(); else if (ResArchive::isResArchive(entry->getMCData())) new_archive = new ResArchive(); else if (LibArchive::isLibArchive(entry->getMCData())) new_archive = new LibArchive(); else if (DatArchive::isDatArchive(entry->getMCData())) new_archive = new DatArchive(); else if (PakArchive::isPakArchive(entry->getMCData())) new_archive = new PakArchive(); else if (BSPArchive::isBSPArchive(entry->getMCData())) new_archive = new BSPArchive(); else if (GrpArchive::isGrpArchive(entry->getMCData())) new_archive = new GrpArchive(); else if (RffArchive::isRffArchive(entry->getMCData())) new_archive = new RffArchive(); else if (GobArchive::isGobArchive(entry->getMCData())) new_archive = new GobArchive(); else if (LfdArchive::isLfdArchive(entry->getMCData())) new_archive = new LfdArchive(); else if (HogArchive::isHogArchive(entry->getMCData())) new_archive = new HogArchive(); else if (ADatArchive::isADatArchive(entry->getMCData())) new_archive = new ADatArchive(); else if (Wad2Archive::isWad2Archive(entry->getMCData())) new_archive = new Wad2Archive(); else if (WadJArchive::isWadJArchive(entry->getMCData())) new_archive = new WadJArchive(); else if (WolfArchive::isWolfArchive(entry->getMCData())) new_archive = new WolfArchive(); else if (GZipArchive::isGZipArchive(entry->getMCData())) new_archive = new GZipArchive(); else if (BZip2Archive::isBZip2Archive(entry->getMCData())) new_archive = new BZip2Archive(); else if (TarArchive::isTarArchive(entry->getMCData())) new_archive = new TarArchive(); else if (DiskArchive::isDiskArchive(entry->getMCData())) new_archive = new DiskArchive(); else { // Unsupported format Global::error = "Unsupported or invalid Archive format"; return NULL; } // If it opened successfully, add it to the list & return it, // Otherwise, delete it and return NULL if (new_archive->open(entry)) { if (manage) { // Add to parent's child list if parent is open in the manager (it should be) int index_parent = -1; if (entry->getParent()) index_parent = archiveIndex(entry->getParent()); if (index_parent >= 0) open_archives[index_parent].open_children.push_back(new_archive); // Add the new archive addArchive(new_archive); // Announce open if (!silent) { MemChunk mc; uint32_t index = archiveIndex(new_archive); mc.write(&index, 4); announce("archive_opened", mc); } } return new_archive; } else { wxLogMessage("Error: " + Global::error); delete new_archive; return NULL; } }