From 8d9bc8cc67335a07b9bde0df5decfe5810bf5715 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sat, 7 Feb 2009 01:14:36 +0000 Subject: [PATCH] - Fixed: Keys bound in a custom key section would unbind the key in the main game section. SVN r1409 (trunk) --- docs/rh-log.txt | 4 ++- src/c_bind.cpp | 58 ++++++++++++++++++++++++++++++------------ src/configfile.cpp | 34 +++++++++++++++++++++++++ src/configfile.h | 1 + src/gameconfigfile.cpp | 2 -- 5 files changed, 80 insertions(+), 19 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index aa679c8d54..85c8f91089 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,5 +1,7 @@ February 6, 2009 -- Fixed scrolling of the automap background on a rotating automap. +- Fixed: Keys bound in a custom key section would unbind the key in the + main game section. +- Fixed scrolling of the automap background on a rotated automap. February 5, 2009 - Changed singleplayer allowrespawn to act like a co-op game when you diff --git a/src/c_bind.cpp b/src/c_bind.cpp index f02a1b2d50..422437d3cd 100644 --- a/src/c_bind.cpp +++ b/src/c_bind.cpp @@ -580,35 +580,61 @@ bool C_DoKey (event_t *ev) return false; } +const char *C_ConfigKeyName(int keynum) +{ + const char *name = KeyName(keynum); + if (name[1] == 0) // Make sure given name is config-safe + { + if (name[0] == '[') + return "LeftBracket"; + else if (name[0] == ']') + return "RightBracket"; + else if (name[0] == '=') + return "Equals"; + else if (strcmp (name, "kp=") == 0) + return "KP-Equals"; + } + return name; +} + +// This function is first called for functions in custom key sections. +// In this case, matchcmd is non-NULL, and only keys bound to that command +// are stored. If a match is found, its binding is set to "\1". +// After all custom key sections are saved, it is called one more for the +// normal Bindings and DoubleBindings sections for this game. In this case +// matchcmd is NULL and all keys will be stored. The config section was not +// previously cleared, so all old bindings are still in place. If the binding +// for a key is empty, the corresponding key in the config is removed as well. +// If a binding is "\1", then the binding itself is cleared, but nothing +// happens to the entry in the config. void C_ArchiveBindings (FConfigFile *f, bool dodouble, const char *matchcmd) { FString *bindings; - const char *name; int i; bindings = dodouble ? DoubleBindings : Bindings; for (i = 0; i < NUM_KEYS; i++) { - if (!bindings[i].IsEmpty() && (matchcmd==NULL || stricmp(bindings[i], matchcmd)==0)) + if (bindings[i].IsEmpty()) { - name = KeyName (i); - if (name[1] == 0) // Make sure given name is config-safe + if (matchcmd == NULL) { - if (name[0] == '[') - name = "LeftBracket"; - else if (name[0] == ']') - name = "RightBracket"; - else if (name[0] == '=') - name = "Equals"; - else if (strcmp (name, "kp=") == 0) - name = "KP-Equals"; + f->ClearKey(C_ConfigKeyName(i)); } - f->SetValueForKey (name, bindings[i]); + } + else if (matchcmd == NULL || stricmp(bindings[i], matchcmd) == 0) + { + if (bindings[i][0] == '\1') + { + bindings[i] = ""; + continue; + } + f->SetValueForKey(C_ConfigKeyName(i), bindings[i]); if (matchcmd != NULL) - { // If saving a specific command, remove the old binding - // so it does not get saved in the general binding list - Bindings[i] = ""; + { // If saving a specific command, set a marker so that + // it does not get saved in the general binding list. + bindings[i] = "\1"; } } } diff --git a/src/configfile.cpp b/src/configfile.cpp index 0e29a8c7a7..faca98562c 100644 --- a/src/configfile.cpp +++ b/src/configfile.cpp @@ -332,6 +332,40 @@ void FConfigFile::ClearCurrentSection () } } +//==================================================================== +// +// FConfigFile :: ClearKey +// +// Removes a key from the current section, if found. If there are +// duplicates, only the first is removed. +// +//==================================================================== + +void FConfigFile::ClearKey(const char *key) +{ + if (CurrentSection->RootEntry == NULL) + { + return; + } + FConfigEntry **prober = &CurrentSection->RootEntry, *probe = *prober; + + while (probe != NULL && stricmp(probe->Key, key) != 0) + { + prober = &probe->Next; + probe = *prober; + } + if (probe != NULL) + { + *prober = probe->Next; + if (CurrentSection->LastEntryPtr == &probe->Next) + { + CurrentSection->LastEntryPtr = prober; + } + delete[] probe->Value; + delete[] (char *)probe; + } +} + //==================================================================== // // FConfigFile :: SectionIsEmpty diff --git a/src/configfile.h b/src/configfile.h index 11453e5611..ca39894155 100644 --- a/src/configfile.h +++ b/src/configfile.h @@ -59,6 +59,7 @@ public: bool SetNextSection (); const char *GetCurrentSection () const; void ClearCurrentSection (); + void ClearKey (const char *key); bool SectionIsEmpty (); bool NextInSection (const char *&key, const char *&value); diff --git a/src/gameconfigfile.cpp b/src/gameconfigfile.cpp index 7a5aa223d9..7c4286c7b5 100644 --- a/src/gameconfigfile.cpp +++ b/src/gameconfigfile.cpp @@ -454,12 +454,10 @@ void FGameConfigFile::ArchiveGameData (const char *gamename) strcpy (subsection, "Bindings"); SetSection (section, true); - ClearCurrentSection (); C_ArchiveBindings (this, false); strncpy (subsection, "DoubleBindings", sublen); SetSection (section, true); - ClearCurrentSection (); C_ArchiveBindings (this, true); if (WeaponSection.IsEmpty())