Ticket #8877: config_changes_take_3.diff
File config_changes_take_3.diff, 61.4 KB (added by , 16 years ago) |
---|
-
gui/Actions.cpp
25 25 26 26 #include "gui/Actions.h" 27 27 #include "gui/message.h" 28 #include "scumm/scumm.h"29 28 #include "common/config-manager.h" 30 29 31 30 #ifdef _WIN32_WCE … … 110 109 current_version = ConfMan.getInt("action_mapping_version", domain()); 111 110 if (current_version != version()) 112 111 return false; 113 tempo = ConfMan.get ("action_mapping", domain()).c_str();112 tempo = ConfMan.getKey("action_mapping", domain()).c_str(); 114 113 if (tempo && strlen(tempo)) { 115 114 for (i=0; i<size(); i++) { 116 115 char x[7]; -
gui/theme.h
30 30 #include "common/str.h" 31 31 #include "common/file.h" 32 32 #include "common/config-file.h" 33 33 #include "common/config-manager.h" 34 34 #include "graphics/surface.h" 35 35 #include "graphics/fontman.h" 36 36 -
gui/massadd.cpp
89 89 new ButtonWidget(this, "massadddialog_cancel", "Cancel", kCancelCmd, Common::ASCII_ESCAPE); 90 90 91 91 // Build a map from all configured game paths to the targets using them 92 const Common::ConfigManager:: DomainMap &domains = ConfMan.getGameDomains();93 Common::ConfigManager:: DomainMap::const_iterator iter;94 for (iter = domains.begin(); iter != domains.end(); ++iter) {92 const Common::ConfigManager::SectionRefList §ions = ConfMan.getGameSections(); 93 Common::ConfigManager::SectionRefList::const_iterator iter; 94 for (iter = sections.begin(); iter != sections.end(); ++iter) { 95 95 96 96 #ifdef __DS__ 97 97 // DS port uses an extra section called 'ds'. This prevents the section from being 98 98 // detected as a game. 99 if ( iter->_key== "ds") {99 if ((*iter)->name == "ds") { 100 100 continue; 101 101 } 102 102 #endif 103 103 104 Common::String path( iter->_value.get("path"));104 Common::String path((*iter)->getKey("path")->value); 105 105 // Remove trailing slash, so that "/foo" and "/foo/" match. 106 106 // This works around a bug in the POSIX FS code (and others?) 107 107 // where paths are not normalized (so FSNodes refering to identical … … 109 109 while (path != "/" && path.lastChar() == '/') 110 110 path.deleteLastChar(); 111 111 if (!path.empty()) 112 _pathToTargets[path].push_back( iter->_key);112 _pathToTargets[path].push_back((*iter)->name); 113 113 } 114 114 } 115 115 … … 176 176 const Common::StringList &targets = _pathToTargets[path]; 177 177 for (Common::StringList::const_iterator iter = targets.begin(); iter != targets.end(); ++iter) { 178 178 // If the gameid, platform and language match -> skip it 179 Common::Config Manager::Domain *dom = ConfMan.getDomain(*iter);180 assert( dom);179 Common::ConfigFile::Section *sec = ConfMan.getSection(*iter); 180 assert(sec); 181 181 182 if ((* dom)["gameid"]== result["gameid"] &&183 (* dom)["platform"]== result["platform"] &&184 (* dom)["language"]== result["language"]) {182 if ((*sec).getKey("gameid")->value == result["gameid"] && 183 (*sec).getKey("platform")->value == result["platform"] && 184 (*sec).getKey("language")->value == result["language"]) { 185 185 duplicate = true; 186 186 break; 187 187 } -
gui/options.cpp
130 130 131 131 if (ConfMan.hasKey("gfx_mode", _domain)) { 132 132 const OSystem::GraphicsMode *gm = g_system->getSupportedGraphicsModes(); 133 String gfxMode(ConfMan.get ("gfx_mode", _domain));133 String gfxMode(ConfMan.getKey("gfx_mode", _domain)); 134 134 int gfxCount = 1; 135 135 while (gm->name) { 136 136 gfxCount++; … … 146 146 147 147 if (ConfMan.hasKey("render_mode", _domain)) { 148 148 const Common::RenderModeDescription *p = Common::g_renderModes; 149 const Common::RenderMode renderMode = Common::parseRenderMode(ConfMan.get ("render_mode", _domain));149 const Common::RenderMode renderMode = Common::parseRenderMode(ConfMan.getKey("render_mode", _domain)); 150 150 int sel = 0; 151 151 for (int i = 0; p->code; ++p, ++i) { 152 152 if (renderMode == p->id) … … 171 171 int i = 0; 172 172 const int midiDriver = 173 173 ConfMan.hasKey("music_driver", _domain) 174 ? MidiDriver::parseMusicDriver(ConfMan.get ("music_driver", _domain))174 ? MidiDriver::parseMusicDriver(ConfMan.getKey("music_driver", _domain)) 175 175 : MD_AUTO; 176 176 while (md->name && md->id != midiDriver) { 177 177 i++; … … 200 200 // GS extensions setting 201 201 _enableGSCheckbox->setState(ConfMan.getBool("enable_gs", _domain)); 202 202 203 String soundFont(ConfMan.get ("soundfont", _domain));203 String soundFont(ConfMan.getKey("soundfont", _domain)); 204 204 if (soundFont.empty() || !ConfMan.hasKey("soundfont", _domain)) { 205 205 _soundFont->setLabel("None"); 206 206 _soundFontClearButton->setEnabled(false); … … 659 659 660 660 661 661 GlobalOptionsDialog::GlobalOptionsDialog() 662 : OptionsDialog(Common::ConfigManager::kApplication Domain, "globaloptions") {662 : OptionsDialog(Common::ConfigManager::kApplicationSection, "globaloptions") { 663 663 664 664 // The tab widget 665 665 TabWidget *tab = new TabWidget(this, "globaloptions_tabwidget"); … … 757 757 758 758 #if !( defined(__DC__) || defined(__GP32__) || defined(__PLAYSTATION2__) ) 759 759 // Set _savePath to the current save path 760 Common::String savePath(ConfMan.get ("savepath", _domain));761 Common::String themePath(ConfMan.get ("themepath", _domain));762 Common::String extraPath(ConfMan.get ("extrapath", _domain));760 Common::String savePath(ConfMan.getKey("savepath", _domain)); 761 Common::String themePath(ConfMan.getKey("themepath", _domain)); 762 Common::String extraPath(ConfMan.getKey("extrapath", _domain)); 763 763 764 764 if (savePath.empty() || !ConfMan.hasKey("savepath", _domain)) { 765 765 _savePath->setLabel("None"); -
gui/launcher.cpp
26 26 #include "base/version.h" 27 27 28 28 #include "common/config-manager.h" 29 #include "common/config-file.h" 29 30 #include "common/events.h" 30 31 #include "common/fs.h" 31 32 #include "common/util.h" … … 147 148 int labelWidth = g_gui.evaluator()->getVar("tabPopupsLabelW"); 148 149 149 150 // GAME: Path to game data (r/o), extra data (r/o), and save data (r/w) 150 String gamePath(ConfMan.get ("path", _domain));151 String extraPath(ConfMan.get ("extrapath", _domain));152 String savePath(ConfMan.get ("savepath", _domain));151 String gamePath(ConfMan.getKey("path", _domain)); 152 String extraPath(ConfMan.getKey("extrapath", _domain)); 153 String savePath(ConfMan.getKey("savepath", _domain)); 153 154 154 155 // GAME: Determine the description string 155 String description(ConfMan.get ("description", domain));156 String description(ConfMan.getKey("description", domain)); 156 157 if (description.empty() && !desc.empty()) { 157 158 description = desc; 158 159 } … … 309 310 // TODO: game path 310 311 311 312 const Common::LanguageDescription *l = Common::g_languages; 312 const Common::Language lang = Common::parseLanguage(ConfMan.get ("language", _domain));313 const Common::Language lang = Common::parseLanguage(ConfMan.getKey("language", _domain)); 313 314 314 315 sel = 0; 315 316 if (ConfMan.hasKey("language", _domain)) { … … 322 323 323 324 324 325 const Common::PlatformDescription *p = Common::g_platforms; 325 const Common::Platform platform = Common::parsePlatform(ConfMan.get ("platform", _domain));326 const Common::Platform platform = Common::parsePlatform(ConfMan.getKey("platform", _domain)); 326 327 sel = 0; 327 328 for (i = 0; p->code; ++p, ++i) { 328 329 if (platform == p->id) … … 449 450 // Write back changes made to config object 450 451 String newDomain(_domainWidget->getEditString()); 451 452 if (newDomain != _domain) { 452 if (newDomain.empty() || ConfMan.hasGame Domain(newDomain)) {453 if (newDomain.empty() || ConfMan.hasGameSection(newDomain)) { 453 454 MessageDialog alert("This game ID is already taken. Please choose another one."); 454 455 alert.runModal(); 455 456 return; 456 457 } 457 ConfMan.renameGame Domain(_domain, newDomain);458 ConfMan.renameGameSection(_domain, newDomain); 458 459 _domain = newDomain; 459 460 } 460 461 } … … 517 518 updateListing(); 518 519 519 520 // Restore last selection 520 String last(ConfMan.get ("lastselectedgame", ConfigManager::kApplicationDomain));521 String last(ConfMan.getKey("lastselectedgame", ConfigManager::kApplicationSection)); 521 522 selectGame(last); 522 523 523 524 // En-/disable the buttons depending on the list selection … … 548 549 // Clear the active domain, in case we return to the dialog from a 549 550 // failure to launch a game. Otherwise, pressing ESC will attempt to 550 551 // re-launch the same game again. 551 ConfMan.setActive Domain("");552 ConfMan.setActiveSection(""); 552 553 Dialog::open(); 553 554 554 555 updateButtons(); … … 558 559 // Save last selection 559 560 const int sel = _list->getSelected(); 560 561 if (sel >= 0) 561 ConfMan.set("lastselectedgame", _domains[sel], ConfigManager::kApplication Domain);562 ConfMan.set("lastselectedgame", _domains[sel], ConfigManager::kApplicationSection); 562 563 else 563 ConfMan.removeKey("lastselectedgame", ConfigManager::kApplication Domain);564 ConfMan.removeKey("lastselectedgame", ConfigManager::kApplicationSection); 564 565 565 566 ConfMan.flushToDisk(); 566 567 Dialog::close(); … … 571 572 572 573 // Retrieve a list of all games defined in the config file 573 574 _domains.clear(); 574 const ConfigManager::DomainMap &domains = ConfMan.getGameDomains(); 575 ConfigManager::DomainMap::const_iterator iter; 576 for (iter = domains.begin(); iter != domains.end(); ++iter) { 575 const Common::ConfigManager::SectionRefList §ions = ConfMan.getGameSections(); 576 Common::ConfigManager::SectionRefList::const_iterator iter; 577 for (iter = sections.begin(); iter != sections.end(); ++iter) { 578 Common::ConfigFile::Section section = *(*iter); 577 579 #ifdef __DS__ 578 580 // DS port uses an extra section called 'ds'. This prevents the section from being 579 581 // detected as a game. 580 if ( iter->_key== "ds") {582 if ((*iter)->name == "ds") { 581 583 continue; 582 584 } 583 585 #endif 586 587 String gameid(section.getKey("gameid")->value); 588 String description(section.getKey("description")->value); 584 589 585 String gameid(iter->_value.get("gameid"));586 String description(iter->_value.get("description"));587 588 590 if (gameid.empty()) 589 gameid = iter->_key;591 gameid = section.name; 590 592 if (description.empty()) { 591 593 GameDescriptor g = EngineMan.findGame(gameid); 592 594 if (g.contains("description")) … … 594 596 } 595 597 596 598 if (description.empty()) 597 description = "Unknown (target " + iter->_key+ ", gameid " + gameid + ")";599 description = "Unknown (target " + section.name + ", gameid " + gameid + ")"; 598 600 599 601 if (!gameid.empty() && !description.empty()) { 600 602 // Insert the game into the launcher list … … 603 605 while (pos < size && (scumm_stricmp(description.c_str(), l[pos].c_str()) > 0)) 604 606 pos++; 605 607 l.insert_at(pos, description); 606 _domains.insert_at(pos, iter->_key);608 _domains.insert_at(pos, section.name); 607 609 } 608 610 } 609 611 … … 700 702 draw(); 701 703 } else { 702 704 // User aborted, remove the the new domain again 703 ConfMan.removeGame Domain(domain);705 ConfMan.removeGameSection(domain); 704 706 } 705 707 706 708 } … … 719 721 domain = result.gameid(); 720 722 721 723 assert(!domain.empty()); 722 if (ConfMan.hasGame Domain(domain)) {724 if (ConfMan.hasGameSection(domain)) { 723 725 int suffixN = 1; 724 726 char suffix[16]; 725 727 String gameid(domain); 726 728 727 while (ConfMan.hasGame Domain(domain)) {729 while (ConfMan.hasGameSection(domain)) { 728 730 snprintf(suffix, 16, "-%d", suffixN); 729 731 domain = gameid + suffix; 730 732 suffixN++; … … 732 734 } 733 735 734 736 // Add the name domain 735 ConfMan.addGame Domain(domain);737 ConfMan.addGameSection(domain); 736 738 737 739 // Copy all non-empty key/value pairs into the new domain 738 740 for (GameDescriptor::const_iterator iter = result.begin(); iter != result.end(); ++iter) { … … 759 761 if (alert.runModal() == GUI::kMessageOK) { 760 762 // Remove the currently selected game from the list 761 763 assert(item >= 0); 762 ConfMan.removeGame Domain(_domains[item]);764 ConfMan.removeGameSection(_domains[item]); 763 765 764 766 // Write config to disk 765 767 ConfMan.flushToDisk(); … … 778 780 // This is useful because e.g. MonkeyVGA needs Adlib music to have decent 779 781 // music support etc. 780 782 assert(item >= 0); 781 String gameId(ConfMan.get ("gameid", _domains[item]));783 String gameId(ConfMan.getKey("gameid", _domains[item])); 782 784 if (gameId.empty()) 783 785 gameId = _domains[item]; 784 786 EditGameDialog editDialog(_domains[item], EngineMan.findGame(gameId).description()); … … 832 834 case kListItemDoubleClickedCmd: 833 835 // Print out what was selected 834 836 assert(item >= 0); 835 ConfMan.setActive Domain(_domains[item]);837 ConfMan.setActiveSection(_domains[item]); 836 838 close(); 837 839 break; 838 840 case kListItemRemovalRequestCmd: … … 842 844 updateButtons(); 843 845 break; 844 846 case kQuitCmd: 845 ConfMan.setActive Domain("");847 ConfMan.setActiveSection(""); 846 848 setResult(-1); 847 849 close(); 848 850 break; -
engines/engine.cpp
52 52 _timer(_system->getTimerManager()), 53 53 _eventMan(_system->getEventManager()), 54 54 _saveFileMan(_system->getSavefileManager()), 55 _targetName(ConfMan.getActive DomainName()),55 _targetName(ConfMan.getActiveSectionName()), 56 56 _gameDataPath(ConfMan.get("path")), 57 57 _pauseLevel(0) { 58 58 … … 77 77 } 78 78 79 79 void Engine::initCommonGFX(bool defaultTo1XScaler) { 80 const Common::Config Manager::Domain *transientDomain = ConfMan.getDomain(Common::ConfigManager::kTransientDomain);81 const Common::Config Manager::Domain *gameDomain = ConfMan.getActiveDomain();80 const Common::ConfigFile::Section *transientSection = ConfMan.getSection(Common::ConfigManager::kTransientSection); 81 const Common::ConfigFile::Section *gameSection = ConfMan.getActiveSection(); 82 82 83 assert(transient Domain);83 assert(transientSection); 84 84 85 85 const bool useDefaultGraphicsMode = 86 !transient Domain->contains("gfx_mode") &&86 !transientSection->hasKey("gfx_mode") && 87 87 ( 88 !game Domain ||89 !game Domain->contains("gfx_mode") ||90 !scumm_stricmp(game Domain->get("gfx_mode").c_str(), "normal") ||91 !scumm_stricmp(game Domain->get("gfx_mode").c_str(), "default")88 !gameSection || 89 !gameSection->hasKey("gfx_mode") || 90 !scumm_stricmp(gameSection->getKey("gfx_mode")->value.c_str(), "normal") || 91 !scumm_stricmp(gameSection->getKey("gfx_mode")->value.c_str(), "default") 92 92 ); 93 93 94 94 // See if the game should default to 1x scaler … … 112 112 // we get here. Hence we only do something 113 113 114 114 // (De)activate aspect-ratio correction as determined by the config settings 115 if (game Domain && gameDomain->contains("aspect_ratio"))115 if (gameSection && gameSection->hasKey("aspect_ratio")) 116 116 _system->setFeatureState(OSystem::kFeatureAspectRatioCorrection, ConfMan.getBool("aspect_ratio")); 117 117 118 118 // (De)activate fullscreen mode as determined by the config settings 119 if (game Domain && gameDomain->contains("fullscreen"))119 if (gameSection && gameSection->hasKey("fullscreen")) 120 120 _system->setFeatureState(OSystem::kFeatureFullscreenMode, ConfMan.getBool("fullscreen")); 121 121 } 122 122 -
common/config-manager.h
27 27 #define COMMON_CONFIG_MANAGER_H 28 28 29 29 #include "common/array.h" 30 //#include "common/config-file.h"30 #include "common/config-file.h" 31 31 #include "common/hashmap.h" 32 32 #include "common/singleton.h" 33 33 #include "common/str.h" … … 46 46 * which sends out notifications to interested parties whenever the value 47 47 * of some specific (or any) configuration key changes. 48 48 */ 49 class ConfigManager : public Singleton<ConfigManager> {49 class ConfigManager : public Singleton<ConfigManager>, public ConfigFile { 50 50 51 51 public: 52 52 53 class Domain : public StringMap {54 private:55 StringMap _keyValueComments;56 String _domainComment;57 58 public:59 const String &get(const String &key) const;60 61 void setDomainComment(const String &comment);62 const String &getDomainComment() const;63 64 void setKVComment(const String &key, const String &comment);65 const String &getKVComment(const String &key) const;66 bool hasKVComment(const String &key) const;67 };68 69 typedef HashMap<String, Domain, IgnoreCase_Hash, IgnoreCase_EqualTo> DomainMap;70 71 53 #if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__)) 72 /** The name of the application domain (normally 'scummvm'). */73 static const String kApplication Domain;54 /** The name of the application section (normally 'scummvm'). */ 55 static const String kApplicationSection; 74 56 75 /** The transient (pseudo) domain. */76 static const String kTransient Domain;57 /** The transient (pseudo) section. */ 58 static const String kTransientSection; 77 59 #else 78 static const char *kApplication Domain;79 static const char *kTransient Domain;60 static const char *kApplicationSection; 61 static const char *kTransientSection; 80 62 81 const String _emptyString;82 63 #endif 64 65 typedef List<Section*> SectionRefList; 83 66 84 67 void loadDefaultConfigFile(); 85 68 void loadConfigFile(const String &filename); 86 69 87 70 /** 88 * Retrieve the config domain with the given name.89 * @param domName the name of the domain to retrieve90 * @return pointer to the domain, or 0 if the domain doesn't exist.71 * Retrieve the config section with the given name. 72 * @param secName the name of the section to retrieve 73 * @return pointer to the section, or 0 if the section doesn't exist. 91 74 */ 92 Domain * getDomain(const String &domName);93 const Domain * getDomain(const String &domName) const;75 Section * getSection(const String &secName); 76 const Section * getSection(const String &secName) const; 94 77 95 78 96 79 // 97 // Generic access methods: No domain specified, use the values from the98 // various domains in the order of their priority.80 // Generic access methods: No section specified, use the values from the 81 // various sections in the order of their priority. 99 82 // 100 83 101 84 bool hasKey(const String &key) const; 102 85 const String & get(const String &key) const; 103 86 void set(const String &key, const String &value); 104 87 const String & getKey(const String &key) const; 105 88 #if 1 106 89 // 107 // Domain specific access methods: Acces *one specific* domain and modify it.90 // Section specific access methods: Acces *one specific* section and modify it. 108 91 // TODO: I'd like to get rid of most of those if possible, or at least reduce 109 // their usage, by using get Domain as often as possible. For example in the92 // their usage, by using getSection as often as possible. For example in the 110 93 // options dialog code... 111 94 // 112 95 113 bool hasKey(const String &key, const String & domName) const;114 const String & get (const String &key, const String &domName) const;115 void set(const String &key, const String &value, const String & domName);116 117 void removeKey(const String &key, const String &domName);96 bool hasKey(const String &key, const String &secName) const; 97 const String & getKey(const String &key, const String &secName) const; 98 void set(const String &key, const String &value, const String &secName); 99 void removeKey(const String &key, const String &secName); 100 118 101 #endif 119 102 120 103 // 121 104 // Some additional convenience accessors. 122 105 // 123 int getInt(const String &key, const String & domName = String::emptyString) const;124 bool getBool(const String &key, const String & domName = String::emptyString) const;125 void setInt(const String &key, int value, const String & domName = String::emptyString);126 void setBool(const String &key, bool value, const String & domName = String::emptyString);106 int getInt(const String &key, const String &secName = String::emptyString) const; 107 bool getBool(const String &key, const String &secName = String::emptyString) const; 108 void setInt(const String &key, int value, const String &secName = String::emptyString); 109 void setBool(const String &key, bool value, const String &secName = String::emptyString); 127 110 128 111 129 112 void registerDefault(const String &key, const String &value); … … 133 116 134 117 void flushToDisk(); 135 118 136 void setActive Domain(const String &domName);137 Domain * getActiveDomain() { return _activeDomain; }138 const Domain * getActiveDomain() const { return _activeDomain; }139 const String & getActive DomainName() const { return _activeDomainName; }119 void setActiveSection(const String &secName); 120 Section * getActiveSection() { return _activeSection; } 121 const Section * getActiveSection() const { return _activeSection; } 122 const String & getActiveSectionName() const { return _activeSectionName; } 140 123 141 void addGame Domain(const String &domName);142 void removeGame Domain(const String &domName);143 void renameGame Domain(const String &oldName, const String &newName);144 bool hasGame Domain(const String &domName) const;145 const DomainMap & getGameDomains() const { return _gameDomains; }124 void addGameSection(const String &secName); 125 void removeGameSection(const String &secName); 126 void renameGameSection(const String &oldName, const String &newName); 127 bool hasGameSection(const String &secName) const; 128 const SectionRefList &getGameSections() const { return _gameSections; } 146 129 147 130 /* 148 131 TODO: Callback/change notification system … … 157 140 ConfigManager(); 158 141 159 142 void loadFile(const String &filename); 160 void write Domain(WriteStream &stream, const String &name, const Domain &domain);143 void writeSection(WriteStream &stream, const String &name, const Section §ion); 161 144 162 Domain _transientDomain;163 DomainMap _gameDomains;164 Domain _appDomain;165 Domain _defaultsDomain;145 Section _transientSection; 146 SectionRefList _gameSections; 147 Section *_appSection; 148 Section _defaultsSection; 166 149 167 StringList _domainSaveOrder; 150 String _activeSectionName; 151 Section *_activeSection; 168 152 169 String _activeDomainName;170 Domain * _activeDomain;171 172 153 String _filename; 173 154 }; 174 155 -
common/config-file.h
26 26 #ifndef COMMON_CONFIG_FILE_H 27 27 #define COMMON_CONFIG_FILE_H 28 28 29 #include "common/config-manager.h"30 29 #include "common/list.h" 31 30 #include "common/str.h" 32 31 #include "common/stream.h" 32 #include "common/hash-str.h" 33 33 34 34 namespace Common { 35 35 … … 53 53 */ 54 54 class ConfigFile { 55 55 public: 56 typedef HashMap<String, bool, IgnoreCase_Hash, IgnoreCase_EqualTo> StringSet; 57 56 enum{ 57 kSectionChanged, 58 kSectionAdded, 59 kSectionRemoved 60 }; 61 62 63 class Observer{ 64 public: 65 virtual void configFileChanged(int event, const String §ion, const String &key) = 0; 66 virtual ~Observer(); 67 }; 68 /** A section in a config file. I.e. corresponds to something like this: 69 * [mySection] 70 * key=value 71 * 72 * Comments are also stored, to keep users happy who like editing their 73 * config files manually. 74 */ 75 76 58 77 struct KeyValue { 59 78 String key; 60 79 String value; 61 80 String comment; 62 81 }; 63 82 64 83 typedef List<KeyValue> SectionKeyList; 65 84 66 85 /** A section in a config file. I.e. corresponds to something like this: 67 86 * [mySection] 68 87 * key=value … … 74 93 String name; 75 94 List<KeyValue> keys; 76 95 String comment; 77 96 97 void clear() { keys.clear(); } 78 98 bool hasKey(const String &key) const; 79 99 const KeyValue* getKey(const String &key) const; 80 100 void setKey(const String &key, const String &value); 81 101 void removeKey(const String &key); 82 102 const SectionKeyList getKeys() const { return keys; } 83 103 }; 84 104 85 105 typedef List<Section> SectionList; 86 106 87 107 public: 88 108 ConfigFile(); 89 ~ConfigFile();109 virtual ~ConfigFile(); 90 110 111 static const String _emptyString; 91 112 // TODO: Maybe add a copy constructor etc.? 92 113 93 114 /** … … 100 121 101 122 /** Reset everything stored in this config file. */ 102 123 void clear(); 103 124 104 125 bool loadFromFile(const String &filename); 105 126 bool loadFromSaveFile(const char *filename); 106 127 bool loadFromStream(SeekableReadStream &stream); 107 128 bool saveToFile(const String &filename); 108 129 bool saveToSaveFile(const char *filename); 109 130 bool saveToStream(WriteStream &stream); 110 131 void writeSection(WriteStream &stream, const Section §ion); 132 133 void addSection(const String §ion); 111 134 bool hasSection(const String §ion) const; 112 135 void removeSection(const String §ion); 113 136 void renameSection(const String &oldName, const String &newName); 114 137 const SectionKeyList getKeys(const String §ion) const; 138 115 139 bool hasKey(const String &key, const String §ion) const; 116 bool getKey(const String &key, const String §ion, String &value) const; 140 virtual const String &getKey(const String &key, const String §ion) const; 141 virtual bool getKey(const String &key, const String §ion, String &value) const; 117 142 void setKey(const String &key, const String §ion, const String &value); 118 143 void removeKey(const String &key, const String §ion); 119 144 120 const SectionList getSections() const { return _sections; }121 const SectionKeyList getKeys(const String §ion) const;145 void registerObserver(Observer *ob); 146 void notifyObservers(int event, const String §ion, const String &key); 122 147 123 void listSections(StringSet &set); 124 void listKeyValues(StringMap &kv); 125 126 private: 127 SectionList _sections; 128 148 protected: 149 SectionList _sections; 129 150 Section *getSection(const String §ion); 130 151 const Section *getSection(const String §ion) const; 152 List<Observer*> _observers; 153 154 131 155 }; 132 156 133 157 /* -
common/config-manager.cpp
66 66 67 67 #if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__)) 68 68 69 const String ConfigManager::kApplication Domain("scummvm");70 const String ConfigManager::kTransient Domain("__TRANSIENT");69 const String ConfigManager::kApplicationSection("scummvm"); 70 const String ConfigManager::kTransientSection("__TRANSIENT"); 71 71 72 72 #else 73 73 74 const char *ConfigManager::kApplication Domain = "scummvm";75 const char *ConfigManager::kTransient Domain = "__TRANSIENT";74 const char *ConfigManager::kApplicationSection = "scummvm"; 75 const char *ConfigManager::kTransientSection = "__TRANSIENT"; 76 76 77 77 #endif 78 78 … … 80 80 81 81 82 82 ConfigManager::ConfigManager() 83 : _active Domain(0){83 : _activeSection(0){ 84 84 } 85 86 87 85 void ConfigManager::loadDefaultConfigFile() { 88 86 char configFile[MAXPATHLEN]; 89 87 // GP2X is Linux based but Home dir can be read only so do not use it and put the config in the executable dir. 90 88 // On the iPhone, the home dir of the user when you launch the app from the Springboard, is /. Which we don't want. 91 #if defined(UNIX) && !defined(GP2X) && !defined(IPHONE)89 #if defined(UNIX) || defined(MACOSX) && !defined(GP2X) && !defined(IPHONE) 92 90 const char *home = getenv("HOME"); 93 91 if (home != NULL && strlen(home) < MAXPATHLEN) 94 92 snprintf(configFile, MAXPATHLEN, "%s/%s", home, DEFAULT_CONFIG_FILE); … … 160 158 } 161 159 162 160 void ConfigManager::loadConfigFile(const String &filename) { 163 _appDomain.clear(); 164 _gameDomains.clear(); 165 _transientDomain.clear(); 161 162 if(_appSection) 163 _appSection->keys.clear(); 164 _gameSections.clear(); 165 _transientSection.keys.clear(); 166 166 167 167 _filename = filename; 168 _domainSaveOrder.clear(); 169 loadFile(_filename); 168 loadFromFile(filename); 169 170 if(!hasSection(kApplicationSection)) 171 addSection(kApplicationSection); 172 _appSection = ConfigFile::getSection(kApplicationSection); 173 174 SectionList::const_iterator iter; 175 for(iter = _sections.begin(); iter != _sections.end(); ++iter){ 176 if(iter->name != kApplicationSection) 177 _gameSections.push_back(ConfigFile::getSection(iter->name)); 178 } 179 170 180 printf("Using configuration file: %s\n", _filename.c_str()); 171 181 } 172 182 173 void ConfigManager::loadFile(const String &filename) {174 File cfg_file;175 183 176 if (!cfg_file.open(filename)) {177 printf("Creating configuration file: %s\n", filename.c_str());178 } else {179 char buf[MAXLINELEN];180 String domain;181 String comment;182 int lineno = 0;183 184 // TODO: Detect if a domain occurs multiple times (or likewise, if185 // a key occurs multiple times inside one domain).186 187 while (!cfg_file.eof()) {188 lineno++;189 if (!cfg_file.readLine(buf, MAXLINELEN))190 break;191 192 if (buf[0] == '#') {193 // Accumulate comments here. Once we encounter either the start194 // of a new domain, or a key-value-pair, we associate the value195 // of the 'comment' variable with that entity.196 comment += buf;197 comment += '\n';198 } else if (buf[0] == '[') {199 // It's a new domain which begins here.200 char *p = buf + 1;201 // Get the domain name, and check whether it's valid (that202 // is, verify that it only consists of alphanumerics,203 // dashes and underscores).204 while (*p && (isalnum(*p) || *p == '-' || *p == '_'))205 p++;206 207 switch (*p) {208 case '\0':209 error("Config file buggy: missing ] in line %d", lineno);210 break;211 case ']':212 *p = 0;213 domain = buf + 1;214 break;215 default:216 error("Config file buggy: Invalid character '%c' occured in domain name in line %d", *p, lineno);217 }218 219 // Store domain comment220 if (domain == kApplicationDomain) {221 _appDomain.setDomainComment(comment);222 } else {223 _gameDomains[domain].setDomainComment(comment);224 }225 comment.clear();226 227 _domainSaveOrder.push_back(domain);228 } else {229 // Skip leading & trailing whitespaces230 char *t = rtrim(ltrim(buf));231 232 // Skip empty lines233 if (*t == 0)234 continue;235 236 // If no domain has been set, this config file is invalid!237 if (domain.empty()) {238 error("Config file buggy: Key/value pair found outside a domain in line %d", lineno);239 }240 241 // Split string at '=' into 'key' and 'value'.242 char *p = strchr(t, '=');243 if (!p)244 error("Config file buggy: Junk found in line line %d: '%s'", lineno, t);245 *p = 0;246 String key = rtrim(t);247 String value = ltrim(p + 1);248 set(key, value, domain);249 250 // Store comment251 if (domain == kApplicationDomain) {252 _appDomain.setKVComment(key, comment);253 } else {254 _gameDomains[domain].setKVComment(key, comment);255 }256 comment.clear();257 }258 }259 }260 }261 262 184 void ConfigManager::flushToDisk() { 263 #ifndef __DC__ 264 File cfg_file; 265 266 // TODO 267 // if (!willwrite) 268 // return; 269 270 if (!cfg_file.open(_filename, File::kFileWriteMode)) { 271 warning("Unable to write configuration file: %s", _filename.c_str()); 272 } else { 273 // First write the domains in _domainSaveOrder, in that order. 274 // Note: It's possible for _domainSaveOrder to list domains which 275 // are not present anymore. 276 StringList::const_iterator i; 277 for (i = _domainSaveOrder.begin(); i != _domainSaveOrder.end(); ++i) { 278 if (kApplicationDomain == *i) { 279 writeDomain(cfg_file, *i, _appDomain); 280 } else if (_gameDomains.contains(*i)) { 281 writeDomain(cfg_file, *i, _gameDomains[*i]); 282 } 283 } 284 285 DomainMap::const_iterator d; 286 287 288 // Now write the domains which haven't been written yet 289 if (find(_domainSaveOrder.begin(), _domainSaveOrder.end(), kApplicationDomain) == _domainSaveOrder.end()) 290 writeDomain(cfg_file, kApplicationDomain, _appDomain); 291 for (d = _gameDomains.begin(); d != _gameDomains.end(); ++d) { 292 if (find(_domainSaveOrder.begin(), _domainSaveOrder.end(), d->_key) == _domainSaveOrder.end()) 293 writeDomain(cfg_file, d->_key, d->_value); 294 } 295 } 296 #endif // !__DC__ 185 saveToFile(_filename); 297 186 } 298 187 299 void ConfigManager::writeDomain(WriteStream &stream, const String &name, const Domain &domain) {300 if (domain.empty())301 return; // Don't bother writing empty domains.302 188 303 String comment; 189 #pragma mark - 304 190 305 // Write domain comment (if any)306 comment = domain.getDomainComment();307 if (!comment.empty())308 stream.writeString(comment);309 191 310 // Write domain start 311 stream.writeByte('['); 312 stream.writeString(name); 313 stream.writeByte(']'); 314 stream.writeByte('\n'); 192 const ConfigManager::Section *ConfigManager::getSection(const String &secName) const { 193 assert(!secName.empty()); 194 assert(isValidDomainName(secName)); 315 195 316 // Write all key/value pairs in this domain, including comments 317 Domain::const_iterator x; 318 for (x = domain.begin(); x != domain.end(); ++x) { 319 if (!x->_value.empty()) { 320 // Write comment (if any) 321 if (domain.hasKVComment(x->_key)) { 322 comment = domain.getKVComment(x->_key); 323 stream.writeString(comment); 324 } 325 // Write the key/value pair 326 stream.writeString(x->_key); 327 stream.writeByte('='); 328 stream.writeString(x->_value); 329 stream.writeByte('\n'); 196 if (secName == kTransientSection) 197 return &_transientSection; 198 if (secName == kApplicationSection) 199 return _appSection; 200 for (SectionRefList::iterator i = _gameSections.begin(); i != _gameSections.end(); ++i) { 201 if (!scumm_stricmp(secName.c_str(), (*i)->name.c_str())) { 202 return (*i); 330 203 } 331 204 } 332 stream.writeByte('\n');333 }334 205 335 336 #pragma mark -337 338 339 const ConfigManager::Domain *ConfigManager::getDomain(const String &domName) const {340 assert(!domName.empty());341 assert(isValidDomainName(domName));342 343 if (domName == kTransientDomain)344 return &_transientDomain;345 if (domName == kApplicationDomain)346 return &_appDomain;347 if (_gameDomains.contains(domName))348 return &_gameDomains[domName];349 350 206 return 0; 351 207 } 352 208 353 ConfigManager::Domain *ConfigManager::getDomain(const String &domName) { 354 assert(!domName.empty()); 355 assert(isValidDomainName(domName)); 209 ConfigManager::Section *ConfigManager::getSection(const String &secName) { 210 assert(!secName.empty()); 211 assert(isValidDomainName(secName)); 212 213 if (secName == kTransientSection) 214 return &_transientSection; 215 if (secName == kApplicationSection) 216 return _appSection; 217 for (SectionRefList::iterator i = _gameSections.begin(); i != _gameSections.end(); ++i) { 218 if (!scumm_stricmp(secName.c_str(), (*i)->name.c_str())) { 219 return (*i); 220 } 221 } 356 222 357 if (domName == kTransientDomain)358 return &_transientDomain;359 if (domName == kApplicationDomain)360 return &_appDomain;361 if (_gameDomains.contains(domName))362 return &_gameDomains[domName];363 364 223 return 0; 365 224 } 366 225 367 368 226 #pragma mark - 369 227 370 228 … … 375 233 // 3) the application domain. 376 234 // The defaults domain is explicitly *not* checked. 377 235 378 if (_transient Domain.contains(key))236 if (_transientSection.hasKey(key)) 379 237 return true; 380 238 381 if (_active Domain && _activeDomain->contains(key))239 if (_activeSection && _activeSection->hasKey(key)) 382 240 return true; 383 241 384 if (_app Domain.contains(key))242 if (_appSection && _appSection->hasKey(key)) 385 243 return true; 386 244 387 245 return false; 388 246 } 389 390 bool ConfigManager::hasKey(const String &key, const String & domName) const {391 // FIXME: For now we continue to allow empty domName to indicate392 // "use 'default' domain". This is mainly needed for the SCUMM ConfigDialog247 248 bool ConfigManager::hasKey(const String &key, const String &secName) const { 249 // FIXME: For now we continue to allow empty secName to indicate 250 // "use 'default' section". This is mainly needed for the SCUMM ConfigDialog 393 251 // and should be removed ASAP. 394 if ( domName.empty())252 if (secName.empty()) 395 253 return hasKey(key); 396 254 397 const Domain *domain = getDomain(domName);255 const Section *section = getSection(secName); 398 256 399 if (! domain)257 if (!section) 400 258 return false; 401 return domain->contains(key);259 return section->hasKey(key); 402 260 } 403 261 404 void ConfigManager::removeKey(const String &key, const String & domName) {405 Domain *domain = getDomain(domName);262 void ConfigManager::removeKey(const String &key, const String &secName) { 263 Section *section = getSection(secName); 406 264 407 if (! domain)265 if (!section) 408 266 error("ConfigManager::removeKey(%s, %s) called on non-existent domain", 409 key.c_str(), domName.c_str());267 key.c_str(), secName.c_str()); 410 268 411 domain->erase(key);269 section->removeKey(key); 412 270 } 413 271 414 272 415 273 #pragma mark - 274 416 275 417 418 276 const String & ConfigManager::get(const String &key) const { 419 if (_transientDomain.contains(key)) 420 return _transientDomain[key]; 421 else if (_activeDomain && _activeDomain->contains(key)) 422 return (*_activeDomain)[key]; 423 else if (_appDomain.contains(key)) 424 return _appDomain[key]; 425 else if (_defaultsDomain.contains(key)) 426 return _defaultsDomain[key]; 277 return getKey(key); 278 } 427 279 280 const String &ConfigManager::getKey(const String &key) const { 281 if (_transientSection.hasKey(key)) 282 return _transientSection.getKey(key)->value; 283 else if (_activeSection && _activeSection->hasKey(key)) 284 return (*_activeSection).getKey(key)->value; 285 else if (_appSection && _appSection->hasKey(key)) 286 return _appSection->getKey(key)->value; 287 else if (_defaultsSection.hasKey(key)) 288 return _defaultsSection.getKey(key)->value; 289 428 290 #if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__)) 429 291 return String::emptyString; 430 292 #else 431 return ConfMan._emptyString;293 return _emptyString; 432 294 #endif 433 295 } 434 296 435 const String & ConfigManager::get (const String &key, const String &domName) const {297 const String & ConfigManager::getKey(const String &key, const String &secName) const { 436 298 // FIXME: For now we continue to allow empty domName to indicate 437 299 // "use 'default' domain". This is mainly needed for the SCUMM ConfigDialog 438 300 // and should be removed ASAP. 439 if ( domName.empty())301 if (secName.empty()) 440 302 return get(key); 441 442 const Domain *domain = getDomain(domName);443 444 if (! domain)303 304 const Section *section = getSection(secName); 305 306 if (!section) 445 307 error("ConfigManager::get(%s,%s) called on non-existent domain", 446 key.c_str(), domName.c_str()); 308 key.c_str(), secName.c_str()); 309 447 310 448 if ( domain->contains(key))449 return (*domain)[key];311 if (section->hasKey(key)) 312 return section->getKey(key)->value; 450 313 451 return _defaultsDomain.get(key);452 453 if (!domain->contains(key)) {314 if(_defaultsSection.hasKey(key)) 315 return _defaultsSection.getKey(key)->value; 316 454 317 #if 1 455 318 #if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__)) 456 return String::emptyString;319 return String::emptyString; 457 320 #else 458 return ConfMan._emptyString;321 return _emptyString; 459 322 #endif 460 323 #else 461 324 error("ConfigManager::get(%s,%s) called on non-existent key", 462 key.c_str(), domName.c_str());325 key.c_str(), secName.c_str()); 463 326 #endif 464 }465 466 return (*domain)[key];467 327 } 468 328 469 329 int ConfigManager::getInt(const String &key, const String &domName) const { 470 String value(get (key, domName));330 String value(getKey(key, domName)); 471 331 char *errpos; 472 332 473 333 // For now, be tolerant against missing config keys. Strictly spoken, it is … … 488 348 } 489 349 490 350 bool ConfigManager::getBool(const String &key, const String &domName) const { 491 String value(get (key, domName));351 String value(getKey(key, domName)); 492 352 493 353 if ((value == "true") || (value == "yes") || (value == "1")) 494 354 return true; … … 505 365 506 366 void ConfigManager::set(const String &key, const String &value) { 507 367 // Remove the transient domain value, if any. 508 _transient Domain.erase(key);368 _transientSection.removeKey(key); 509 369 510 370 // Write the new key/value pair into the active domain, resp. into 511 371 // the application domain if no game domain is active. 512 if (_active Domain)513 (*_active Domain)[key] = value;372 if (_activeSection) 373 (*_activeSection).setKey(key, value); 514 374 else 515 _appDomain[key] = value;375 (*_appSection).setKey(key, value); 516 376 } 517 377 518 void ConfigManager::set(const String &key, const String &value, const String & domName) {378 void ConfigManager::set(const String &key, const String &value, const String &secName) { 519 379 // FIXME: For now we continue to allow empty domName to indicate 520 380 // "use 'default' domain". This is mainly needed for the SCUMM ConfigDialog 521 381 // and should be removed ASAP. 522 if ( domName.empty()) {382 if (secName.empty()) { 523 383 set(key, value); 524 384 return; 525 385 } 526 386 527 Domain *domain = getDomain(domName);387 Section *section = getSection(secName); 528 388 529 if (! domain)530 error("ConfigManager::set(%s,%s,%s) called on non-existent domain",531 key.c_str(), value.c_str(), domName.c_str());389 if (!section) 390 error("ConfigManager::set(%s,%s,%s) called on non-existent section", 391 key.c_str(), value.c_str(), secName.c_str()); 532 392 533 (* domain)[key] = value;534 393 (*section).setKey(key,value); 394 535 395 // TODO/FIXME: We used to erase the given key from the transient domain 536 396 // here. Do we still want to do that? 537 397 // It was probably there to simplify the options dialogs code: … … 575 435 576 436 577 437 void ConfigManager::registerDefault(const String &key, const String &value) { 578 _defaults Domain[key] = value;438 _defaultsSection.setKey(key, value); 579 439 } 580 440 581 441 void ConfigManager::registerDefault(const String &key, const char *value) { … … 596 456 #pragma mark - 597 457 598 458 599 void ConfigManager::setActive Domain(const String &domName) {600 if ( domName.empty()) {601 _active Domain = 0;459 void ConfigManager::setActiveSection(const String &secName) { 460 if (secName.empty()) { 461 _activeSection = 0; 602 462 } else { 603 assert(isValidDomainName( domName));604 _active Domain = & _gameDomains[domName];463 assert(isValidDomainName(secName)); 464 _activeSection = getSection(secName); 605 465 } 606 _active DomainName = domName;466 _activeSectionName = secName; 607 467 } 608 468 609 void ConfigManager::addGame Domain(const String &domName) {610 assert(! domName.empty());611 assert(isValidDomainName( domName));612 469 void ConfigManager::addGameSection(const String &secName) { 470 assert(!secName.empty()); 471 assert(isValidDomainName(secName)); 472 613 473 // TODO: Do we want to generate an error/warning if a domain with 614 474 // the given name already exists? 615 475 616 _gameDomains[domName]; 476 addSection(secName); 477 _gameSections.push_back(ConfigFile::getSection(secName)); 617 478 } 618 479 619 void ConfigManager::removeGameDomain(const String &domName) { 620 assert(!domName.empty()); 621 assert(isValidDomainName(domName)); 622 _gameDomains.erase(domName); 480 void ConfigManager::removeGameSection(const String &secName) { 481 assert(!secName.empty()); 482 assert(isValidDomainName(secName)); 483 _gameSections.remove(ConfigFile::getSection(secName)); 484 removeSection(secName); 623 485 } 624 486 625 void ConfigManager::renameGame Domain(const String &oldName, const String &newName) {487 void ConfigManager::renameGameSection(const String &oldName, const String &newName) { 626 488 if (oldName == newName) 627 489 return; 628 490 … … 631 493 assert(isValidDomainName(oldName)); 632 494 assert(isValidDomainName(newName)); 633 495 496 renameSection(oldName, newName); 634 497 // _gameDomains[newName].merge(_gameDomains[oldName]); 635 Domain &oldDom = _gameDomains[oldName];636 Domain &newDom = _gameDomains[newName];637 Domain::const_iterator iter;638 for (iter = oldDom.begin(); iter != oldDom.end(); ++iter)639 newDom[iter->_key] = iter->_value;640 641 _gameDomains.erase(oldName);642 498 } 643 499 644 bool ConfigManager::hasGameDomain(const String &domName) const { 645 assert(!domName.empty()); 646 return isValidDomainName(domName) && _gameDomains.contains(domName); 500 bool ConfigManager::hasGameSection(const String &secName) const { 501 assert(!secName.empty()); 502 if(!isValidDomainName(secName)) 503 return false; 504 505 SectionRefList::const_iterator iter; 506 for(iter = _gameSections.begin(); iter != _gameSections.end(); ++iter){ 507 if(scumm_stricmp(secName.c_str(), (*iter)->name.c_str())) 508 return true; 509 } 510 return false; 647 511 } 648 512 649 513 650 #pragma mark -651 652 653 const String &ConfigManager::Domain::get(const String &key) const {654 const_iterator iter(find(key));655 if (iter != end())656 return iter->_value;657 658 #if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__))659 return String::emptyString;660 #else661 return ConfMan._emptyString;662 #endif663 }664 665 void ConfigManager::Domain::setDomainComment(const String &comment) {666 _domainComment = comment;667 }668 const String &ConfigManager::Domain::getDomainComment() const {669 return _domainComment;670 }671 672 void ConfigManager::Domain::setKVComment(const String &key, const String &comment) {673 _keyValueComments[key] = comment;674 }675 const String &ConfigManager::Domain::getKVComment(const String &key) const {676 return _keyValueComments[key];677 }678 bool ConfigManager::Domain::hasKVComment(const String &key) const {679 return _keyValueComments.contains(key);680 }681 682 514 } // End of namespace Common -
common/config-file.cpp
28 28 #include "common/savefile.h" 29 29 #include "common/system.h" 30 30 #include "common/util.h" 31 31 #include "config-manager.h" 32 32 #define MAXLINELEN 256 33 33 34 34 namespace Common { … … 82 82 KeyValue kv; 83 83 String comment; 84 84 int lineno = 0; 85 85 86 86 // TODO: Detect if a section occurs multiple times (or likewise, if 87 87 // a key occurs multiple times inside one section). 88 88 89 89 while (!stream.eos()) { 90 90 lineno++; 91 91 if (!stream.readLine(buf, MAXLINELEN)) 92 92 break; 93 93 94 94 if (buf[0] == '#') { 95 95 // Accumulate comments here. Once we encounter either the start 96 96 // of a new section, or a key-value-pair, we associate the value … … 115 115 // dashes and underscores). 116 116 while (*p && (isalnum(*p) || *p == '-' || *p == '_')) 117 117 p++; 118 118 119 119 if (*p == '\0') 120 120 error("ConfigFile::loadFromStream: missing ] in line %d", lineno); 121 121 else if (*p != ']') 122 122 error("ConfigFile::loadFromStream: Invalid character '%c' occured in section name in line %d", *p, lineno); 123 123 124 124 *p = 0; 125 125 126 126 // Previous section is finished now, store it. 127 127 if (!section.name.empty()) 128 128 _sections.push_back(section); 129 129 130 130 section.name = buf + 1; 131 131 section.keys.clear(); 132 132 section.comment = comment; 133 133 comment.clear(); 134 134 135 135 assert(isValidName(section.name)); 136 136 } else { 137 137 // Skip leading & trailing whitespaces 138 138 char *t = rtrim(ltrim(buf)); 139 139 140 140 // Skip empty lines 141 141 if (*t == 0) 142 142 continue; 143 143 144 144 // If no section has been set, this config file is invalid! 145 145 if (section.name.empty()) { 146 146 error("ConfigFile::loadFromStream: Key/value pair found outside a section in line %d", lineno); 147 147 } 148 148 149 149 // Split string at '=' into 'key' and 'value'. 150 150 char *p = strchr(t, '='); 151 151 if (!p) 152 152 error("ConfigFile::loadFromStream: Junk found in line line %d: '%s'", lineno, t); 153 153 *p = 0; 154 154 155 155 kv.key = rtrim(t); 156 156 kv.value = ltrim(p + 1); 157 157 kv.comment = comment; 158 158 comment.clear(); 159 159 160 160 assert(isValidName(kv.key)); 161 161 162 162 section.keys.push_back(kv); 163 163 } 164 164 } 165 165 166 166 // Save last section 167 167 if (!section.name.empty()) 168 168 _sections.push_back(section); 169 169 170 170 return (!stream.ioFailed() || stream.eos()); 171 171 } 172 172 … … 191 191 } 192 192 193 193 bool ConfigFile::saveToStream(WriteStream &stream) { 194 for (List<Section>::iterator i = _sections.begin(); i != _sections.end(); ++i) { 195 // Write out the section comment, if any 196 if (! i->comment.empty()) { 197 stream.writeString(i->comment); 194 for (List<Section>::const_iterator i = _sections.begin(); i != _sections.end(); ++i) { 195 writeSection(stream, *i); 196 } 197 198 stream.flush(); 199 return !stream.ioFailed(); 200 } 201 202 void ConfigFile::writeSection(WriteStream &stream, const Section §ion) { 203 204 if(section.keys.empty()) 205 return; 206 207 // Write out the section comment, if any 208 if (! section.comment.empty()) { 209 stream.writeString(section.comment); 210 } 211 212 // Write out the section name 213 stream.writeByte('['); 214 stream.writeString(section.name); 215 stream.writeByte(']'); 216 stream.writeByte('\n'); 217 218 // Write out the key/value pairs 219 for (List<KeyValue>::iterator kv = section.keys.begin(); kv != section.keys.end(); ++kv) { 220 // Write out the comment, if any 221 if (! section.comment.empty()) { 222 stream.writeString(kv->comment); 198 223 } 199 200 // Write out the section name 201 stream.writeByte('['); 202 stream.writeString(i->name); 203 stream.writeByte(']'); 224 // Write out the key/value pair 225 stream.writeString(kv->key); 226 stream.writeByte('='); 227 stream.writeString(kv->value); 204 228 stream.writeByte('\n'); 205 206 // Write out the key/value pairs207 for (List<KeyValue>::iterator kv = i->keys.begin(); kv != i->keys.end(); ++kv) {208 // Write out the comment, if any209 if (! kv->comment.empty()) {210 stream.writeString(kv->comment);211 }212 // Write out the key/value pair213 stream.writeString(kv->key);214 stream.writeByte('=');215 stream.writeString(kv->value);216 stream.writeByte('\n');217 }218 229 } 230 } 231 232 void ConfigFile::addSection(const String &secName) { 233 Section section; 234 section.name = secName; 235 section.keys.clear(); 236 section.comment.clear(); 237 238 _sections.push_back(section); 219 239 220 stream.flush();221 return !stream.ioFailed();222 240 } 223 224 225 241 void ConfigFile::removeSection(const String §ion) { 226 242 assert(isValidName(section)); 227 243 for (List<Section>::iterator i = _sections.begin(); i != _sections.end(); ++i) { … … 231 247 } 232 248 } 233 249 } 234 250 235 251 bool ConfigFile::hasSection(const String §ion) const { 236 252 assert(isValidName(section)); 237 253 const Section *s = getSection(section); 238 254 return s != 0; 239 255 } 240 256 241 257 void ConfigFile::renameSection(const String &oldName, const String &newName) { 242 258 assert(isValidName(oldName)); 243 259 assert(isValidName(newName)); 244 260 245 261 //Section *os = getSection(oldName); 246 262 Section *ns = getSection(newName); 247 263 if (ns) { … … 253 269 // - error out 254 270 // - merge the two sections "oldName" and "newName" 255 271 } 272 256 273 257 258 274 bool ConfigFile::hasKey(const String &key, const String §ion) const { 259 275 assert(isValidName(key)); 260 276 assert(isValidName(section)); 261 277 262 278 const Section *s = getSection(section); 263 279 if (!s) 264 280 return false; … … 268 284 void ConfigFile::removeKey(const String &key, const String §ion) { 269 285 assert(isValidName(key)); 270 286 assert(isValidName(section)); 271 287 272 288 Section *s = getSection(section); 273 289 if (s) 274 290 s->removeKey(key); 275 291 } 276 292 293 const String &ConfigFile::getKey(const String &key, const String §ion) const { 294 assert(isValidName(key)); 295 assert(isValidName(section)); 296 297 const Section *s = getSection(section); 298 if (s){ 299 const KeyValue *kv = s->getKey(key); 300 if (kv) 301 return kv->value; 302 } 303 #if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__)) 304 return String::emptyString; 305 #else 306 return ConfMan._emptyString; 307 #endif 308 } 309 277 310 bool ConfigFile::getKey(const String &key, const String §ion, String &value) const { 278 311 assert(isValidName(key)); 279 312 assert(isValidName(section)); 280 313 281 314 const Section *s = getSection(section); 282 315 if (!s) 283 316 return false; … … 293 326 assert(isValidName(section)); 294 327 // TODO: Verify that value is valid, too. In particular, it shouldn't 295 328 // contain CR or LF... 296 329 297 330 Section *s = getSection(section); 298 331 if (!s) { 299 332 KeyValue newKV; 300 333 newKV.key = key; 301 334 newKV.value = value; 302 335 303 336 Section newSection; 304 337 newSection.name = section; 305 338 newSection.keys.push_back(newKV); 306 339 307 340 _sections.push_back(newSection); 308 341 } else { 309 342 s->setKey(key, value); … … 312 345 313 346 const ConfigFile::SectionKeyList ConfigFile::getKeys(const String §ion) const { 314 347 const Section *s = getSection(section); 315 348 316 349 return s->getKeys(); 317 350 } 318 351 319 352 ConfigFile::Section *ConfigFile::getSection(const String §ion) { 320 353 for (List<Section>::iterator i = _sections.begin(); i != _sections.end(); ++i) { 321 354 if (!scumm_stricmp(section.c_str(), i->name.c_str())) { … … 333 366 } 334 367 return 0; 335 368 } 369 370 void ConfigFile::notifyObservers(int event, const String §ion, const String &key){ 371 List<Observer*>::iterator i; 372 373 for(i=_observers.begin(); i!=_observers.end() ;++i) { 374 (*i)->configFileChanged(event, section, key); 375 } 376 } 377 378 void ConfigFile::registerObserver(Observer *ob){ 379 _observers.push_back(ob); 380 } 336 381 382 383 #pragma mark - 384 337 385 bool ConfigFile::Section::hasKey(const String &key) const { 338 386 return getKey(key) != 0; 339 387 } … … 344 392 return &(*i); 345 393 } 346 394 } 395 347 396 return 0; 348 397 } 349 398 … … 354 403 return; 355 404 } 356 405 } 357 406 358 407 KeyValue newKV; 359 408 newKV.key = key; 360 409 newKV.value = value; … … 368 417 return; 369 418 } 370 419 } 371 } 420 } 372 421 373 422 } // End of namespace Common -
common/system.cpp
135 135 #endif 136 136 137 137 FilesystemFactory *OSystem::getFilesystemFactory() { 138 #if defined(__amigaos4__) || defined(__DC__) || defined(__SYMBIAN32__) || defined(UNIX) || defined(WIN32) || defined(__WII__) || defined(__PSP__) || defined(__DS__) 138 #if defined(__amigaos4__) || defined(__DC__) || defined(__SYMBIAN32__) || defined(UNIX) || defined(WIN32) || defined(__WII__) || defined(__PSP__) || defined(__DS__) || defined(MACOSX) 139 139 // These ports already implement this function, so it should never be called. 140 140 return 0; 141 141 #elif defined(PALMOS_MODE) -
backends/saves/default/default-saves.cpp
271 271 // Work around a bug (#999122) in the original 0.6.1 release of 272 272 // ScummVM, which would insert a bad savepath value into config files. 273 273 if (dir == "None") { 274 ConfMan.removeKey("savepath", ConfMan.getActive DomainName());274 ConfMan.removeKey("savepath", ConfMan.getActiveSectionName()); 275 275 ConfMan.flushToDisk(); 276 276 dir = ConfMan.get("savepath"); 277 277 } -
backends/platform/sdl/sdl.cpp
45 45 */ 46 46 #if defined(__amigaos4__) 47 47 #include "backends/fs/amigaos4/amigaos4-fs-factory.h" 48 #elif defined(UNIX) 48 #elif defined(UNIX) || defined(MACOSX) 49 49 #include "backends/fs/posix/posix-fs-factory.h" 50 50 #elif defined(WIN32) 51 51 #include "backends/fs/windows/windows-fs-factory.h" -
backends/platform/sdl/main.cpp
31 31 32 32 #include "backends/platform/sdl/sdl.h" 33 33 #include "backends/plugins/sdl/sdl-provider.h" 34 #include "base/main.h" 34 #include "base/main.h" 35 35 36 36 #if defined(__SYMBIAN32__) 37 37 #include "SymbianOs.h" -
base/main.cpp
82 82 const EnginePlugin *plugin = 0; 83 83 84 84 // Make sure the gameid is set in the config manager, and that it is lowercase. 85 Common::String gameid(ConfMan.getActive DomainName());85 Common::String gameid(ConfMan.getActiveSectionName()); 86 86 assert(!gameid.empty()); 87 87 if (ConfMan.hasKey("gameid")) 88 88 gameid = ConfMan.get("gameid"); … … 90 90 ConfMan.set("gameid", gameid); 91 91 92 92 // Query the plugins and find one that will handle the specified gameid 93 printf("User picked target '%s' (gameid '%s')...\n", ConfMan.getActive DomainName().c_str(), gameid.c_str());93 printf("User picked target '%s' (gameid '%s')...\n", ConfMan.getActiveSectionName().c_str(), gameid.c_str()); 94 94 printf(" Looking for a plugin supporting this gameid... "); 95 95 GameDescriptor game = EngineMan.findGame(gameid, &plugin); 96 96 … … 118 118 #endif 119 119 && gameDataPath.lastChar() != '\\') { 120 120 gameDataPath += '/'; 121 ConfMan.set("path", gameDataPath, Common::ConfigManager::kTransient Domain);121 ConfMan.set("path", gameDataPath, Common::ConfigManager::kTransientSection); 122 122 } 123 123 124 124 // We add the game "path" to the file search path via File::addDefaultDirectory(), … … 163 163 warning("%s failed to instantiate engine: %s (target '%s', path '%s')", 164 164 plugin->getName(), 165 165 errMsg, 166 ConfMan.getActive DomainName().c_str(),166 ConfMan.getActiveSectionName().c_str(), 167 167 path.c_str() 168 168 ); 169 169 return 0; … … 176 176 if (caption.empty() && !desc.empty()) 177 177 caption = desc; 178 178 if (caption.empty()) 179 caption = ConfMan.getActive DomainName(); // Use the domain (=target) name179 caption = ConfMan.getActiveSectionName(); // Use the domain (=target) name 180 180 if (!caption.empty()) { 181 181 system.setWindowCaption(caption.c_str()); 182 182 } … … 190 190 if (ConfMan.hasKey("extrapath")) 191 191 Common::File::addDefaultDirectoryRecursive(ConfMan.get("extrapath")); 192 192 193 if (ConfMan.hasKey("extrapath", Common::ConfigManager::kApplication Domain))194 Common::File::addDefaultDirectoryRecursive(ConfMan.get ("extrapath", Common::ConfigManager::kApplicationDomain));193 if (ConfMan.hasKey("extrapath", Common::ConfigManager::kApplicationSection)) 194 Common::File::addDefaultDirectoryRecursive(ConfMan.getKey("extrapath", Common::ConfigManager::kApplicationSection)); 195 195 196 196 #ifdef DATA_PATH 197 197 // Add the global DATA_PATH to the directory search list … … 256 256 } 257 257 258 258 // Update the config file 259 ConfMan.set("versioninfo", gScummVMVersion, Common::ConfigManager::kApplication Domain);259 ConfMan.set("versioninfo", gScummVMVersion, Common::ConfigManager::kApplicationSection); 260 260 261 261 262 262 // Load and setup the debuglevel and the debug flags. We do this at the … … 287 287 system.initBackend(); 288 288 289 289 // Unless a game was specified, show the launcher dialog 290 if (0 == ConfMan.getActive Domain()) {290 if (0 == ConfMan.getActiveSection()) { 291 291 launcherDialog(system); 292 292 293 293 // Discard any command line options. Those that affect the graphics 294 294 // mode etc. already have should have been handled by the backend at 295 295 // this point. And the others (like bootparam etc.) should not 296 296 // blindly be passed to the first game launched from the launcher. 297 ConfMan.get Domain(Common::ConfigManager::kTransientDomain)->clear();297 ConfMan.getSection(Common::ConfigManager::kTransientSection)->clear(); 298 298 } 299 299 300 300 // FIXME: We're now looping the launcher. This, of course, doesn't 301 301 // work as well as it should. In theory everything should be destroyed 302 302 // cleanly, so this is now enabled to encourage people to fix bits :) 303 while (0 != ConfMan.getActive Domain()) {303 while (0 != ConfMan.getActiveSection()) { 304 304 // Try to find a plugin which feels responsible for the specified game. 305 305 const EnginePlugin *plugin = detectPlugin(); 306 306 if (plugin) { … … 318 318 319 319 // Discard any command line options. It's unlikely that the user 320 320 // wanted to apply them to *all* games ever launched. 321 ConfMan.get Domain(Common::ConfigManager::kTransientDomain)->clear();321 ConfMan.getSection(Common::ConfigManager::kTransientSection)->clear(); 322 322 323 323 // Clear the active config domain 324 ConfMan.setActive Domain("");324 ConfMan.setActiveSection(""); 325 325 326 326 // PluginManager::instance().unloadPlugins(); 327 327 PluginManager::instance().loadPlugins(); -
base/commandLine.cpp
580 580 "-------------------- ------------------------------------------------------\n"); 581 581 582 582 using namespace Common; 583 const ConfigManager:: DomainMap &domains = ConfMan.getGameDomains();584 ConfigManager:: DomainMap::const_iterator iter;585 for (iter = domains.begin(); iter != domains.end(); ++iter) {586 Common::String name( iter->_key);587 Common::String description( iter->_value.get("description"));583 const ConfigManager::SectionRefList §ions = ConfMan.getGameSections(); 584 ConfigManager::SectionRefList::const_iterator iter; 585 for (iter = sections.begin(); iter != sections.end(); ++iter) { 586 Common::String name((*iter)->name); 587 Common::String description((*iter)->getKey("description")->value); 588 588 589 589 if (description.empty()) { 590 590 // FIXME: At this point, we should check for a "gameid" override … … 607 607 g_system->initBackend(); 608 608 609 609 // Grab the "target" domain, if any 610 const Common::Config Manager::Domain *domain = ConfMan.getDomain(target);610 const Common::ConfigFile::Section *section = ConfMan.getSection(target); 611 611 612 612 // Grab the gameid from the domain resp. use the target as gameid 613 613 Common::String gameid; 614 if ( domain)615 gameid = domain->get("gameid");614 if (section) 615 gameid = section->getKey("gameid")->value; 616 616 if (gameid.empty()) 617 617 gameid = target; 618 618 gameid.toLowercase(); // Normalize it to lower case … … 648 648 // for the given path. It then prints out the result and also checks 649 649 // whether the result agrees with the settings of the target. 650 650 651 const Common::ConfigManager:: DomainMap &domains = ConfMan.getGameDomains();652 Common::ConfigManager:: DomainMap::const_iterator iter = domains.begin();651 const Common::ConfigManager::SectionRefList §ions = ConfMan.getGameSections(); 652 Common::ConfigManager::SectionRefList::const_iterator iter; 653 653 int success = 0, failure = 0; 654 for (iter = domains.begin(); iter != domains.end(); ++iter) {655 Common::String name( iter->_key);656 Common::String gameid( iter->_value.get("gameid"));657 Common::String path( iter->_value.get("path"));654 for (iter = sections.begin(); iter != sections.end(); ++iter) { 655 Common::String name((*iter)->name); 656 Common::String gameid((*iter)->getKey("gameid")->value); 657 Common::String path((*iter)->getKey("path")->value); 658 658 printf("Looking at target '%s', gameid '%s', path '%s' ...\n", 659 659 name.c_str(), gameid.c_str(), path.c_str()); 660 660 if (path.empty()) { … … 705 705 Common::getPlatformCode(x->platform())); 706 706 } 707 707 } 708 int total = domains.size();708 int total = sections.size(); 709 709 printf("Detector test run: %d fail, %d success, %d skipped, out of %d\n", 710 710 failure, success, total - failure - success, total); 711 711 } … … 746 746 // whether there is a gameid matching that name. 747 747 if (!command.empty()) { 748 748 GameDescriptor gd = EngineMan.findGame(command); 749 if (ConfMan.hasGame Domain(command) || !gd.gameid().empty()) {749 if (ConfMan.hasGameSection(command) || !gd.gameid().empty()) { 750 750 bool idCameFromCommandLine = false; 751 751 752 752 // WORKAROUND: Fix for bug #1719463: "DETECTOR: Launching … … 755 755 // We designate gameids which come strictly from command line 756 756 // so AdvancedDetector will not save config file with invalid 757 757 // gameid in case target autoupgrade was performed 758 if (!ConfMan.hasGame Domain(command)) {758 if (!ConfMan.hasGameSection(command)) { 759 759 idCameFromCommandLine = true; 760 760 } 761 761 762 ConfMan.setActive Domain(command);762 ConfMan.setActiveSection(command); 763 763 764 764 if (idCameFromCommandLine) 765 765 ConfMan.set("id_came_from_command_line", "1"); … … 801 801 *c = '_'; 802 802 803 803 // Store it into ConfMan. 804 ConfMan.set(key, value, Common::ConfigManager::kTransient Domain);804 ConfMan.set(key, value, Common::ConfigManager::kTransientSection); 805 805 } 806 806 807 807 return true;