This repository has been archived on 2025-02-27. You can view files and clone it, but cannot push or open issues or pull requests.
CnC_Renegade/Code/Commando/inputconfigmgr.cpp

710 lines
No EOL
16 KiB
C++

/*
** Command & Conquer Renegade(tm)
** Copyright 2025 Electronic Arts Inc.
**
** 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/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : Combat *
* *
* $Archive:: /Commando/Code/commando/inputconfigmgr.cpp $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 1/09/02 11:40a $*
* *
* $Revision:: 6 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "inputconfigmgr.h"
#include "dlgcontrols.h"
#include "input.h"
#include "rawfile.h"
#include "ffactory.h"
#include "registry.h"
#include "chunkio.h"
#include "debug.h"
#include "translatedb.h"
#include "string_ids.h"
#include "slavemaster.h"
////////////////////////////////////////////////////////////////
// Local constants
////////////////////////////////////////////////////////////////
static const char *CFG_DICTIONARY_FILENAME = "CONFIG.DAT";
////////////////////////////////////////////////////////////////
// Registry key names
////////////////////////////////////////////////////////////////
//static const char *REGISTRY_SUB_KEY = "Software\\Westwood\\Renegade\\Input";
static const char *REG_CURRENT_CONFIG = "Current Config";
////////////////////////////////////////////////////////////////
// Static member initialization
////////////////////////////////////////////////////////////////
DynamicVectorClass<InputConfigClass> InputConfigMgrClass::ConfigList;
int InputConfigMgrClass::CurrentConfigIndex = -1;
////////////////////////////////////////////////////////////////
// Save/load constants
////////////////////////////////////////////////////////////////
enum
{
CHUNKID_CONFIG_LIST = 0x07181105,
CHUNKID_VARIABLES,
CHUNKID_CONFIG_OBJ,
};
enum
{
VARID_CURRENT_CONFIG = 1,
};
////////////////////////////////////////////////////////////////
//
// Initialize
//
////////////////////////////////////////////////////////////////
void
InputConfigMgrClass::Initialize (void)
{
//
// Build the configuration list and load the current configuration
//
Load ();
Load_Current_Configuration ();
return ;
}
////////////////////////////////////////////////////////////////
//
// Shutdown
//
////////////////////////////////////////////////////////////////
void
InputConfigMgrClass::Shutdown (void)
{
//
// Save our current configuration list
//
if (!SlaveMaster.Am_I_Slave()) {
Save ();
}
//
// Reset our data
//
ConfigList.Delete_All ();
CurrentConfigIndex = -1;
return ;
}
////////////////////////////////////////////////////////////////
//
// Get_Current_Configuration
//
////////////////////////////////////////////////////////////////
bool
InputConfigMgrClass::Get_Current_Configuration (InputConfigClass &config)
{
if (CurrentConfigIndex < 0 || CurrentConfigIndex >= ConfigList.Count ()) {
return false;
}
//
// Simply index into the config list and return the object to the caller
//
config = ConfigList[CurrentConfigIndex];
return true;
}
////////////////////////////////////////////////////////////////
//
// Load_Current_Configuration
//
////////////////////////////////////////////////////////////////
void
InputConfigMgrClass::Load_Current_Configuration (void)
{
if (CurrentConfigIndex < 0 || CurrentConfigIndex >= ConfigList.Count ()) {
//
// The current configuration is invalid, so load the
// default configuration
//
Load_Default_Configuration ();
} else {
//
// Load this configuration
//
Load_Configuration (ConfigList[CurrentConfigIndex]);
}
return ;
}
////////////////////////////////////////////////////////////////
//
// Save_Current_Configuration
//
////////////////////////////////////////////////////////////////
void
InputConfigMgrClass::Save_Current_Configuration (void)
{
if (CurrentConfigIndex < 0 || CurrentConfigIndex >= ConfigList.Count ()) {
return ;
}
//
// Save this configuration
//
Save_Configuration (ConfigList[CurrentConfigIndex]);
return ;
}
////////////////////////////////////////////////////////////////
//
// Add_Configuration
//
////////////////////////////////////////////////////////////////
int
InputConfigMgrClass::Add_Configuration (const WCHAR *display_name)
{
//
// Get a filename for the configuration
//
StringClass filename;
Get_Unique_Config_Filename (filename);
//
// Build a new input config object
//
InputConfigClass config;
config.Set_Display_Name (display_name);
config.Set_Filename (filename);
config.Set_Is_Custom (true);
//
// Add the object to our list
//
CurrentConfigIndex = ConfigList.Add (config);
//
// Now save the current configuration to this file
//
Save_Configuration (config);
return CurrentConfigIndex;
}
////////////////////////////////////////////////////////////////
//
// Delete_Configuration
//
////////////////////////////////////////////////////////////////
void
InputConfigMgrClass::Delete_Configuration (int index)
{
if (index < 0 || index >= ConfigList.Count ()) {
return ;
}
//
// Reset the current configuration (if necessary)
//
bool load_default = false;
if (index == CurrentConfigIndex) {
CurrentConfigIndex = -1;
load_default = true;
}
//
// Get the local path of the configuration files
//
StringClass config_path;
Get_Config_Path (config_path);
StringClass full_path;
full_path.Format ("%s\\%s", config_path, ConfigList[index].Get_Filename ());
//
// Delete the configuration file
//
::DeleteFile (full_path);
//
// Now remove this entry from the list
//
ConfigList.Delete (index);
//
// Load the default configuration is we just deleted the current configuration
//
if (load_default) {
Load_Default_Configuration ();
}
return ;
}
////////////////////////////////////////////////////////////////
//
// Delete_Configuration
//
////////////////////////////////////////////////////////////////
void
InputConfigMgrClass::Delete_Configuration (const char *filename)
{
//
// Try to find the configuration in our list
//
int index = Find_Configuration (filename);
if (index != -1) {
//
// We've found the conversation, so delete it
//
Delete_Configuration (index);
}
return ;
}
////////////////////////////////////////////////////////////////
//
// Find_Configuration
//
////////////////////////////////////////////////////////////////
int
InputConfigMgrClass::Find_Configuration (const char *filename)
{
int retval = -1;
for (int index = 0; index < ConfigList.Count (); index ++) {
//
// Is this the entry we're looking for?
//
if (::lstrcmpi (ConfigList[index].Get_Filename (), filename) == 0) {
retval = index;
break;
}
}
return retval;
}
////////////////////////////////////////////////////////////////
//
// Load_Default_Configuration
//
////////////////////////////////////////////////////////////////
void
InputConfigMgrClass::Load_Default_Configuration (void)
{
for (int index = 0; index < ConfigList.Count (); index ++) {
//
// Is this the default configuration?
//
if (ConfigList[index].Is_Default ()) {
Load_Configuration (ConfigList[index]);
break;
}
}
return ;
}
////////////////////////////////////////////////////////////////
//
// Load_Configuration
//
////////////////////////////////////////////////////////////////
void
InputConfigMgrClass::Load_Configuration (const InputConfigClass &config)
{
//
// Anytime we loada configuration, it becomes our current config
//
CurrentConfigIndex = Find_Configuration (config.Get_Filename ());
//
// Load the configuration into memory
//
Input::Load_Configuration (config.Get_Filename ());
//
// Reload the UI (if necessary)
//
if (ControlsMenuClass::Get_Instance () != NULL) {
ControlsMenuClass::Get_Instance ()->Reload ();
}
return ;
}
////////////////////////////////////////////////////////////////
//
// Save_Configuration
//
////////////////////////////////////////////////////////////////
void
InputConfigMgrClass::Save_Configuration (const InputConfigClass &config)
{
//
// We can only save custom configurations
//
if (config.Is_Custom ()) {
//
// Anytime we save a configuration, it becomes our current config...
//
CurrentConfigIndex = Find_Configuration (config.Get_Filename ());
Input::Save_Configuration (config.Get_Filename ());
//
// Update the copy of this config in our internal list
//
if (CurrentConfigIndex != -1) {
ConfigList[CurrentConfigIndex] = config;
}
} else {
//
// Make a name for a new configuration
//
WideStringClass new_name = TRANSLATE (IDS_MENU_CUSTOM);
new_name += config.Get_Display_Name ();
//
// Add a new configuration to list (this saves the new
// configuration as well)
//
Add_Configuration (new_name);
}
return ;
}
////////////////////////////////////////////////////////////////
//
// Get_Unique_Config_Filename
//
////////////////////////////////////////////////////////////////
void
InputConfigMgrClass::Get_Unique_Config_Filename (StringClass &filename)
{
//
// Get the local path of the configuration files
//
StringClass config_path;
Get_Config_Path (config_path);
int slot = 1;
StringClass full_path;
do
{
//
// Build this filename
//
filename.Format ("input%.2d.cfg", slot ++);
//
// Check to see if this file exists
//
full_path.Format ("%s\\%s", (const char *)config_path, filename);
} while (::GetFileAttributes (full_path) != 0xFFFFFFFF);
return ;
}
////////////////////////////////////////////////////////////////
//
// Save
//
////////////////////////////////////////////////////////////////
void
InputConfigMgrClass::Save (void)
{
FileClass *file = _TheFileFactory->Get_File (CFG_DICTIONARY_FILENAME);
WWASSERT (file != NULL);
if (file == NULL) {
return ;
}
//
// Open the file for writing
//
file->Open (FileClass::WRITE);
ChunkSaveClass csave(file);
//
// Save the config list to its own chunk
//
csave.Begin_Chunk (CHUNKID_CONFIG_LIST);
Save_Config_List (csave);
csave.End_Chunk ();
//
// Save the
//
csave.Begin_Chunk (CHUNKID_VARIABLES);
Save_Variables (csave);
csave.End_Chunk ();
//
// Close the file
//
file->Close ();
_TheFileFactory->Return_File (file);
return ;
}
////////////////////////////////////////////////////////////////
//
// Load
//
////////////////////////////////////////////////////////////////
void
InputConfigMgrClass::Load (void)
{
FileClass *file = _TheFileFactory->Get_File (CFG_DICTIONARY_FILENAME);
WWASSERT (file != NULL);
if (file == NULL) {
return ;
}
//
// Open the file for reading
//
file->Open (FileClass::READ);
ChunkLoadClass cload(file);
//
// Read all the chunks stored in this file
//
while (cload.Open_Chunk ()) {
switch(cload.Cur_Chunk_ID ()) {
case CHUNKID_CONFIG_LIST:
Load_Config_List (cload);
break;
case CHUNKID_VARIABLES:
Load_Variables (cload);
break;
default:
Debug_Say (("Unrecognized InputConfigMgrClass Chunk ID\n"));
break;
}
cload.Close_Chunk ();
}
//
// If the configuration list is empty, then add the default
// configuration file to the list
//
if (ConfigList.Count () == 0) {
InputConfigClass config;
config.Set_Display_Name (TRANSLATE (IDS_MENU_DEFAULT_SETTINGS));
config.Set_Filename (DEFAULT_INPUT_FILENAME);
config.Set_Is_Custom (false);
config.Set_Is_Default (true);
ConfigList.Add (config);
CurrentConfigIndex = 0;
}
//
// Close the file
//
file->Close ();
_TheFileFactory->Return_File (file);
return ;
}
////////////////////////////////////////////////////////////////
//
// Save_Config_List
//
////////////////////////////////////////////////////////////////
void
InputConfigMgrClass::Save_Config_List (ChunkSaveClass &csave)
{
for (int index = 0; index < ConfigList.Count (); index ++) {
//
// Save this configuration object to its own chunk
//
csave.Begin_Chunk (CHUNKID_CONFIG_OBJ);
ConfigList[index].Save (csave);
csave.End_Chunk ();
}
return ;
}
////////////////////////////////////////////////////////////////
//
// Load_Config_List
//
////////////////////////////////////////////////////////////////
void
InputConfigMgrClass::Load_Config_List (ChunkLoadClass &cload)
{
//
// Read all the sub-chunks
//
while (cload.Open_Chunk ()) {
switch (cload.Cur_Chunk_ID ()) {
case CHUNKID_CONFIG_OBJ:
{
//
// Load this configuration object
//
InputConfigClass config;
config.Load (cload);
//
// Add the object to our list
//
ConfigList.Add (config);
break;
}
default:
Debug_Say (("Unrecognized InputConfigMgrClass::Load_Config_List Chunk ID\n"));
break;
}
cload.Close_Chunk ();
}
return ;
}
////////////////////////////////////////////////////////////////
//
// Save_Variables
//
////////////////////////////////////////////////////////////////
void
InputConfigMgrClass::Save_Variables (ChunkSaveClass &csave)
{
//
// Determine what the filename of the current configuration is
//
StringClass filename;
if (CurrentConfigIndex != -1) {
filename = ConfigList[CurrentConfigIndex].Get_Filename ();
} else {
filename = DEFAULT_INPUT_FILENAME;
}
WRITE_MICRO_CHUNK_WWSTRING (csave, VARID_CURRENT_CONFIG, filename);
return ;
}
////////////////////////////////////////////////////////////////
//
// Load_Variables
//
////////////////////////////////////////////////////////////////
void
InputConfigMgrClass::Load_Variables (ChunkLoadClass &cload)
{
StringClass filename;
//
// Read all the microchunks
//
while (cload.Open_Micro_Chunk ()) {
switch(cload.Cur_Micro_Chunk_ID ()) {
READ_MICRO_CHUNK_WWSTRING (cload, VARID_CURRENT_CONFIG, filename);
}
cload.Close_Micro_Chunk ();
}
//
// Store the index of this configuration
//
CurrentConfigIndex = Find_Configuration (filename);
return ;
}
////////////////////////////////////////////////////////////////
//
// Get_Config_Path
//
////////////////////////////////////////////////////////////////
void
InputConfigMgrClass::Get_Config_Path (StringClass &full_path)
{
//
// Lookup the path of the executable
//
char path[MAX_PATH] = { 0 };
::GetModuleFileName (NULL, path, sizeof (path));
//
// Strip off the filename
//
char *filename_portion = ::strrchr (path, '\\');
if (filename_portion != NULL) {
filename_portion[0] = 0;
}
//
// Build the full path from the EXE's directory
//
full_path.Format ("%s\\data\\config", path);
return ;
}