/* * 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 . */ #include "stdafx.h" #include "resource.h" #include "TableFileEdit.h" #include "PsTypes.h" // #include "descent.h" #include "TableManage.h" #include "manage.h" // #include "pserror.h" // #include "gametexture.h" // #include "texpage.h" // #include "doorpage.h" // #include "soundpage.h" // #include "megapage.h" // #include "shippage.h" // #include "weaponpage.h" // #include "gamefilepage.h" #include "mono.h" #include "genericpage.h" // #include "object.h" // #include "ddio.h" #include "cfile.h" // #include "AppDatabase.h" #include "mem.h" //////////////////////////////////////////////////////////////// // GenericPageNode Class Members //////////////////////////////////////////////////////////////// GenericPageNode::GenericPageNode() { prev = NULL; next = NULL; page_id = 0; } GenericPageNode::~GenericPageNode() { // Free up the object description memory if (genericpage.objinfo_struct.description != NULL) { mem_free(genericpage.objinfo_struct.description); genericpage.objinfo_struct.description = NULL; } } bool GenericPageNode::operator<(const GenericPageNode &node) { return (stricmp(genericpage.objinfo_struct.name, node.genericpage.objinfo_struct.name) < 0); } //////////////////////////////////////////////////////////////// // GenericPageList Class Members //////////////////////////////////////////////////////////////// GenericPageList::GenericPageList() { m_head = NULL; m_tail = NULL; m_size = 0; m_TableFilename = ""; m_TableLoaded = FALSE; m_TableModified = FALSE; m_SelectedNode = NULL; m_SelectedIndex = 0; } GenericPageList::~GenericPageList() { ClearList(); } void GenericPageList::ClearList(void) { GenericPageNode *temp, *node; node = m_head; while (node != NULL) { temp = node; node = node->next; delete temp; } m_size = 0; m_head = NULL; m_tail = NULL; m_TableFilename = ""; m_TableLoaded = FALSE; m_TableModified = FALSE; m_SelectedNode = NULL; m_SelectedIndex = 0; } // Adds the node to the list in ascending alphabetical order // according to the page names of the nodes bool GenericPageList::AddToList(GenericPageNode *new_node) { GenericPageNode *node; if (new_node == NULL) return FALSE; // Handle empty list case if (m_head == NULL) { m_head = new_node; m_tail = new_node; new_node->next = NULL; new_node->prev = NULL; m_size++; return TRUE; } // Handle (new node < list head) case if ((*new_node) < (*m_head)) { new_node->next = m_head; new_node->prev = NULL; m_head->prev = new_node; m_head = new_node; m_size++; return TRUE; } // Search through list until end of list or until the new node is less // than the next node, then add the new node after the current node node = m_head; while (node->next != NULL && (*(node->next)) < (*new_node)) node = node->next; new_node->next = node->next; new_node->prev = node; if (node->next == NULL) m_tail = new_node; else node->next->prev = new_node; node->next = new_node; m_size++; return TRUE; } bool GenericPageList::LoadTable(char *table_filename) { CFILE *infile; uint8_t pagetype; int done; uint32_t page_id; GenericPageNode *generic_page_node; infile = cfopen(table_filename, "rb"); if (!infile) { // mprintf(0,"Couldn't open table file to reorder!\n"); // Int3(); return FALSE; } CWaitCursor wc; // Wipeout the list first ClearList(); done = 0; page_id = 0; while (!done) { if (cfeof(infile)) { done = 1; continue; } pagetype = cf_ReadByte(infile); // If not a generic page, just read it in and ignore it if (pagetype != PAGETYPE_GENERIC) { mng_ReadDummyPage(infile, pagetype); page_id++; continue; } generic_page_node = new GenericPageNode; if (generic_page_node == NULL) { return FALSE; } mng_ReadNewGenericPage(infile, &(generic_page_node->genericpage)); generic_page_node->page_id = page_id; AddToList(generic_page_node); page_id++; } cfclose(infile); // Set Loaded tabel data m_TableFilename = table_filename; m_TableLoaded = TRUE; m_TableModified = FALSE; return TRUE; } bool GenericPageList::SaveTable(char *table_filename) { CFILE *infile, *outfile; uint8_t pagetype, replaced = 0; int done = 0; uint32_t page_id; GenericPageNode *new_generic_page; mngs_generic_page genericpage; CWaitCursor wc; // If no table is loaded, get outta here if (!m_TableLoaded) return FALSE; // First make sure we can open the table file and the temp table file infile = cfopen(m_TableFilename.GetBuffer(0), "rb"); if (!infile) { mprintf(0, "Couldn't open table file to replace generic!\n"); return FALSE; } outfile = cfopen(TEMP_TABLE_FILENAME, "wb"); if (!outfile) { mprintf(0, "Couldn't open temp table file to replace generic!\n"); cfclose(infile); return FALSE; } // Clear out the generic page memset(&genericpage, 0, sizeof(mngs_generic_page)); // Read through the entire pagefile and replace the page we want replaced // If we can't find the one we want, we simply append it to the end of the file page_id = 0; while (!done) { if (cfeof(infile)) { done = 1; continue; } pagetype = cf_ReadByte(infile); // If not a generic page, just read it in and write it right back out if (pagetype != PAGETYPE_GENERIC) { mng_ReadWriteDummyPage(infile, outfile, pagetype); page_id++; continue; } mng_ReadNewGenericPage(infile, &genericpage); // Look for the generic page with the current page position in list new_generic_page = FindNode(page_id); if (new_generic_page == NULL) { // There is a page incompatibility!!!! // so, just write out the one that was read instead mng_WriteNewGenericPage(outfile, &genericpage); OutrageMessageBox("File incompatibility Error!", "Error!"); } else { // Found the page for this position in the list, // So write out the new generic page mng_WriteNewGenericPage(outfile, &(new_generic_page->genericpage)); } // Free up the description memory for the temp page if (genericpage.objinfo_struct.description != NULL) { mem_free(genericpage.objinfo_struct.description); genericpage.objinfo_struct.description = NULL; } page_id++; } cfclose(infile); cfclose(outfile); if (table_filename == NULL) // if no filename specified, just save it to the currently loaded file table_filename = m_TableFilename.GetBuffer(0); else { // We need to create this one just so it can get deleted alright by // Jason's Switcheroo function outfile = cfopen(table_filename, "wb"); if (!outfile) return FALSE; cfclose(outfile); } // Now, perform the switcheroo by deleting the real table file and renaming the // temp table file to be the new "real" table file. if (!SwitcherooFiles(table_filename, TEMP_TABLE_FILENAME)) return FALSE; m_TableModified = FALSE; m_TableFilename = table_filename; return TRUE; // successful! } bool GenericPageList::FillFromList(CComboBox *list) { GenericPageNode *node; list->ResetContent(); node = m_head; while (node != NULL) { list->InsertString(-1, node->genericpage.objinfo_struct.name); node = node->next; } // Select the start of the list SelectNode(0); return TRUE; } void GenericPageList::SelectNext(void) { if (m_SelectedNode == NULL) return; if (m_SelectedNode->next == NULL) { m_SelectedNode = m_head; m_SelectedIndex = 0; } else { m_SelectedNode = m_SelectedNode->next; m_SelectedIndex++; } } void GenericPageList::SelectPrev(void) { if (m_SelectedNode == NULL) return; if (m_SelectedNode->prev == NULL) { m_SelectedNode = m_tail; m_SelectedIndex = (m_size - 1); } else { m_SelectedNode = m_SelectedNode->prev; m_SelectedIndex--; } } void GenericPageList::SelectNode(uint32_t list_index) { uint32_t j; GenericPageNode *node; if (list_index < 0 || list_index > (m_size - 1)) return; node = m_head; for (j = 0; j < list_index; j++) if (node != NULL) node = node->next; m_SelectedNode = node; m_SelectedIndex = list_index; } void GenericPageList::DisplaySelected(CComboBox *list, CEdit *description) { char *text; if (m_SelectedNode == NULL) return; list->SetCurSel(m_SelectedIndex); text = m_SelectedNode->genericpage.objinfo_struct.description; if (text == NULL) description->SetWindowText(NO_DESCRIPTION_STRING); else description->SetWindowText(text); } void GenericPageList::SaveSelected(CEdit *description) { CString new_descrip; char *new_text; char *old_text; if (m_SelectedNode == NULL) return; // Get pointer to old text old_text = m_SelectedNode->genericpage.objinfo_struct.description; // Get Copy of new Description text description->GetWindowText(new_descrip); new_text = (char *)mem_malloc(strlen(new_descrip.GetBuffer(0)) + 1); ASSERT(new_text); // out of memory! sprintf(new_text, "%s", new_descrip.GetBuffer(0)); // Check if new description is empty, if it is, make it NULL if (strlen(new_text) == 0 || stricmp(new_text, NO_DESCRIPTION_STRING) == 0) { mem_free(new_text); new_text = NULL; } // If both new and old are empty, get outta here if (old_text == NULL && new_text == NULL) { mem_free(new_text); return; } // If both have descriptions and they match, get outta here if (old_text != NULL && new_text != NULL) { if (strcmp(old_text, new_text) == 0) { mem_free(new_text); return; } } // Free up the old text memory, and assign it to the new text if (old_text != NULL) mem_free(old_text); m_SelectedNode->genericpage.objinfo_struct.description = new_text; m_TableModified = TRUE; return; } GenericPageNode *GenericPageList::FindNode(uint32_t page_id) { GenericPageNode *node, *found_node; found_node = NULL; node = m_head; while (node != NULL) { if (node->page_id == page_id) { found_node = node; break; } node = node->next; } return (found_node); } int GenericPageList::ModifiedPrompt(CDialog *wnd) { // If current file has been modified, check with user first... if (!m_TableModified) return (IDYES); if (wnd->MessageBox("Changes to table file will be lost. Proceed?", "Table File Has Been Modified", MB_YESNO) == IDYES) return (IDYES); return (IDNO); } void GenericPageList::SetTitleString(CDialog *wnd) { char title[1024]; char loaded_file[1024]; if (m_TableLoaded) sprintf(loaded_file, " - [%s%s]", m_TableFilename.GetBuffer(0), (m_TableModified) ? "*" : ""); else sprintf(loaded_file, ""); sprintf(title, "%s%s", TITLE_NAME, loaded_file); wnd->SetWindowText(title); }