mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-26 05:51:20 +00:00
- Moved ExpandEnvVars() from d_main.cpp to cmdlib.cpp.
- AutoExec paths now support the same variable expansion as the search paths. Additionally, on Windows, the default autoexec path is now relative to $PROGDIR, rather than using a fixed path to the executable's current directory. - All usable Autoload and AutoExec sections are now created at the top of the config file along with some brief explanatory notes so they are readily visible to anyone who wants to edit them. SVN r1307 (trunk)
This commit is contained in:
parent
fb75c46806
commit
ef3b57fb8f
8 changed files with 466 additions and 101 deletions
|
@ -1,3 +1,13 @@
|
||||||
|
December 6, 2008
|
||||||
|
- Moved ExpandEnvVars() from d_main.cpp to cmdlib.cpp.
|
||||||
|
- AutoExec paths now support the same variable expansion as the search paths.
|
||||||
|
Additionally, on Windows, the default autoexec path is now relative to
|
||||||
|
$PROGDIR, rather than using a fixed path to the executable's current
|
||||||
|
directory.
|
||||||
|
- All usable Autoload and AutoExec sections are now created at the top of
|
||||||
|
the config file along with some brief explanatory notes so they are
|
||||||
|
readily visible to anyone who wants to edit them.
|
||||||
|
|
||||||
December 6, 2008 (Changes by Graf Zahl)
|
December 6, 2008 (Changes by Graf Zahl)
|
||||||
- Fixed: G_DoPlayDemo did not free the demobuffer or the CVAR backups when it
|
- Fixed: G_DoPlayDemo did not free the demobuffer or the CVAR backups when it
|
||||||
failed to start the demo.
|
failed to start the demo.
|
||||||
|
@ -19,7 +29,8 @@ December 1, 2008 (Changes by Graf Zahl)
|
||||||
|
|
||||||
December 1, 2008
|
December 1, 2008
|
||||||
- Restored the multiplayer scoreboard's former centering so that it doesn't
|
- Restored the multiplayer scoreboard's former centering so that it doesn't
|
||||||
look awful on widescreen intermissions.
|
look awful on widescreen intermissions. Also changed the column widths to
|
||||||
|
be font-dependant rather than fixed proportions of the screen width.
|
||||||
- Fixed horizontal positioning of 'finished' on the Raven games when scaled.
|
- Fixed horizontal positioning of 'finished' on the Raven games when scaled.
|
||||||
|
|
||||||
November 30, 2008 (Changes by Graf Zahl)
|
November 30, 2008 (Changes by Graf Zahl)
|
||||||
|
|
|
@ -469,3 +469,68 @@ int strbin (char *str)
|
||||||
*str = 0;
|
*str = 0;
|
||||||
return str - start;
|
return str - start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// ExpandEnvVars
|
||||||
|
//
|
||||||
|
// Expands environment variable references in a string. Intended primarily
|
||||||
|
// for use with IWAD search paths in config files.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FString ExpandEnvVars(const char *searchpathstring)
|
||||||
|
{
|
||||||
|
static const char envvarnamechars[] =
|
||||||
|
"01234567890"
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
"_"
|
||||||
|
"abcdefghijklmnopqrstuvwxyz";
|
||||||
|
|
||||||
|
if (searchpathstring == NULL)
|
||||||
|
return FString("");
|
||||||
|
|
||||||
|
const char *dollar = strchr(searchpathstring, '$');
|
||||||
|
if (dollar == NULL)
|
||||||
|
{
|
||||||
|
return FString(searchpathstring);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *nextchars = searchpathstring;
|
||||||
|
FString out = FString(searchpathstring, dollar - searchpathstring);
|
||||||
|
while ( (dollar != NULL) && (*nextchars != 0) )
|
||||||
|
{
|
||||||
|
size_t length = strspn(dollar + 1, envvarnamechars);
|
||||||
|
if (length != 0)
|
||||||
|
{
|
||||||
|
FString varname = FString(dollar + 1, length);
|
||||||
|
if (stricmp(varname, "progdir") == 0)
|
||||||
|
{
|
||||||
|
out += progdir;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char *varvalue = getenv(varname);
|
||||||
|
if ( (varvalue != NULL) && (strlen(varvalue) != 0) )
|
||||||
|
{
|
||||||
|
out += varvalue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out += '$';
|
||||||
|
}
|
||||||
|
nextchars = dollar + length + 1;
|
||||||
|
dollar = strchr(nextchars, '$');
|
||||||
|
if (dollar != NULL)
|
||||||
|
{
|
||||||
|
out += FString(nextchars, dollar - nextchars);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (*nextchars != 0)
|
||||||
|
{
|
||||||
|
out += nextchars;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
|
@ -55,4 +55,6 @@ int strbin (char *str);
|
||||||
|
|
||||||
void CreatePath(const char * fn);
|
void CreatePath(const char * fn);
|
||||||
|
|
||||||
|
FString ExpandEnvVars(const char *searchpathstring);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
** Implements the basic .ini parsing class
|
** Implements the basic .ini parsing class
|
||||||
**
|
**
|
||||||
**---------------------------------------------------------------------------
|
**---------------------------------------------------------------------------
|
||||||
** Copyright 1998-2006 Randy Heit
|
** Copyright 1998-2008 Randy Heit
|
||||||
** All rights reserved.
|
** All rights reserved.
|
||||||
**
|
**
|
||||||
** Redistribution and use in source and binary forms, with or without
|
** Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -30,11 +30,6 @@
|
||||||
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
**---------------------------------------------------------------------------
|
**---------------------------------------------------------------------------
|
||||||
**
|
**
|
||||||
** This could have been done with a lot less source code using the STL and
|
|
||||||
** maps, but how much larger would the object code be?
|
|
||||||
**
|
|
||||||
** Regardless of object size, I had not considered the possibility of using
|
|
||||||
** the STL when I wrote this.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -46,6 +41,12 @@
|
||||||
|
|
||||||
#define READBUFFERSIZE 256
|
#define READBUFFERSIZE 256
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
//
|
||||||
|
// FConfigFile Constructor
|
||||||
|
//
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
FConfigFile::FConfigFile ()
|
FConfigFile::FConfigFile ()
|
||||||
{
|
{
|
||||||
Sections = CurrentSection = NULL;
|
Sections = CurrentSection = NULL;
|
||||||
|
@ -54,6 +55,12 @@ FConfigFile::FConfigFile ()
|
||||||
PathName = "";
|
PathName = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
//
|
||||||
|
// FConfigFile Constructor
|
||||||
|
//
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
FConfigFile::FConfigFile (const char *pathname,
|
FConfigFile::FConfigFile (const char *pathname,
|
||||||
void (*nosechandler)(const char *pathname, FConfigFile *config, void *userdata),
|
void (*nosechandler)(const char *pathname, FConfigFile *config, void *userdata),
|
||||||
void *userdata)
|
void *userdata)
|
||||||
|
@ -65,6 +72,12 @@ FConfigFile::FConfigFile (const char *pathname,
|
||||||
LoadConfigFile (nosechandler, userdata);
|
LoadConfigFile (nosechandler, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
//
|
||||||
|
// FConfigFile Copy Constructor
|
||||||
|
//
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
FConfigFile::FConfigFile (const FConfigFile &other)
|
FConfigFile::FConfigFile (const FConfigFile &other)
|
||||||
{
|
{
|
||||||
Sections = CurrentSection = NULL;
|
Sections = CurrentSection = NULL;
|
||||||
|
@ -74,6 +87,12 @@ FConfigFile::FConfigFile (const FConfigFile &other)
|
||||||
*this = other;
|
*this = other;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
//
|
||||||
|
// FConfigFile Destructor
|
||||||
|
//
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
FConfigFile::~FConfigFile ()
|
FConfigFile::~FConfigFile ()
|
||||||
{
|
{
|
||||||
FConfigSection *section = Sections;
|
FConfigSection *section = Sections;
|
||||||
|
@ -90,11 +109,18 @@ FConfigFile::~FConfigFile ()
|
||||||
delete[] (char *)entry;
|
delete[] (char *)entry;
|
||||||
entry = nextentry;
|
entry = nextentry;
|
||||||
}
|
}
|
||||||
|
section->~FConfigSection();
|
||||||
delete[] (char *)section;
|
delete[] (char *)section;
|
||||||
section = nextsection;
|
section = nextsection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
//
|
||||||
|
// FConfigFile Copy Operator
|
||||||
|
//
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
FConfigFile &FConfigFile::operator = (const FConfigFile &other)
|
FConfigFile &FConfigFile::operator = (const FConfigFile &other)
|
||||||
{
|
{
|
||||||
FConfigSection *fromsection, *tosection;
|
FConfigSection *fromsection, *tosection;
|
||||||
|
@ -116,6 +142,14 @@ FConfigFile &FConfigFile::operator = (const FConfigFile &other)
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
//
|
||||||
|
// FConfigFile :: ClearConfig
|
||||||
|
//
|
||||||
|
// Removes all sections and entries from the config file.
|
||||||
|
//
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
void FConfigFile::ClearConfig ()
|
void FConfigFile::ClearConfig ()
|
||||||
{
|
{
|
||||||
CurrentSection = Sections;
|
CurrentSection = Sections;
|
||||||
|
@ -130,11 +164,73 @@ void FConfigFile::ClearConfig ()
|
||||||
LastSectionPtr = &Sections;
|
LastSectionPtr = &Sections;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
//
|
||||||
|
// FConfigFile :: ChangePathName
|
||||||
|
//
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
void FConfigFile::ChangePathName (const char *pathname)
|
void FConfigFile::ChangePathName (const char *pathname)
|
||||||
{
|
{
|
||||||
PathName = pathname;
|
PathName = pathname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
//
|
||||||
|
// FConfigFile :: CreateSectionAtStart
|
||||||
|
//
|
||||||
|
// Creates the section at the start of the file if it does not exist.
|
||||||
|
// Otherwise, simply moves the section to the start of the file.
|
||||||
|
//
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
|
void FConfigFile::CreateSectionAtStart (const char *name)
|
||||||
|
{
|
||||||
|
NewConfigSection (name);
|
||||||
|
MoveSectionToStart (name);
|
||||||
|
}
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
//
|
||||||
|
// FConfigFile :: MoveSectionToStart
|
||||||
|
//
|
||||||
|
// Moves the named section to the start of the file if it exists.
|
||||||
|
// Otherwise, does nothing.
|
||||||
|
//
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
|
void FConfigFile::MoveSectionToStart (const char *name)
|
||||||
|
{
|
||||||
|
FConfigSection *section = FindSection (name);
|
||||||
|
|
||||||
|
if (section != NULL)
|
||||||
|
{
|
||||||
|
FConfigSection **prevsec = &Sections;
|
||||||
|
while (*prevsec != NULL && *prevsec != section)
|
||||||
|
{
|
||||||
|
prevsec = &((*prevsec)->Next);
|
||||||
|
}
|
||||||
|
*prevsec = section->Next;
|
||||||
|
section->Next = Sections;
|
||||||
|
Sections = section;
|
||||||
|
if (LastSectionPtr == §ion->Next)
|
||||||
|
{
|
||||||
|
LastSectionPtr = prevsec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
//
|
||||||
|
// FConfigFile :: SetSection
|
||||||
|
//
|
||||||
|
// Sets the current section to the named one, optionally creating it
|
||||||
|
// if it does not exist. Returns true if the section exists (even if
|
||||||
|
// it was newly created), false otherwise.
|
||||||
|
//
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
bool FConfigFile::SetSection (const char *name, bool allowCreate)
|
bool FConfigFile::SetSection (const char *name, bool allowCreate)
|
||||||
{
|
{
|
||||||
FConfigSection *section = FindSection (name);
|
FConfigSection *section = FindSection (name);
|
||||||
|
@ -151,6 +247,14 @@ bool FConfigFile::SetSection (const char *name, bool allowCreate)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
//
|
||||||
|
// FConfigFile :: SetFirstSection
|
||||||
|
//
|
||||||
|
// Sets the current section to the first one in the file.
|
||||||
|
//
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
bool FConfigFile::SetFirstSection ()
|
bool FConfigFile::SetFirstSection ()
|
||||||
{
|
{
|
||||||
CurrentSection = Sections;
|
CurrentSection = Sections;
|
||||||
|
@ -162,6 +266,14 @@ bool FConfigFile::SetFirstSection ()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
//
|
||||||
|
// FConfigFile :: SetNextSection
|
||||||
|
//
|
||||||
|
// Advances the current section to the next one in the file.
|
||||||
|
//
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
bool FConfigFile::SetNextSection ()
|
bool FConfigFile::SetNextSection ()
|
||||||
{
|
{
|
||||||
if (CurrentSection != NULL)
|
if (CurrentSection != NULL)
|
||||||
|
@ -176,6 +288,14 @@ bool FConfigFile::SetNextSection ()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
//
|
||||||
|
// FConfigFile :: GetCurrentSection
|
||||||
|
//
|
||||||
|
// Returns the name of the current section.
|
||||||
|
//
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
const char *FConfigFile::GetCurrentSection () const
|
const char *FConfigFile::GetCurrentSection () const
|
||||||
{
|
{
|
||||||
if (CurrentSection != NULL)
|
if (CurrentSection != NULL)
|
||||||
|
@ -185,6 +305,14 @@ const char *FConfigFile::GetCurrentSection () const
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
//
|
||||||
|
// FConfigFile :: ClearCurrentSection
|
||||||
|
//
|
||||||
|
// Removes all entries from the current section.
|
||||||
|
//
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
void FConfigFile::ClearCurrentSection ()
|
void FConfigFile::ClearCurrentSection ()
|
||||||
{
|
{
|
||||||
if (CurrentSection != NULL)
|
if (CurrentSection != NULL)
|
||||||
|
@ -204,6 +332,30 @@ void FConfigFile::ClearCurrentSection ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
//
|
||||||
|
// FConfigFile :: SectionIsEmpty
|
||||||
|
//
|
||||||
|
// Returns true if the current section has no entries. If there is
|
||||||
|
// no current section, it is also considered empty.
|
||||||
|
//
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
|
bool FConfigFile::SectionIsEmpty()
|
||||||
|
{
|
||||||
|
return (CurrentSection == NULL) || (CurrentSection->RootEntry == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
//
|
||||||
|
// FConfigFile :: NextInSection
|
||||||
|
//
|
||||||
|
// Provides the next key/value pair in the current section. Returns
|
||||||
|
// true if there was another, false otherwise.
|
||||||
|
//
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
bool FConfigFile::NextInSection (const char *&key, const char *&value)
|
bool FConfigFile::NextInSection (const char *&key, const char *&value)
|
||||||
{
|
{
|
||||||
FConfigEntry *entry = CurrentEntry;
|
FConfigEntry *entry = CurrentEntry;
|
||||||
|
@ -217,6 +369,15 @@ bool FConfigFile::NextInSection (const char *&key, const char *&value)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
//
|
||||||
|
// FConfigFile :: GetValueForKey
|
||||||
|
//
|
||||||
|
// Returns the value for the specified key in the current section,
|
||||||
|
// returning NULL if the key does not exist.
|
||||||
|
//
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
const char *FConfigFile::GetValueForKey (const char *key) const
|
const char *FConfigFile::GetValueForKey (const char *key) const
|
||||||
{
|
{
|
||||||
FConfigEntry *entry = FindEntry (CurrentSection, key);
|
FConfigEntry *entry = FindEntry (CurrentSection, key);
|
||||||
|
@ -228,6 +389,16 @@ const char *FConfigFile::GetValueForKey (const char *key) const
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
//
|
||||||
|
// FConfigFile :: SetValueForKey
|
||||||
|
//
|
||||||
|
// Sets they key/value pair as specified in the current section. If
|
||||||
|
// duplicates are allowed, it always creates a new pair. Otherwise, it
|
||||||
|
// will overwrite the value of an existing key with the same name.
|
||||||
|
//
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
void FConfigFile::SetValueForKey (const char *key, const char *value, bool duplicates)
|
void FConfigFile::SetValueForKey (const char *key, const char *value, bool duplicates)
|
||||||
{
|
{
|
||||||
if (CurrentSection != NULL)
|
if (CurrentSection != NULL)
|
||||||
|
@ -245,6 +416,12 @@ void FConfigFile::SetValueForKey (const char *key, const char *value, bool dupli
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
//
|
||||||
|
// FConfigFile :: FindSection
|
||||||
|
//
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
FConfigFile::FConfigSection *FConfigFile::FindSection (const char *name) const
|
FConfigFile::FConfigSection *FConfigFile::FindSection (const char *name) const
|
||||||
{
|
{
|
||||||
FConfigSection *section = Sections;
|
FConfigSection *section = Sections;
|
||||||
|
@ -256,6 +433,12 @@ FConfigFile::FConfigSection *FConfigFile::FindSection (const char *name) const
|
||||||
return section;
|
return section;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
//
|
||||||
|
// FConfigFile :: FindEntry
|
||||||
|
//
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
FConfigFile::FConfigEntry *FConfigFile::FindEntry (
|
FConfigFile::FConfigEntry *FConfigFile::FindEntry (
|
||||||
FConfigFile::FConfigSection *section, const char *key) const
|
FConfigFile::FConfigSection *section, const char *key) const
|
||||||
{
|
{
|
||||||
|
@ -268,15 +451,23 @@ FConfigFile::FConfigEntry *FConfigFile::FindEntry (
|
||||||
return probe;
|
return probe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
//
|
||||||
|
// FConfigFile :: NewConfigSection
|
||||||
|
//
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
FConfigFile::FConfigSection *FConfigFile::NewConfigSection (const char *name)
|
FConfigFile::FConfigSection *FConfigFile::NewConfigSection (const char *name)
|
||||||
{
|
{
|
||||||
FConfigSection *section;
|
FConfigSection *section;
|
||||||
|
char *memblock;
|
||||||
|
|
||||||
section = FindSection (name);
|
section = FindSection (name);
|
||||||
if (section == NULL)
|
if (section == NULL)
|
||||||
{
|
{
|
||||||
size_t namelen = strlen (name);
|
size_t namelen = strlen (name);
|
||||||
section = (FConfigSection *)new char[sizeof(*section)+namelen];
|
memblock = new char[sizeof(*section)+namelen];
|
||||||
|
section = ::new(memblock) FConfigSection;
|
||||||
section->RootEntry = NULL;
|
section->RootEntry = NULL;
|
||||||
section->LastEntryPtr = §ion->RootEntry;
|
section->LastEntryPtr = §ion->RootEntry;
|
||||||
section->Next = NULL;
|
section->Next = NULL;
|
||||||
|
@ -288,6 +479,12 @@ FConfigFile::FConfigSection *FConfigFile::NewConfigSection (const char *name)
|
||||||
return section;
|
return section;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
//
|
||||||
|
// FConfigFile :: NewConfigEntry
|
||||||
|
//
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
FConfigFile::FConfigEntry *FConfigFile::NewConfigEntry (
|
FConfigFile::FConfigEntry *FConfigFile::NewConfigEntry (
|
||||||
FConfigFile::FConfigSection *section, const char *key, const char *value)
|
FConfigFile::FConfigSection *section, const char *key, const char *value)
|
||||||
{
|
{
|
||||||
|
@ -306,6 +503,12 @@ FConfigFile::FConfigEntry *FConfigFile::NewConfigEntry (
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
//
|
||||||
|
// FConfigFile :: LoadConfigFile
|
||||||
|
//
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
void FConfigFile::LoadConfigFile (void (*nosechandler)(const char *pathname, FConfigFile *config, void *userdata), void *userdata)
|
void FConfigFile::LoadConfigFile (void (*nosechandler)(const char *pathname, FConfigFile *config, void *userdata), void *userdata)
|
||||||
{
|
{
|
||||||
FILE *file = fopen (PathName, "r");
|
FILE *file = fopen (PathName, "r");
|
||||||
|
@ -326,6 +529,12 @@ void FConfigFile::LoadConfigFile (void (*nosechandler)(const char *pathname, FCo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
//
|
||||||
|
// FConfigFile :: ReadConfig
|
||||||
|
//
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
bool FConfigFile::ReadConfig (void *file)
|
bool FConfigFile::ReadConfig (void *file)
|
||||||
{
|
{
|
||||||
char readbuf[READBUFFERSIZE];
|
char readbuf[READBUFFERSIZE];
|
||||||
|
@ -394,11 +603,23 @@ bool FConfigFile::ReadConfig (void *file)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
//
|
||||||
|
// FConfigFile :: ReadLine
|
||||||
|
//
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
char *FConfigFile::ReadLine (char *string, int n, void *file) const
|
char *FConfigFile::ReadLine (char *string, int n, void *file) const
|
||||||
{
|
{
|
||||||
return fgets (string, n, (FILE *)file);
|
return fgets (string, n, (FILE *)file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
//
|
||||||
|
// FConfigFile :: WriteConfigFile
|
||||||
|
//
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
bool FConfigFile::WriteConfigFile () const
|
bool FConfigFile::WriteConfigFile () const
|
||||||
{
|
{
|
||||||
FILE *file = fopen (PathName, "w");
|
FILE *file = fopen (PathName, "w");
|
||||||
|
@ -414,6 +635,10 @@ bool FConfigFile::WriteConfigFile () const
|
||||||
while (section != NULL)
|
while (section != NULL)
|
||||||
{
|
{
|
||||||
entry = section->RootEntry;
|
entry = section->RootEntry;
|
||||||
|
if (section->Note.IsNotEmpty())
|
||||||
|
{
|
||||||
|
fprintf (file, "%s", section->Note.GetChars());
|
||||||
|
}
|
||||||
fprintf (file, "[%s]\n", section->Name);
|
fprintf (file, "[%s]\n", section->Name);
|
||||||
while (entry != NULL)
|
while (entry != NULL)
|
||||||
{
|
{
|
||||||
|
@ -427,10 +652,24 @@ bool FConfigFile::WriteConfigFile () const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
//
|
||||||
|
// FConfigFile :: WriteCommentHeader
|
||||||
|
//
|
||||||
|
// Override in a subclass to write a header to the config file.
|
||||||
|
//
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
void FConfigFile::WriteCommentHeader (FILE *file) const
|
void FConfigFile::WriteCommentHeader (FILE *file) const
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
//
|
||||||
|
// FConfigFile :: FConfigEntry :: SetValue
|
||||||
|
//
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
void FConfigFile::FConfigEntry::SetValue (const char *value)
|
void FConfigFile::FConfigEntry::SetValue (const char *value)
|
||||||
{
|
{
|
||||||
if (Value != NULL)
|
if (Value != NULL)
|
||||||
|
@ -441,14 +680,62 @@ void FConfigFile::FConfigEntry::SetValue (const char *value)
|
||||||
strcpy (Value, value);
|
strcpy (Value, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
//
|
||||||
|
// FConfigFile :: GetPosition
|
||||||
|
//
|
||||||
|
// Populates a struct with the current position of the parse cursor.
|
||||||
|
//
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
void FConfigFile::GetPosition (FConfigFile::Position &pos) const
|
void FConfigFile::GetPosition (FConfigFile::Position &pos) const
|
||||||
{
|
{
|
||||||
pos.Section = CurrentSection;
|
pos.Section = CurrentSection;
|
||||||
pos.Entry = CurrentEntry;
|
pos.Entry = CurrentEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
//
|
||||||
|
// FConfigFile :: SetPosition
|
||||||
|
//
|
||||||
|
// Sets the parse cursor to a previously retrieved position.
|
||||||
|
//
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
void FConfigFile::SetPosition (const FConfigFile::Position &pos)
|
void FConfigFile::SetPosition (const FConfigFile::Position &pos)
|
||||||
{
|
{
|
||||||
CurrentSection = pos.Section;
|
CurrentSection = pos.Section;
|
||||||
CurrentEntry = pos.Entry;
|
CurrentEntry = pos.Entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//====================================================================
|
||||||
|
//
|
||||||
|
// FConfigFile :: SetSectionNote
|
||||||
|
//
|
||||||
|
// Sets a comment note to be inserted into the INI verbatim directly
|
||||||
|
// ahead of the section. Notes are lost when the INI is read so must
|
||||||
|
// be explicitly set to be maintained.
|
||||||
|
//
|
||||||
|
//====================================================================
|
||||||
|
|
||||||
|
void FConfigFile::SetSectionNote(const char *section, const char *note)
|
||||||
|
{
|
||||||
|
SetSectionNote(FindSection(section), note);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FConfigFile::SetSectionNote(const char *note)
|
||||||
|
{
|
||||||
|
SetSectionNote(CurrentSection, note);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FConfigFile::SetSectionNote(FConfigSection *section, const char *note)
|
||||||
|
{
|
||||||
|
if (section != NULL)
|
||||||
|
{
|
||||||
|
if (note == NULL)
|
||||||
|
{
|
||||||
|
note = "";
|
||||||
|
}
|
||||||
|
section->Note = note;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
** configfile.h
|
** configfile.h
|
||||||
**
|
**
|
||||||
**---------------------------------------------------------------------------
|
**---------------------------------------------------------------------------
|
||||||
** Copyright 1998-2006 Randy Heit
|
** Copyright 1998-2008 Randy Heit
|
||||||
** All rights reserved.
|
** All rights reserved.
|
||||||
**
|
**
|
||||||
** Redistribution and use in source and binary forms, with or without
|
** Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -50,12 +50,17 @@ public:
|
||||||
FConfigFile &operator= (const FConfigFile &other);
|
FConfigFile &operator= (const FConfigFile &other);
|
||||||
|
|
||||||
bool HaveSections () { return Sections != NULL; }
|
bool HaveSections () { return Sections != NULL; }
|
||||||
|
void CreateSectionAtStart (const char *name);
|
||||||
|
void MoveSectionToStart (const char *name);
|
||||||
|
void SetSectionNote (const char *section, const char *note);
|
||||||
|
void SetSectionNote (const char *note);
|
||||||
bool SetSection (const char *section, bool allowCreate=false);
|
bool SetSection (const char *section, bool allowCreate=false);
|
||||||
bool SetFirstSection ();
|
bool SetFirstSection ();
|
||||||
bool SetNextSection ();
|
bool SetNextSection ();
|
||||||
const char *GetCurrentSection () const;
|
const char *GetCurrentSection () const;
|
||||||
void ClearCurrentSection ();
|
void ClearCurrentSection ();
|
||||||
|
|
||||||
|
bool SectionIsEmpty ();
|
||||||
bool NextInSection (const char *&key, const char *&value);
|
bool NextInSection (const char *&key, const char *&value);
|
||||||
const char *GetValueForKey (const char *key) const;
|
const char *GetValueForKey (const char *key) const;
|
||||||
void SetValueForKey (const char *key, const char *value, bool duplicates=false);
|
void SetValueForKey (const char *key, const char *value, bool duplicates=false);
|
||||||
|
@ -86,6 +91,7 @@ private:
|
||||||
FConfigEntry *RootEntry;
|
FConfigEntry *RootEntry;
|
||||||
FConfigEntry **LastEntryPtr;
|
FConfigEntry **LastEntryPtr;
|
||||||
FConfigSection *Next;
|
FConfigSection *Next;
|
||||||
|
FString Note;
|
||||||
char Name[1]; // + length of name
|
char Name[1]; // + length of name
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -99,6 +105,7 @@ private:
|
||||||
FConfigEntry *FindEntry (FConfigSection *section, const char *key) const;
|
FConfigEntry *FindEntry (FConfigSection *section, const char *key) const;
|
||||||
FConfigSection *NewConfigSection (const char *name);
|
FConfigSection *NewConfigSection (const char *name);
|
||||||
FConfigEntry *NewConfigEntry (FConfigSection *section, const char *key, const char *value);
|
FConfigEntry *NewConfigEntry (FConfigSection *section, const char *key, const char *value);
|
||||||
|
void SetSectionNote (FConfigSection *section, const char *note);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class Position
|
class Position
|
||||||
|
|
|
@ -1656,71 +1656,6 @@ static int CheckIWAD (const char *doomwaddir, WadStuff *wads)
|
||||||
return numfound;
|
return numfound;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// ExpandEnvVars
|
|
||||||
//
|
|
||||||
// Expands environment variable references in a string. Intended primarily
|
|
||||||
// for use with IWAD search paths in config files.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
static FString ExpandEnvVars(const char *searchpathstring)
|
|
||||||
{
|
|
||||||
static const char envvarnamechars[] =
|
|
||||||
"01234567890"
|
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
||||||
"_"
|
|
||||||
"abcdefghijklmnopqrstuvwxyz";
|
|
||||||
|
|
||||||
if (searchpathstring == NULL)
|
|
||||||
return FString ("");
|
|
||||||
|
|
||||||
const char *dollar = strchr (searchpathstring,'$');
|
|
||||||
if (dollar == NULL)
|
|
||||||
{
|
|
||||||
return FString (searchpathstring);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *nextchars = searchpathstring;
|
|
||||||
FString out = FString (searchpathstring, dollar - searchpathstring);
|
|
||||||
while ( (dollar != NULL) && (*nextchars != 0) )
|
|
||||||
{
|
|
||||||
size_t length = strspn(dollar + 1, envvarnamechars);
|
|
||||||
if (length != 0)
|
|
||||||
{
|
|
||||||
FString varname = FString (dollar + 1, length);
|
|
||||||
if (stricmp (varname, "progdir") == 0)
|
|
||||||
{
|
|
||||||
out += progdir;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char *varvalue = getenv (varname);
|
|
||||||
if ( (varvalue != NULL) && (strlen(varvalue) != 0) )
|
|
||||||
{
|
|
||||||
out += varvalue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
out += '$';
|
|
||||||
}
|
|
||||||
nextchars = dollar + length + 1;
|
|
||||||
dollar = strchr (nextchars, '$');
|
|
||||||
if (dollar != NULL)
|
|
||||||
{
|
|
||||||
out += FString (nextchars, dollar - nextchars);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (*nextchars != 0)
|
|
||||||
{
|
|
||||||
out += nextchars;
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// CheckIWADinEnvDir
|
// CheckIWADinEnvDir
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
** An .ini parser specifically for zdoom.ini
|
** An .ini parser specifically for zdoom.ini
|
||||||
**
|
**
|
||||||
**---------------------------------------------------------------------------
|
**---------------------------------------------------------------------------
|
||||||
** Copyright 1998-2006 Randy Heit
|
** Copyright 1998-2008 Randy Heit
|
||||||
** All rights reserved.
|
** All rights reserved.
|
||||||
**
|
**
|
||||||
** Redistribution and use in source and binary forms, with or without
|
** Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -120,6 +120,60 @@ FGameConfigFile::FGameConfigFile ()
|
||||||
#endif
|
#endif
|
||||||
SetValueForKey ("Path", "$DOOMWADDIR", true);
|
SetValueForKey ("Path", "$DOOMWADDIR", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create auto-load sections, so users know what's available.
|
||||||
|
// Note that this totem pole is the reverse of the order that
|
||||||
|
// they will appear in the file.
|
||||||
|
CreateSectionAtStart("Chex3.Autoload");
|
||||||
|
CreateSectionAtStart("Chex.Autoload");
|
||||||
|
CreateSectionAtStart("Strife.Autoload");
|
||||||
|
CreateSectionAtStart("HexenDemo.Autoload");
|
||||||
|
CreateSectionAtStart("HexenDK.Autoload");
|
||||||
|
CreateSectionAtStart("Hexen.Autoload");
|
||||||
|
CreateSectionAtStart("Heretic.Autoload");
|
||||||
|
CreateSectionAtStart("FreeDM.Autoload");
|
||||||
|
CreateSectionAtStart("Freedoom1.Autoload");
|
||||||
|
CreateSectionAtStart("Freedoom.Autoload");
|
||||||
|
CreateSectionAtStart("Plutonia.Autoload");
|
||||||
|
CreateSectionAtStart("TNT.Autoload");
|
||||||
|
CreateSectionAtStart("Doom2.Autoload");
|
||||||
|
CreateSectionAtStart("Doom1.Autoload");
|
||||||
|
CreateSectionAtStart("Doom.Autoload");
|
||||||
|
CreateSectionAtStart("Global.Autoload");
|
||||||
|
|
||||||
|
// The same goes for auto-exec files.
|
||||||
|
CreateStandardAutoExec("Chex.AutoExec", true);
|
||||||
|
CreateStandardAutoExec("Strife.AutoExec", true);
|
||||||
|
CreateStandardAutoExec("Hexen.AutoExec", true);
|
||||||
|
CreateStandardAutoExec("Heretic.AutoExec", true);
|
||||||
|
CreateStandardAutoExec("Doom.AutoExec", true);
|
||||||
|
|
||||||
|
// Move search paths back to the top.
|
||||||
|
MoveSectionToStart("FileSearch.Directories");
|
||||||
|
MoveSectionToStart("IWADSearch.Directories");
|
||||||
|
|
||||||
|
// Add some self-documentation.
|
||||||
|
SetSectionNote("IWADSearch.Directories",
|
||||||
|
"# These are the directories to automatically search for IWADs.\n"
|
||||||
|
"# Each directory should be on a separate line, preceded by Path=\n");
|
||||||
|
SetSectionNote("FileSearch.Directories",
|
||||||
|
"# These are the directories to search for wads added with the -file\n"
|
||||||
|
"# command line parameter, if they cannot be found with the path\n"
|
||||||
|
"# as-is. Layout is the same as for IWADSearch.Directories\n");
|
||||||
|
SetSectionNote("Doom.AutoExec",
|
||||||
|
"# Files to automatically execute when running the corresponding game.\n"
|
||||||
|
"# Each file should be on its own line, preceded by Path=\n\n");
|
||||||
|
SetSectionNote("Global.Autoload",
|
||||||
|
"# WAD files to always load. These are loaded after the IWAD but before\n"
|
||||||
|
"# any files added with -file. Place each file on its own line, preceded\n"
|
||||||
|
"# by Path=\n");
|
||||||
|
SetSectionNote("Doom.Autoload",
|
||||||
|
"# Wad files to automatically load depending on the game and IWAD you are\n"
|
||||||
|
"# playing. You may have have files that are loaded for all similar IWADs\n"
|
||||||
|
"# (the game) and files that are only loaded for particular IWADs. For example,\n"
|
||||||
|
"# any files listed under Doom.Autoload will be loaded for any version of Doom,\n"
|
||||||
|
"# but files listed under Doom2.Autoload will only load when you are\n"
|
||||||
|
"# playing Doom 2.\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
FGameConfigFile::~FGameConfigFile ()
|
FGameConfigFile::~FGameConfigFile ()
|
||||||
|
@ -128,8 +182,7 @@ FGameConfigFile::~FGameConfigFile ()
|
||||||
|
|
||||||
void FGameConfigFile::WriteCommentHeader (FILE *file) const
|
void FGameConfigFile::WriteCommentHeader (FILE *file) const
|
||||||
{
|
{
|
||||||
fprintf (file, "# This file was generated by " GAMENAME " " DOTVERSIONSTR " on %s"
|
fprintf (file, "# This file was generated by " GAMENAME " " DOTVERSIONSTR " on %s\n", myasctime());
|
||||||
"# It is not really meant to be modified outside of ZDoom, nyo.\n\n", myasctime ());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGameConfigFile::MigrateStub (const char *pathname, FConfigFile *config, void *userdata)
|
void FGameConfigFile::MigrateStub (const char *pathname, FConfigFile *config, void *userdata)
|
||||||
|
@ -507,6 +560,25 @@ FString FGameConfigFile::GetConfigPath (bool tryProg)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FGameConfigFile::CreateStandardAutoExec(const char *section, bool start)
|
||||||
|
{
|
||||||
|
if (!SetSection(section))
|
||||||
|
{
|
||||||
|
FString path;
|
||||||
|
#ifndef unix
|
||||||
|
path = "$PROGDIR/autoexec.cfg";
|
||||||
|
#else
|
||||||
|
path = GetUserFile ("autoexec.cfg");
|
||||||
|
#endif
|
||||||
|
SetSection (section, true);
|
||||||
|
SetValueForKey ("Path", path.GetChars());
|
||||||
|
}
|
||||||
|
if (start)
|
||||||
|
{
|
||||||
|
MoveSectionToStart(section);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void FGameConfigFile::AddAutoexec (DArgs *list, const char *game)
|
void FGameConfigFile::AddAutoexec (DArgs *list, const char *game)
|
||||||
{
|
{
|
||||||
char section[64];
|
char section[64];
|
||||||
|
@ -537,34 +609,19 @@ void FGameConfigFile::AddAutoexec (DArgs *list, const char *game)
|
||||||
{
|
{
|
||||||
// If <game>.AutoExec section does not exist, create it
|
// If <game>.AutoExec section does not exist, create it
|
||||||
// with a default autoexec.cfg file present.
|
// with a default autoexec.cfg file present.
|
||||||
if (!SetSection (section))
|
CreateStandardAutoExec(section, false);
|
||||||
{
|
|
||||||
FString path;
|
|
||||||
|
|
||||||
#ifndef unix
|
|
||||||
if (Args->CheckParm ("-cdrom"))
|
|
||||||
{
|
|
||||||
path = CDROM_DIR "\\autoexec.cfg";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
path = progdir;
|
|
||||||
path += "autoexec.cfg";
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
path = GetUserFile ("autoexec.cfg");
|
|
||||||
#endif
|
|
||||||
SetSection (section, true);
|
|
||||||
SetValueForKey ("Path", path.GetChars());
|
|
||||||
}
|
|
||||||
// Run any files listed in the <game>.AutoExec section
|
// Run any files listed in the <game>.AutoExec section
|
||||||
if (SetSection (section))
|
if (!SectionIsEmpty())
|
||||||
{
|
{
|
||||||
while (NextInSection (key, value))
|
while (NextInSection (key, value))
|
||||||
{
|
{
|
||||||
if (stricmp (key, "Path") == 0 && FileExists (value))
|
if (stricmp (key, "Path") == 0 && *value != '\0')
|
||||||
{
|
{
|
||||||
list->AppendArg (value);
|
FString expanded_path = ExpandEnvVars(value);
|
||||||
|
if (FileExists(expanded_path))
|
||||||
|
{
|
||||||
|
list->AppendArg (ExpandEnvVars(value));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
** gameconfigfile.h
|
** gameconfigfile.h
|
||||||
**
|
**
|
||||||
**---------------------------------------------------------------------------
|
**---------------------------------------------------------------------------
|
||||||
** Copyright 1998-2006 Randy Heit
|
** Copyright 1998-2008 Randy Heit
|
||||||
** All rights reserved.
|
** All rights reserved.
|
||||||
**
|
**
|
||||||
** Redistribution and use in source and binary forms, with or without
|
** Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -56,6 +56,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void WriteCommentHeader (FILE *file) const;
|
void WriteCommentHeader (FILE *file) const;
|
||||||
|
void CreateStandardAutoExec (const char *section, bool start);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void MigrateStub (const char *pathname, FConfigFile *config, void *userdata);
|
static void MigrateStub (const char *pathname, FConfigFile *config, void *userdata);
|
||||||
|
|
Loading…
Reference in a new issue