Index: gui/Actions.cpp
===================================================================
--- gui/Actions.cpp	(revision 32664)
+++ gui/Actions.cpp	(working copy)
@@ -25,7 +25,6 @@
 
 #include "gui/Actions.h"
 #include "gui/message.h"
-#include "scumm/scumm.h"
 #include "common/config-manager.h"
 
 #ifdef _WIN32_WCE
@@ -110,7 +109,7 @@
 	current_version = ConfMan.getInt("action_mapping_version", domain());
 	if (current_version != version())
 		return false;
-	tempo = ConfMan.get("action_mapping", domain()).c_str();
+	tempo = ConfMan.getKey("action_mapping", domain()).c_str();
 	if (tempo && strlen(tempo)) {
 		for (i=0; i<size(); i++) {
 			char x[7];
Index: gui/theme.h
===================================================================
--- gui/theme.h	(revision 32664)
+++ gui/theme.h	(working copy)
@@ -30,7 +30,7 @@
 #include "common/str.h"
 #include "common/file.h"
 #include "common/config-file.h"
-
+#include "common/config-manager.h"
 #include "graphics/surface.h"
 #include "graphics/fontman.h"
 
Index: gui/massadd.cpp
===================================================================
--- gui/massadd.cpp	(revision 32664)
+++ gui/massadd.cpp	(working copy)
@@ -89,19 +89,19 @@
 	new ButtonWidget(this, "massadddialog_cancel", "Cancel", kCancelCmd, Common::ASCII_ESCAPE);
 
 	// Build a map from all configured game paths to the targets using them
-	const Common::ConfigManager::DomainMap &domains = ConfMan.getGameDomains();
-	Common::ConfigManager::DomainMap::const_iterator iter;
-	for (iter = domains.begin(); iter != domains.end(); ++iter) {
+	const Common::ConfigManager::SectionRefList &sections = ConfMan.getGameSections();
+	Common::ConfigManager::SectionRefList::const_iterator iter;
+	for (iter = sections.begin(); iter != sections.end(); ++iter) {
 
 #ifdef __DS__
 		// DS port uses an extra section called 'ds'.  This prevents the section from being
 		// detected as a game.
-		if (iter->_key == "ds") {
+		if ((*iter)->name == "ds") {
 			continue;
 		}
 #endif
 
-		Common::String path(iter->_value.get("path"));
+		Common::String path((*iter)->getKey("path")->value);
 		// Remove trailing slash, so that "/foo" and "/foo/" match.
 		// This works around a bug in the POSIX FS code (and others?)
 		// where paths are not normalized (so FSNodes refering to identical
@@ -109,7 +109,7 @@
 		while (path != "/" && path.lastChar() == '/')
 			path.deleteLastChar();
 		if (!path.empty())
-			_pathToTargets[path].push_back(iter->_key);
+			_pathToTargets[path].push_back((*iter)->name);
 	}
 }
 
@@ -176,15 +176,25 @@
 				const Common::StringList &targets = _pathToTargets[path];
 				for (Common::StringList::const_iterator iter = targets.begin(); iter != targets.end(); ++iter) {
 					// If the gameid, platform and language match -> skip it
-					Common::ConfigManager::Domain *dom = ConfMan.getDomain(*iter);
-					assert(dom);
+					const Common::ConfigFile::Section *sec = ConfMan.getSection(*iter);
+					const Common::ConfigFile::KeyValue *kv;
+					assert(sec);
 
-					if ((*dom)["gameid"] == result["gameid"] &&
-					    (*dom)["platform"] == result["platform"] && 
-					    (*dom)["language"] == result["language"]) {
-						duplicate = true;
-						break;
-					}
+					kv = (*sec).getKey("gameid");
+					if (kv && kv->value != result["gameid"])
+						continue;	// No match
+
+					kv = (*sec).getKey("platform");
+					if ((kv && kv->value != result["platform"]) || (!kv && result.contains("platform")))
+						continue;	// No match
+
+					kv = (*sec).getKey("language");
+					if ((kv && kv->value != result["language"]) || (!kv && result.contains("language")))
+						continue;	// No match
+				
+					// gameid, platform and language match -> duplicate entry
+					duplicate = true;
+					break;
 				}
 				if (duplicate)
 					break;	// Skip duplicates
Index: gui/options.cpp
===================================================================
--- gui/options.cpp	(revision 32664)
+++ gui/options.cpp	(working copy)
@@ -130,7 +130,7 @@
 
 		if (ConfMan.hasKey("gfx_mode", _domain)) {
 			const OSystem::GraphicsMode *gm = g_system->getSupportedGraphicsModes();
-			String gfxMode(ConfMan.get("gfx_mode", _domain));
+			String gfxMode(ConfMan.getKey("gfx_mode", _domain));
 			int gfxCount = 1;
 			while (gm->name) {
 				gfxCount++;
@@ -146,7 +146,7 @@
 
 		if (ConfMan.hasKey("render_mode", _domain)) {
 			const Common::RenderModeDescription *p = Common::g_renderModes;
-			const Common::RenderMode renderMode = Common::parseRenderMode(ConfMan.get("render_mode", _domain));
+			const Common::RenderMode renderMode = Common::parseRenderMode(ConfMan.getKey("render_mode", _domain));
 			int sel = 0;
 			for (int i = 0; p->code; ++p, ++i) {
 				if (renderMode == p->id)
@@ -171,7 +171,7 @@
 		int i = 0;
 		const int midiDriver =
 			ConfMan.hasKey("music_driver", _domain)
-				? MidiDriver::parseMusicDriver(ConfMan.get("music_driver", _domain))
+				? MidiDriver::parseMusicDriver(ConfMan.getKey("music_driver", _domain))
 				: MD_AUTO;
 		while (md->name && md->id != midiDriver) {
 			i++;
@@ -200,7 +200,7 @@
 		// GS extensions setting
 		_enableGSCheckbox->setState(ConfMan.getBool("enable_gs", _domain));
 
-		String soundFont(ConfMan.get("soundfont", _domain));
+		String soundFont(ConfMan.getKey("soundfont", _domain));
 		if (soundFont.empty() || !ConfMan.hasKey("soundfont", _domain)) {
 			_soundFont->setLabel("None");
 			_soundFontClearButton->setEnabled(false);
@@ -659,7 +659,7 @@
 
 
 GlobalOptionsDialog::GlobalOptionsDialog()
-	: OptionsDialog(Common::ConfigManager::kApplicationDomain, "globaloptions") {
+	: OptionsDialog(Common::ConfigManager::kApplicationSection, "globaloptions") {
 
 	// The tab widget
 	TabWidget *tab = new TabWidget(this, "globaloptions_tabwidget");
@@ -757,9 +757,9 @@
 
 #if !( defined(__DC__) || defined(__GP32__) || defined(__PLAYSTATION2__) )
 	// Set _savePath to the current save path
-	Common::String savePath(ConfMan.get("savepath", _domain));
-	Common::String themePath(ConfMan.get("themepath", _domain));
-	Common::String extraPath(ConfMan.get("extrapath", _domain));
+	Common::String savePath(ConfMan.getKey("savepath", _domain));
+	Common::String themePath(ConfMan.getKey("themepath", _domain));
+	Common::String extraPath(ConfMan.getKey("extrapath", _domain));
 
 	if (savePath.empty() || !ConfMan.hasKey("savepath", _domain)) {
 		_savePath->setLabel("None");
Index: gui/launcher.cpp
===================================================================
--- gui/launcher.cpp	(revision 32664)
+++ gui/launcher.cpp	(working copy)
@@ -26,6 +26,7 @@
 #include "base/version.h"
 
 #include "common/config-manager.h"
+#include "common/config-file.h"
 #include "common/events.h"
 #include "common/fs.h"
 #include "common/util.h"
@@ -147,12 +148,12 @@
 	int labelWidth = g_gui.evaluator()->getVar("tabPopupsLabelW");
 
 	// GAME: Path to game data (r/o), extra data (r/o), and save data (r/w)
-	String gamePath(ConfMan.get("path", _domain));
-	String extraPath(ConfMan.get("extrapath", _domain));
-	String savePath(ConfMan.get("savepath", _domain));
+	String gamePath(ConfMan.getKey("path", _domain));
+	String extraPath(ConfMan.getKey("extrapath", _domain));
+	String savePath(ConfMan.getKey("savepath", _domain));
 
 	// GAME: Determine the description string
-	String description(ConfMan.get("description", domain));
+	String description(ConfMan.getKey("description", domain));
 	if (description.empty() && !desc.empty()) {
 		description = desc;
 	}
@@ -309,7 +310,7 @@
 	// TODO: game path
 
 	const Common::LanguageDescription *l = Common::g_languages;
-	const Common::Language lang = Common::parseLanguage(ConfMan.get("language", _domain));
+	const Common::Language lang = Common::parseLanguage(ConfMan.getKey("language", _domain));
 
 	sel = 0;
 	if (ConfMan.hasKey("language", _domain)) {
@@ -322,7 +323,7 @@
 
 
 	const Common::PlatformDescription *p = Common::g_platforms;
-	const Common::Platform platform = Common::parsePlatform(ConfMan.get("platform", _domain));
+	const Common::Platform platform = Common::parsePlatform(ConfMan.getKey("platform", _domain));
 	sel = 0;
 	for (i = 0; p->code; ++p, ++i) {
 		if (platform == p->id)
@@ -449,12 +450,12 @@
 		// Write back changes made to config object
 		String newDomain(_domainWidget->getEditString());
 		if (newDomain != _domain) {
-			if (newDomain.empty() || ConfMan.hasGameDomain(newDomain)) {
+			if (newDomain.empty() || ConfMan.hasGameSection(newDomain)) {
 				MessageDialog alert("This game ID is already taken. Please choose another one.");
 				alert.runModal();
 				return;
 			}
-			ConfMan.renameGameDomain(_domain, newDomain);
+			ConfMan.renameGameSection(_domain, newDomain);
 			_domain = newDomain;
 		}
 		}
@@ -517,7 +518,7 @@
 	updateListing();
 
 	// Restore last selection
-	String last(ConfMan.get("lastselectedgame", ConfigManager::kApplicationDomain));
+	String last(ConfMan.getKey("lastselectedgame", ConfigManager::kApplicationSection));
 	selectGame(last);
 
 	// En-/disable the buttons depending on the list selection
@@ -548,7 +549,7 @@
 	// Clear the active domain, in case we return to the dialog from a
 	// failure to launch a game. Otherwise, pressing ESC will attempt to
 	// re-launch the same game again.
-	ConfMan.setActiveDomain("");
+	ConfMan.setActiveSection("");
 	Dialog::open();
 
 	updateButtons();
@@ -558,9 +559,9 @@
 	// Save last selection
 	const int sel = _list->getSelected();
 	if (sel >= 0)
-		ConfMan.set("lastselectedgame", _domains[sel], ConfigManager::kApplicationDomain);
+		ConfMan.set("lastselectedgame", _domains[sel], ConfigManager::kApplicationSection);
 	else
-		ConfMan.removeKey("lastselectedgame", ConfigManager::kApplicationDomain);
+		ConfMan.removeKey("lastselectedgame", ConfigManager::kApplicationSection);
 
 	ConfMan.flushToDisk();
 	Dialog::close();
@@ -571,22 +572,23 @@
 
 	// Retrieve a list of all games defined in the config file
 	_domains.clear();
-	const ConfigManager::DomainMap &domains = ConfMan.getGameDomains();
-	ConfigManager::DomainMap::const_iterator iter;
-	for (iter = domains.begin(); iter != domains.end(); ++iter) {
+	const Common::ConfigManager::SectionRefList &sections = ConfMan.getGameSections();
+	Common::ConfigManager::SectionRefList::const_iterator iter;
+	for (iter = sections.begin(); iter != sections.end(); ++iter) {
+		Common::ConfigFile::Section section = *(*iter);
 #ifdef __DS__
 		// DS port uses an extra section called 'ds'.  This prevents the section from being
 		// detected as a game.
-		if (iter->_key == "ds") {
+		if ((*iter)->name == "ds") {
 			continue;
 		}
 #endif
+		
+		String gameid(section.getKey("gameid")->value);
+		String description(section.getKey("description")->value);
 
-		String gameid(iter->_value.get("gameid"));
-		String description(iter->_value.get("description"));
-
 		if (gameid.empty())
-			gameid = iter->_key;
+			gameid = section.name;
 		if (description.empty()) {
 			GameDescriptor g = EngineMan.findGame(gameid);
 			if (g.contains("description"))
@@ -594,7 +596,7 @@
 		}
 
 		if (description.empty())
-			description = "Unknown (target " + iter->_key + ", gameid " + gameid + ")";
+			description = "Unknown (target " + section.name + ", gameid " + gameid + ")";
 
 		if (!gameid.empty() && !description.empty()) {
 			// Insert the game into the launcher list
@@ -603,7 +605,7 @@
 			while (pos < size && (scumm_stricmp(description.c_str(), l[pos].c_str()) > 0))
 				pos++;
 			l.insert_at(pos, description);
-			_domains.insert_at(pos, iter->_key);
+			_domains.insert_at(pos, section.name);
 		}
 	}
 
@@ -700,7 +702,7 @@
 				draw();
 			} else {
 				// User aborted, remove the the new domain again
-				ConfMan.removeGameDomain(domain);
+				ConfMan.removeGameSection(domain);
 			}
 
 		}
@@ -719,12 +721,12 @@
 		domain = result.gameid();
 
 	assert(!domain.empty());
-	if (ConfMan.hasGameDomain(domain)) {
+	if (ConfMan.hasGameSection(domain)) {
 		int suffixN = 1;
 		char suffix[16];
 		String gameid(domain);
 
-		while (ConfMan.hasGameDomain(domain)) {
+		while (ConfMan.hasGameSection(domain)) {
 			snprintf(suffix, 16, "-%d", suffixN);
 			domain = gameid + suffix;
 			suffixN++;
@@ -732,7 +734,7 @@
 	}
 
 	// Add the name domain
-	ConfMan.addGameDomain(domain);
+	ConfMan.addGameSection(domain);
 
 	// Copy all non-empty key/value pairs into the new domain
 	for (GameDescriptor::const_iterator iter = result.begin(); iter != result.end(); ++iter) {
@@ -759,7 +761,7 @@
 	if (alert.runModal() == GUI::kMessageOK) {
 		// Remove the currently selected game from the list
 		assert(item >= 0);
-		ConfMan.removeGameDomain(_domains[item]);
+		ConfMan.removeGameSection(_domains[item]);
 
 		// Write config to disk
 		ConfMan.flushToDisk();
@@ -778,7 +780,7 @@
 	// This is useful because e.g. MonkeyVGA needs Adlib music to have decent
 	// music support etc.
 	assert(item >= 0);
-	String gameId(ConfMan.get("gameid", _domains[item]));
+	String gameId(ConfMan.getKey("gameid", _domains[item]));
 	if (gameId.empty())
 		gameId = _domains[item];
 	EditGameDialog editDialog(_domains[item], EngineMan.findGame(gameId).description());
@@ -832,7 +834,7 @@
 	case kListItemDoubleClickedCmd:
 		// Print out what was selected
 		assert(item >= 0);
-		ConfMan.setActiveDomain(_domains[item]);
+		ConfMan.setActiveSection(_domains[item]);
 		close();
 		break;
 	case kListItemRemovalRequestCmd:
@@ -842,7 +844,7 @@
 		updateButtons();
 		break;
 	case kQuitCmd:
-		ConfMan.setActiveDomain("");
+		ConfMan.setActiveSection("");
 		setResult(-1);
 		close();
 		break;
Index: common/config-manager.h
===================================================================
--- common/config-manager.h	(revision 32664)
+++ common/config-manager.h	(working copy)
@@ -27,7 +27,7 @@
 #define COMMON_CONFIG_MANAGER_H
 
 #include "common/array.h"
-//#include "common/config-file.h"
+#include "common/config-file.h"
 #include "common/hashmap.h"
 #include "common/singleton.h"
 #include "common/str.h"
@@ -46,84 +46,67 @@
  *       which sends out notifications to interested parties whenever the value
  *       of some specific (or any) configuration key changes.
  */
-class ConfigManager : public Singleton<ConfigManager> {
+class ConfigManager : public Singleton<ConfigManager>, public ConfigFile {
 
 public:
 
-	class Domain : public StringMap {
-	private:
-		StringMap _keyValueComments;
-		String _domainComment;
-
-	public:
-		const String &get(const String &key) const;
-
-		void setDomainComment(const String &comment);
-		const String &getDomainComment() const;
-
-		void setKVComment(const String &key, const String &comment);
-		const String &getKVComment(const String &key) const;
-		bool hasKVComment(const String &key) const;
-	};
-
-	typedef HashMap<String, Domain, IgnoreCase_Hash, IgnoreCase_EqualTo> DomainMap;
-
 #if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__))
-	/** The name of the application domain (normally 'scummvm'). */
-	static const String kApplicationDomain;
+	/** The name of the application section (normally 'scummvm'). */
+	static const String kApplicationSection;
 
-	/** The transient (pseudo) domain. */
-	static const String kTransientDomain;
+	/** The transient (pseudo) section. */
+	static const String kTransientSection;
 #else
-	static const char *kApplicationDomain;
-	static const char *kTransientDomain;
+	static const char *kApplicationSection;
+	static const char *kTransientSection;
 
-	const String _emptyString;
 #endif
+	
+	typedef List<Section*> SectionRefList;
 
 	void				loadDefaultConfigFile();
 	void				loadConfigFile(const String &filename);
 
 	/**
-	 * Retrieve the config domain with the given name.
-	 * @param domName	the name of the domain to retrieve
-	 * @return pointer to the domain, or 0 if the domain doesn't exist.
+	 * Retrieve the config section with the given name.
+	 * @param secName	the name of the section to retrieve
+	 * @return pointer to the section, or 0 if the section doesn't exist.
 	 */
-	Domain *			getDomain(const String &domName);
-	const Domain *		getDomain(const String &domName) const;
+	Section *			getSection(const String &secName);
+	const Section *		getSection(const String &secName) const;
 
 
 	//
-	// Generic access methods: No domain specified, use the values from the
-	// various domains in the order of their priority.
+	// Generic access methods: No section specified, use the values from the
+	// various sections in the order of their priority.
 	//
 
 	bool				hasKey(const String &key) const;
 	const String &		get(const String &key) const;
 	void				set(const String &key, const String &value);
-
+	const String & 		getKey(const String &key) const;
 #if 1
 	//
-	// Domain specific access methods: Acces *one specific* domain and modify it.
+	// Section specific access methods: Acces *one specific* section and modify it.
 	// TODO: I'd like to get rid of most of those if possible, or at least reduce
-	// their usage, by using getDomain as often as possible. For example in the
+	// their usage, by using getSection as often as possible. For example in the
 	// options dialog code...
 	//
 
-	bool				hasKey(const String &key, const String &domName) const;
-	const String &		get(const String &key, const String &domName) const;
-	void				set(const String &key, const String &value, const String &domName);
-
-	void				removeKey(const String &key, const String &domName);
+	bool				hasKey(const String &key, const String &secName) const;
+	const String &		getKey(const String &key, const String &secName) const;
+	void				set(const String &key, const String &value, const String &secName);
+	void				removeKey(const String &key, const String &secName);
+	
 #endif
 
 	//
 	// Some additional convenience accessors.
 	//
-	int					getInt(const String &key, const String &domName = String::emptyString) const;
-	bool				getBool(const String &key, const String &domName = String::emptyString) const;
-	void				setInt(const String &key, int value, const String &domName = String::emptyString);
-	void				setBool(const String &key, bool value, const String &domName = String::emptyString);
+	int					getInt(const String &key, const String &secName = String::emptyString) const;
+	bool				getBool(const String &key, const String &secName = String::emptyString) const;
+	void				setInt(const String &key, int value, const String &secName = String::emptyString);
+	void				setBool(const String &key, bool value, const String &secName = String::emptyString);
 
 
 	void				registerDefault(const String &key, const String &value);
@@ -133,16 +116,16 @@
 
 	void				flushToDisk();
 
-	void				setActiveDomain(const String &domName);
-	Domain *			getActiveDomain() { return _activeDomain; }
-	const Domain *		getActiveDomain() const { return _activeDomain; }
-	const String &		getActiveDomainName() const { return _activeDomainName; }
+	void				setActiveSection(const String &secName);
+	Section *			getActiveSection() { return _activeSection; }
+	const Section *		getActiveSection() const { return _activeSection; }
+	const String &		getActiveSectionName() const { return _activeSectionName; }
 
-	void				addGameDomain(const String &domName);
-	void				removeGameDomain(const String &domName);
-	void				renameGameDomain(const String &oldName, const String &newName);
-	bool				hasGameDomain(const String &domName) const;
-	const DomainMap &	getGameDomains() const { return _gameDomains; }
+	void				addGameSection(const String &secName);
+	void				removeGameSection(const String &secName);
+	void				renameGameSection(const String &oldName, const String &newName);
+	bool				hasGameSection(const String &secName) const;
+	const SectionRefList &getGameSections() const { return _gameSections; }
 
 /*
 	TODO: Callback/change notification system
@@ -157,18 +140,16 @@
 	ConfigManager();
 
 	void			loadFile(const String &filename);
-	void			writeDomain(WriteStream &stream, const String &name, const Domain &domain);
+	void			writeSection(WriteStream &stream, const String &name, const Section &section);
 
-	Domain			_transientDomain;
-	DomainMap		_gameDomains;
-	Domain			_appDomain;
-	Domain			_defaultsDomain;
+	Section			_transientSection;
+	SectionRefList	_gameSections;
+	Section			*_appSection;
+	Section			_defaultsSection;
 
-	StringList		_domainSaveOrder;
+	String			_activeSectionName;
+	Section 		*_activeSection;
 
-	String			_activeDomainName;
-	Domain *		_activeDomain;
-
 	String			_filename;
 };
 
Index: common/config-file.h
===================================================================
--- common/config-file.h	(revision 32664)
+++ common/config-file.h	(working copy)
@@ -26,10 +26,10 @@
 #ifndef COMMON_CONFIG_FILE_H
 #define COMMON_CONFIG_FILE_H
 
-#include "common/config-manager.h"
 #include "common/list.h"
 #include "common/str.h"
 #include "common/stream.h"
+#include "common/hash-str.h"
 
 namespace Common {
 
@@ -53,16 +53,35 @@
  */
 class ConfigFile {
 public:
-	typedef HashMap<String, bool, IgnoreCase_Hash, IgnoreCase_EqualTo> StringSet;
-
+	enum{
+		kSectionChanged,
+		kSectionAdded,
+		kSectionRemoved
+	};
+	
+	
+	class Observer{
+	public:
+		virtual void configFileChanged(int event, const String &section, const String &key) = 0;
+		virtual ~Observer();
+	};
+	/** A section in a config file. I.e. corresponds to something like this:
+	 *   [mySection]
+	 *   key=value
+	 *
+	 * Comments are also stored, to keep users happy who like editing their
+	 * config files manually.
+	 */
+	
+	
 	struct KeyValue {
 		String key;
 		String value;
 		String comment;
 	};
-
+	
 	typedef List<KeyValue> SectionKeyList;
-
+	
 	/** A section in a config file. I.e. corresponds to something like this:
 	 *   [mySection]
 	 *   key=value
@@ -74,20 +93,22 @@
 		String name;
 		List<KeyValue> keys;
 		String comment;
-
+		
+		void clear() { keys.clear(); }
 		bool hasKey(const String &key) const;
 		const KeyValue* getKey(const String &key) const;
 		void setKey(const String &key, const String &value);
 		void removeKey(const String &key);
 		const SectionKeyList getKeys() const { return keys; }
 	};
-
+	
 	typedef List<Section> SectionList;
-
+	
 public:
 	ConfigFile();
-	~ConfigFile();
+	virtual ~ConfigFile();
 
+	static const String _emptyString;
 	// TODO: Maybe add a copy constructor etc.?
 
 	/**
@@ -100,34 +121,37 @@
 
 	/** Reset everything stored in this config file. */
 	void	clear();
-
+	
 	bool	loadFromFile(const String &filename);
 	bool	loadFromSaveFile(const char *filename);
 	bool	loadFromStream(SeekableReadStream &stream);
 	bool	saveToFile(const String &filename);
 	bool	saveToSaveFile(const char *filename);
 	bool	saveToStream(WriteStream &stream);
-
+	void	writeSection(WriteStream &stream, const Section &section);
+	
+	void	addSection(const String &section);
 	bool	hasSection(const String &section) const;
 	void	removeSection(const String &section);
 	void	renameSection(const String &oldName, const String &newName);
-
+	const SectionKeyList getKeys(const String &section) const;
+	
 	bool	hasKey(const String &key, const String &section) const;
-	bool	getKey(const String &key, const String &section, String &value) const;
+	virtual const String &getKey(const String &key, const String &section) const;
+	virtual bool	getKey(const String &key, const String &section, String &value) const;
 	void	setKey(const String &key, const String &section, const String &value);
 	void	removeKey(const String &key, const String &section);
 
-	const SectionList getSections() const { return _sections; }
-	const SectionKeyList getKeys(const String &section) const;
+	void	registerObserver(Observer *ob);
+	void	notifyObservers(int event, const String &section, const String &key);
 
-	void listSections(StringSet &set);
-	void listKeyValues(StringMap &kv);
-
-private:
-	SectionList _sections;
-
+protected:
+	SectionList	_sections;
 	Section *getSection(const String &section);
 	const Section *getSection(const String &section) const;
+	List<Observer*>	_observers;
+
+	
 };
 
 /*
Index: common/config-manager.cpp
===================================================================
--- common/config-manager.cpp	(revision 32664)
+++ common/config-manager.cpp	(working copy)
@@ -66,13 +66,13 @@
 
 #if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__))
 
-const String ConfigManager::kApplicationDomain("scummvm");
-const String ConfigManager::kTransientDomain("__TRANSIENT");
+const String ConfigManager::kApplicationSection("scummvm");
+const String ConfigManager::kTransientSection("__TRANSIENT");
 
 #else
 
-const char *ConfigManager::kApplicationDomain = "scummvm";
-const char *ConfigManager::kTransientDomain = "__TRANSIENT";
+const char *ConfigManager::kApplicationSection = "scummvm";
+const char *ConfigManager::kTransientSection = "__TRANSIENT";
 
 #endif
 
@@ -80,15 +80,13 @@
 
 
 ConfigManager::ConfigManager()
- : _activeDomain(0) {
+ : _activeSection(0){
 }
-
-
 void ConfigManager::loadDefaultConfigFile() {
 	char configFile[MAXPATHLEN];
 	// GP2X is Linux based but Home dir can be read only so do not use it and put the config in the executable dir.
 	// On the iPhone, the home dir of the user when you launch the app from the Springboard, is /. Which we don't want.
-#if defined(UNIX) && !defined(GP2X) && !defined(IPHONE)
+#if defined(UNIX) || defined(MACOSX) && !defined(GP2X) && !defined(IPHONE)
 	const char *home = getenv("HOME");
 	if (home != NULL && strlen(home) < MAXPATHLEN)
 		snprintf(configFile, MAXPATHLEN, "%s/%s", home, DEFAULT_CONFIG_FILE);
@@ -160,211 +158,71 @@
 }
 
 void ConfigManager::loadConfigFile(const String &filename) {
-	_appDomain.clear();
-	_gameDomains.clear();
-	_transientDomain.clear();
+	
+	if(_appSection)
+		_appSection->keys.clear();
+	_gameSections.clear();
+	_transientSection.keys.clear();
 
 	_filename = filename;
-	_domainSaveOrder.clear();
-	loadFile(_filename);
+	loadFromFile(filename);
+	
+	if(!hasSection(kApplicationSection))
+		addSection(kApplicationSection);
+	_appSection = ConfigFile::getSection(kApplicationSection);
+	
+	SectionList::const_iterator iter;
+	for(iter = _sections.begin(); iter != _sections.end(); ++iter){
+		if(iter->name != kApplicationSection)
+			_gameSections.push_back(ConfigFile::getSection(iter->name));
+	}
+	
 	printf("Using configuration file: %s\n", _filename.c_str());
 }
 
-void ConfigManager::loadFile(const String &filename) {
-	File cfg_file;
 
-	if (!cfg_file.open(filename)) {
-		printf("Creating configuration file: %s\n", filename.c_str());
-	} else {
-		char buf[MAXLINELEN];
-		String domain;
-		String comment;
-		int lineno = 0;
-
-		// TODO: Detect if a domain occurs multiple times (or likewise, if
-		// a key occurs multiple times inside one domain).
-
-		while (!cfg_file.eof()) {
-			lineno++;
-			if (!cfg_file.readLine(buf, MAXLINELEN))
-				break;
-
-			if (buf[0] == '#') {
-				// Accumulate comments here. Once we encounter either the start
-				// of a new domain, or a key-value-pair, we associate the value
-				// of the 'comment' variable with that entity.
-				comment += buf;
-				comment += '\n';
-			} else if (buf[0] == '[') {
-				// It's a new domain which begins here.
-				char *p = buf + 1;
-				// Get the domain name, and check whether it's valid (that
-				// is, verify that it only consists of alphanumerics,
-				// dashes and underscores).
-				while (*p && (isalnum(*p) || *p == '-' || *p == '_'))
-					p++;
-
-				switch (*p) {
-				case '\0':
-					error("Config file buggy: missing ] in line %d", lineno);
-					break;
-				case ']':
-					*p = 0;
-					domain = buf + 1;
-					break;
-				default:
-					error("Config file buggy: Invalid character '%c' occured in domain name in line %d", *p, lineno);
-				}
-
-				// Store domain comment
-				if (domain == kApplicationDomain) {
-					_appDomain.setDomainComment(comment);
-				} else {
-					_gameDomains[domain].setDomainComment(comment);
-				}
-				comment.clear();
-
-				_domainSaveOrder.push_back(domain);
-			} else {
-				// Skip leading & trailing whitespaces
-				char *t = rtrim(ltrim(buf));
-
-				// Skip empty lines
-				if (*t == 0)
-					continue;
-
-				// If no domain has been set, this config file is invalid!
-				if (domain.empty()) {
-					error("Config file buggy: Key/value pair found outside a domain in line %d", lineno);
-				}
-
-				// Split string at '=' into 'key' and 'value'.
-				char *p = strchr(t, '=');
-				if (!p)
-					error("Config file buggy: Junk found in line line %d: '%s'", lineno, t);
-				*p = 0;
-				String key = rtrim(t);
-				String value = ltrim(p + 1);
-				set(key, value, domain);
-
-				// Store comment
-				if (domain == kApplicationDomain) {
-					_appDomain.setKVComment(key, comment);
-				} else {
-					_gameDomains[domain].setKVComment(key, comment);
-				}
-				comment.clear();
-			}
-		}
-	}
-}
-
 void ConfigManager::flushToDisk() {
-#ifndef __DC__
-	File cfg_file;
-
-// TODO
-//	if (!willwrite)
-//		return;
-
-	if (!cfg_file.open(_filename, File::kFileWriteMode)) {
-		warning("Unable to write configuration file: %s", _filename.c_str());
-	} else {
-		// First write the domains in _domainSaveOrder, in that order.
-		// Note: It's possible for _domainSaveOrder to list domains which
-		// are not present anymore.
-		StringList::const_iterator i;
-		for (i = _domainSaveOrder.begin(); i != _domainSaveOrder.end(); ++i) {
-			if (kApplicationDomain == *i) {
-				writeDomain(cfg_file, *i, _appDomain);
-			} else if (_gameDomains.contains(*i)) {
-				writeDomain(cfg_file, *i, _gameDomains[*i]);
-			}
-		}
-
-		DomainMap::const_iterator d;
-
-
-		// Now write the domains which haven't been written yet
-		if (find(_domainSaveOrder.begin(), _domainSaveOrder.end(), kApplicationDomain) == _domainSaveOrder.end())
-			writeDomain(cfg_file, kApplicationDomain, _appDomain);
-		for (d = _gameDomains.begin(); d != _gameDomains.end(); ++d) {
-			if (find(_domainSaveOrder.begin(), _domainSaveOrder.end(), d->_key) == _domainSaveOrder.end())
-				writeDomain(cfg_file, d->_key, d->_value);
-		}
-	}
-#endif // !__DC__
+	saveToFile(_filename);
 }
 
-void ConfigManager::writeDomain(WriteStream &stream, const String &name, const Domain &domain) {
-	if (domain.empty())
-		return;		// Don't bother writing empty domains.
 
-	String comment;
+#pragma mark -
 
-	// Write domain comment (if any)
-	comment = domain.getDomainComment();
-	if (!comment.empty())
-		stream.writeString(comment);
 
-	// Write domain start
-	stream.writeByte('[');
-	stream.writeString(name);
-	stream.writeByte(']');
-	stream.writeByte('\n');
+const ConfigManager::Section *ConfigManager::getSection(const String &secName) const {
+	assert(!secName.empty());
+	assert(isValidDomainName(secName));
 
-	// Write all key/value pairs in this domain, including comments
-	Domain::const_iterator x;
-	for (x = domain.begin(); x != domain.end(); ++x) {
-		if (!x->_value.empty()) {
-			// Write comment (if any)
-			if (domain.hasKVComment(x->_key)) {
-				comment = domain.getKVComment(x->_key);
-				stream.writeString(comment);
-			}
-			// Write the key/value pair
-			stream.writeString(x->_key);
-			stream.writeByte('=');
-			stream.writeString(x->_value);
-			stream.writeByte('\n');
+	if (secName == kTransientSection)
+		return &_transientSection;
+	if (secName == kApplicationSection)
+		return _appSection;
+	for (SectionRefList::iterator i = _gameSections.begin(); i != _gameSections.end(); ++i) {
+		if (!scumm_stricmp(secName.c_str(), (*i)->name.c_str())) {
+			return (*i);
 		}
 	}
-	stream.writeByte('\n');
-}
 
-
-#pragma mark -
-
-
-const ConfigManager::Domain *ConfigManager::getDomain(const String &domName) const {
-	assert(!domName.empty());
-	assert(isValidDomainName(domName));
-
-	if (domName == kTransientDomain)
-		return &_transientDomain;
-	if (domName == kApplicationDomain)
-		return &_appDomain;
-	if (_gameDomains.contains(domName))
-		return &_gameDomains[domName];
-
 	return 0;
 }
 
-ConfigManager::Domain *ConfigManager::getDomain(const String &domName) {
-	assert(!domName.empty());
-	assert(isValidDomainName(domName));
+ConfigManager::Section *ConfigManager::getSection(const String &secName) {
+	assert(!secName.empty());
+	assert(isValidDomainName(secName));
+	
+	if (secName == kTransientSection)
+		return &_transientSection;
+	if (secName == kApplicationSection)
+		return _appSection;
+	for (SectionRefList::iterator i = _gameSections.begin(); i != _gameSections.end(); ++i) {
+		if (!scumm_stricmp(secName.c_str(), (*i)->name.c_str())) {
+			return (*i);
+		}
+	}
 
-	if (domName == kTransientDomain)
-		return &_transientDomain;
-	if (domName == kApplicationDomain)
-		return &_appDomain;
-	if (_gameDomains.contains(domName))
-		return &_gameDomains[domName];
-
 	return 0;
 }
 
-
 #pragma mark -
 
 
@@ -375,99 +233,101 @@
 	// 3) the application domain.
 	// The defaults domain is explicitly *not* checked.
 
-	if (_transientDomain.contains(key))
+	if (_transientSection.hasKey(key))
 		return true;
 
-	if (_activeDomain && _activeDomain->contains(key))
+	if (_activeSection && _activeSection->hasKey(key))
 		return true;
 
-	if (_appDomain.contains(key))
+	if (_appSection && _appSection->hasKey(key))
 		return true;
 
 	return false;
 }
-
-bool ConfigManager::hasKey(const String &key, const String &domName) const {
-	// FIXME: For now we continue to allow empty domName to indicate
-	// "use 'default' domain". This is mainly needed for the SCUMM ConfigDialog
+	
+bool ConfigManager::hasKey(const String &key, const String &secName) const {
+	// FIXME: For now we continue to allow empty secName to indicate
+	// "use 'default' section". This is mainly needed for the SCUMM ConfigDialog
 	// and should be removed ASAP.
-	if (domName.empty())
+	if (secName.empty())
 		return hasKey(key);
 
-	const Domain *domain = getDomain(domName);
+	const Section *section = getSection(secName);
 
-	if (!domain)
+	if (!section)
 		return false;
-	return domain->contains(key);
+	return section->hasKey(key);
 }
 
-void ConfigManager::removeKey(const String &key, const String &domName) {
-	Domain *domain = getDomain(domName);
+void ConfigManager::removeKey(const String &key, const String &secName) {
+	Section *section = getSection(secName);
 
-	if (!domain)
+	if (!section)
 		error("ConfigManager::removeKey(%s, %s) called on non-existent domain",
-					key.c_str(), domName.c_str());
+					key.c_str(), secName.c_str());
 
-	domain->erase(key);
+	section->removeKey(key);
 }
 
 
 #pragma mark -
+	
 
-
 const String & ConfigManager::get(const String &key) const {
-	if (_transientDomain.contains(key))
-		return _transientDomain[key];
-	else if (_activeDomain && _activeDomain->contains(key))
-		return (*_activeDomain)[key];
-	else if (_appDomain.contains(key))
-		return _appDomain[key];
-	else if (_defaultsDomain.contains(key))
-		return _defaultsDomain[key];
+	return getKey(key);
+}
 
+const String &ConfigManager::getKey(const String &key) const {
+	if (_transientSection.hasKey(key))
+		return _transientSection.getKey(key)->value;
+	else if (_activeSection && _activeSection->hasKey(key))
+		return (*_activeSection).getKey(key)->value;
+	else if (_appSection && _appSection->hasKey(key))
+		return _appSection->getKey(key)->value;
+	else if (_defaultsSection.hasKey(key))
+		return _defaultsSection.getKey(key)->value;
+	
 #if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__))
 	return String::emptyString;
 #else
-	return ConfMan._emptyString;
+	return _emptyString;
 #endif
 }
 
-const String & ConfigManager::get(const String &key, const String &domName) const {
+const String & ConfigManager::getKey(const String &key, const String &secName) const {
 	// FIXME: For now we continue to allow empty domName to indicate
 	// "use 'default' domain". This is mainly needed for the SCUMM ConfigDialog
 	// and should be removed ASAP.
-	if (domName.empty())
+	if (secName.empty())
 		return get(key);
-
-	const Domain *domain = getDomain(domName);
-
-	if (!domain)
+	
+	const Section *section = getSection(secName);
+	
+	if (!section)
 		error("ConfigManager::get(%s,%s) called on non-existent domain",
-								key.c_str(), domName.c_str());
+			 					key.c_str(), secName.c_str());
+	
 
-	if (domain->contains(key))
-		return (*domain)[key];
+	if (section->hasKey(key))
+		return section->getKey(key)->value;
 
-	return _defaultsDomain.get(key);
-
-	if (!domain->contains(key)) {
+	if(_defaultsSection.hasKey(key))
+		return _defaultsSection.getKey(key)->value;
+	
 #if 1
 #if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__))
-	return String::emptyString;
+		return String::emptyString;
 #else
-	return ConfMan._emptyString;
+		return _emptyString;
 #endif
 #else
 		error("ConfigManager::get(%s,%s) called on non-existent key",
-					key.c_str(), domName.c_str());
+			  key.c_str(), secName.c_str());
 #endif
-	}
-
-	return (*domain)[key];
 }
 
 int ConfigManager::getInt(const String &key, const String &domName) const {
-	String value(get(key, domName));
+	String value(getKey(key, domName));
 	char *errpos;
 
 	// For now, be tolerant against missing config keys. Strictly spoken, it is
@@ -488,7 +348,7 @@
 }
 
 bool ConfigManager::getBool(const String &key, const String &domName) const {
-	String value(get(key, domName));
+	String value(getKey(key, domName));
 
 	if ((value == "true") || (value == "yes") || (value == "1"))
 		return true;
@@ -505,33 +365,33 @@
 
 void ConfigManager::set(const String &key, const String &value) {
 	// Remove the transient domain value, if any.
-	_transientDomain.erase(key);
+	_transientSection.removeKey(key);
 
 	// Write the new key/value pair into the active domain, resp. into
 	// the application domain if no game domain is active.
-	if (_activeDomain)
-		(*_activeDomain)[key] = value;
+	if (_activeSection)
+		(*_activeSection).setKey(key, value);
 	else
-		_appDomain[key] = value;
+		(*_appSection).setKey(key, value);
 }
 
-void ConfigManager::set(const String &key, const String &value, const String &domName) {
+void ConfigManager::set(const String &key, const String &value, const String &secName) {
 	// FIXME: For now we continue to allow empty domName to indicate
 	// "use 'default' domain". This is mainly needed for the SCUMM ConfigDialog
 	// and should be removed ASAP.
-	if (domName.empty()) {
+	if (secName.empty()) {
 		set(key, value);
 		return;
 	}
 
-	Domain *domain = getDomain(domName);
+	Section *section = getSection(secName);
 
-	if (!domain)
-		error("ConfigManager::set(%s,%s,%s) called on non-existent domain",
-					key.c_str(), value.c_str(), domName.c_str());
+	if (!section)
+		error("ConfigManager::set(%s,%s,%s) called on non-existent section",
+					key.c_str(), value.c_str(), secName.c_str());
 
-	(*domain)[key] = value;
-
+	(*section).setKey(key,value);
+	
 	// TODO/FIXME: We used to erase the given key from the transient domain
 	// here. Do we still want to do that?
 	// It was probably there to simplify the options dialogs code:
@@ -575,7 +435,7 @@
 
 
 void ConfigManager::registerDefault(const String &key, const String &value) {
-	_defaultsDomain[key] = value;
+	_defaultsSection.setKey(key, value);
 }
 
 void ConfigManager::registerDefault(const String &key, const char *value) {
@@ -596,33 +456,35 @@
 #pragma mark -
 
 
-void ConfigManager::setActiveDomain(const String &domName) {
-	if (domName.empty()) {
-		_activeDomain = 0;
+void ConfigManager::setActiveSection(const String &secName) {
+	if (secName.empty()) {
+		_activeSection = 0;
 	} else {
-		assert(isValidDomainName(domName));
-		_activeDomain = & _gameDomains[domName];
+		assert(isValidDomainName(secName));
+		_activeSection = getSection(secName);
 	}
-	_activeDomainName = domName;
+	_activeSectionName = secName;
 }
 
-void ConfigManager::addGameDomain(const String &domName) {
-	assert(!domName.empty());
-	assert(isValidDomainName(domName));
-
+void ConfigManager::addGameSection(const String &secName) {
+	assert(!secName.empty());
+	assert(isValidDomainName(secName));
+	
 	// TODO: Do we want to generate an error/warning if a domain with
 	// the given name already exists?
 
-	_gameDomains[domName];
+	addSection(secName);
+	_gameSections.push_back(ConfigFile::getSection(secName));
 }
 
-void ConfigManager::removeGameDomain(const String &domName) {
-	assert(!domName.empty());
-	assert(isValidDomainName(domName));
-	_gameDomains.erase(domName);
+void ConfigManager::removeGameSection(const String &secName) {
+	assert(!secName.empty());
+	assert(isValidDomainName(secName));
+	_gameSections.remove(ConfigFile::getSection(secName));
+	removeSection(secName);
 }
 
-void ConfigManager::renameGameDomain(const String &oldName, const String &newName) {
+void ConfigManager::renameGameSection(const String &oldName, const String &newName) {
 	if (oldName == newName)
 		return;
 
@@ -631,52 +493,22 @@
 	assert(isValidDomainName(oldName));
 	assert(isValidDomainName(newName));
 
+	renameSection(oldName, newName);
 //	_gameDomains[newName].merge(_gameDomains[oldName]);
-	Domain &oldDom = _gameDomains[oldName];
-	Domain &newDom = _gameDomains[newName];
-	Domain::const_iterator iter;
-	for (iter = oldDom.begin(); iter != oldDom.end(); ++iter)
-		newDom[iter->_key] = iter->_value;
-
-	_gameDomains.erase(oldName);
 }
 
-bool ConfigManager::hasGameDomain(const String &domName) const {
-	assert(!domName.empty());
-	return isValidDomainName(domName) && _gameDomains.contains(domName);
+bool ConfigManager::hasGameSection(const String &secName) const {
+	assert(!secName.empty());
+	if (!isValidDomainName(secName))
+		return false;
+	
+	SectionRefList::const_iterator iter;
+	for (iter = _gameSections.begin(); iter != _gameSections.end(); ++iter){
+		if (secName.equalsIgnoreCase((*iter)->name))
+		   return true;
+	}
+	return false;
 }
 
 
-#pragma mark -
-
-
-const String &ConfigManager::Domain::get(const String &key) const {
-	const_iterator iter(find(key));
-	if (iter != end())
-		return iter->_value;
-
-#if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__))
-	return String::emptyString;
-#else
-	return ConfMan._emptyString;
-#endif
-}
-
-void ConfigManager::Domain::setDomainComment(const String &comment) {
-	_domainComment = comment;
-}
-const String &ConfigManager::Domain::getDomainComment() const {
-	return _domainComment;
-}
-
-void ConfigManager::Domain::setKVComment(const String &key, const String &comment) {
-	_keyValueComments[key] = comment;
-}
-const String &ConfigManager::Domain::getKVComment(const String &key) const {
-	return _keyValueComments[key];
-}
-bool ConfigManager::Domain::hasKVComment(const String &key) const {
-	return _keyValueComments.contains(key);
-}
-
 }	// End of namespace Common
Index: common/config-file.cpp
===================================================================
--- common/config-file.cpp	(revision 32664)
+++ common/config-file.cpp	(working copy)
@@ -28,7 +28,7 @@
 #include "common/savefile.h"
 #include "common/system.h"
 #include "common/util.h"
-
+#include "config-manager.h"
 #define MAXLINELEN 256
 
 namespace Common {
@@ -82,15 +82,15 @@
 	KeyValue kv;
 	String comment;
 	int lineno = 0;
-
+	
 	// TODO: Detect if a section occurs multiple times (or likewise, if
 	// a key occurs multiple times inside one section).
-
+	
 	while (!stream.eos()) {
 		lineno++;
 		if (!stream.readLine(buf, MAXLINELEN))
 			break;
-
+		
 		if (buf[0] == '#') {
 			// Accumulate comments here. Once we encounter either the start
 			// of a new section, or a key-value-pair, we associate the value
@@ -115,58 +115,58 @@
 			// dashes and underscores).
 			while (*p && (isalnum(*p) || *p == '-' || *p == '_'))
 				p++;
-
+			
 			if (*p == '\0')
 				error("ConfigFile::loadFromStream: missing ] in line %d", lineno);
 			else if (*p != ']')
 				error("ConfigFile::loadFromStream: Invalid character '%c' occured in section name in line %d", *p, lineno);
-
+			
 			*p = 0;
-
+			
 			// Previous section is finished now, store it.
 			if (!section.name.empty())
 				_sections.push_back(section);
-
+			
 			section.name = buf + 1;
 			section.keys.clear();
 			section.comment = comment;
 			comment.clear();
-
+			
 			assert(isValidName(section.name));
 		} else {
 			// Skip leading & trailing whitespaces
 			char *t = rtrim(ltrim(buf));
-
+			
 			// Skip empty lines
 			if (*t == 0)
 				continue;
-
+			
 			// If no section has been set, this config file is invalid!
 			if (section.name.empty()) {
 				error("ConfigFile::loadFromStream: Key/value pair found outside a section in line %d", lineno);
 			}
-
+			
 			// Split string at '=' into 'key' and 'value'.
 			char *p = strchr(t, '=');
 			if (!p)
 				error("ConfigFile::loadFromStream: Junk found in line line %d: '%s'", lineno, t);
 			*p = 0;
-
+			
 			kv.key = rtrim(t);
 			kv.value = ltrim(p + 1);
 			kv.comment = comment;
 			comment.clear();
-
+			
 			assert(isValidName(kv.key));
-
+			
 			section.keys.push_back(kv);
 		}
 	}
-
+	
 	// Save last section
 	if (!section.name.empty())
 		_sections.push_back(section);
-
+	
 	return (!stream.ioFailed() || stream.eos());
 }
 
@@ -191,37 +191,53 @@
 }
 
 bool ConfigFile::saveToStream(WriteStream &stream) {
-	for (List<Section>::iterator i = _sections.begin(); i != _sections.end(); ++i) {
-		// Write out the section comment, if any
-		if (! i->comment.empty()) {
-			stream.writeString(i->comment);
+	for (List<Section>::const_iterator i = _sections.begin(); i != _sections.end(); ++i) {
+		writeSection(stream, *i);
+	}
+	
+	stream.flush();
+	return !stream.ioFailed();
+}
+	
+void ConfigFile::writeSection(WriteStream &stream, const Section &section) {
+	
+	if(section.keys.empty())
+		return;
+	
+	// Write out the section comment, if any
+	if (! section.comment.empty()) {
+		stream.writeString(section.comment);
+	}
+	
+	// Write out the section name
+	stream.writeByte('[');
+	stream.writeString(section.name);
+	stream.writeByte(']');
+	stream.writeByte('\n');
+	
+	// Write out the key/value pairs
+	for (List<KeyValue>::iterator kv = section.keys.begin(); kv != section.keys.end(); ++kv) {
+		// Write out the comment, if any
+		if (! section.comment.empty()) {
+			stream.writeString(kv->comment);
 		}
-
-		// Write out the section name
-		stream.writeByte('[');
-		stream.writeString(i->name);
-		stream.writeByte(']');
+		// Write out the key/value pair
+		stream.writeString(kv->key);
+		stream.writeByte('=');
+		stream.writeString(kv->value);
 		stream.writeByte('\n');
-
-		// Write out the key/value pairs
-		for (List<KeyValue>::iterator kv = i->keys.begin(); kv != i->keys.end(); ++kv) {
-			// Write out the comment, if any
-			if (! kv->comment.empty()) {
-				stream.writeString(kv->comment);
-			}
-			// Write out the key/value pair
-			stream.writeString(kv->key);
-			stream.writeByte('=');
-			stream.writeString(kv->value);
-			stream.writeByte('\n');
-		}
 	}
+}
+	
+void ConfigFile::addSection(const String &secName) {
+	Section section;
+	section.name = secName;
+	section.keys.clear();
+	section.comment.clear();
+	
+	_sections.push_back(section);
 
-	stream.flush();
-	return !stream.ioFailed();
 }
-
-
 void ConfigFile::removeSection(const String &section) {
 	assert(isValidName(section));
 	for (List<Section>::iterator i = _sections.begin(); i != _sections.end(); ++i) {
@@ -231,17 +247,17 @@
 		}
 	}
 }
-
+	
 bool ConfigFile::hasSection(const String &section) const {
 	assert(isValidName(section));
 	const Section *s = getSection(section);
 	return s != 0;
 }
-
+	
 void ConfigFile::renameSection(const String &oldName, const String &newName) {
 	assert(isValidName(oldName));
 	assert(isValidName(newName));
-
+	
 	//Section *os = getSection(oldName);
 	Section *ns = getSection(newName);
 	if (ns) {
@@ -253,12 +269,12 @@
 	// - error out
 	// - merge the two sections "oldName" and "newName"
 }
+	
 
-
 bool ConfigFile::hasKey(const String &key, const String &section) const {
 	assert(isValidName(key));
 	assert(isValidName(section));
-
+	
 	const Section *s = getSection(section);
 	if (!s)
 		return false;
@@ -268,16 +284,33 @@
 void ConfigFile::removeKey(const String &key, const String &section) {
 	assert(isValidName(key));
 	assert(isValidName(section));
-
+	
 	Section *s = getSection(section);
 	if (s)
-		 s->removeKey(key);
+		s->removeKey(key);
 }
 
+const String &ConfigFile::getKey(const String &key, const String &section) const {
+	assert(isValidName(key));
+	assert(isValidName(section));
+	
+	const Section *s = getSection(section);
+	if (s){
+		const KeyValue *kv = s->getKey(key);
+		if (kv)
+			return kv->value;
+	}
+#if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__))
+	return String::emptyString;
+#else
+	return ConfMan._emptyString;
+#endif
+}
+	
 bool ConfigFile::getKey(const String &key, const String &section, String &value) const {
 	assert(isValidName(key));
 	assert(isValidName(section));
-
+	
 	const Section *s = getSection(section);
 	if (!s)
 		return false;
@@ -293,17 +326,17 @@
 	assert(isValidName(section));
 	// TODO: Verify that value is valid, too. In particular, it shouldn't
 	// contain CR or LF...
-
+	
 	Section *s = getSection(section);
 	if (!s) {
 		KeyValue newKV;
 		newKV.key = key;
 		newKV.value = value;
-
+		
 		Section newSection;
 		newSection.name = section;
 		newSection.keys.push_back(newKV);
-
+		
 		_sections.push_back(newSection);
 	} else {
 		s->setKey(key, value);
@@ -312,10 +345,10 @@
 
 const ConfigFile::SectionKeyList ConfigFile::getKeys(const String &section) const {
 	const Section *s = getSection(section);
-
+	
 	return s->getKeys();
 }
-
+	
 ConfigFile::Section *ConfigFile::getSection(const String &section) {
 	for (List<Section>::iterator i = _sections.begin(); i != _sections.end(); ++i) {
 		if (!scumm_stricmp(section.c_str(), i->name.c_str())) {
@@ -333,7 +366,22 @@
 	}
 	return 0;
 }
+	
+void ConfigFile::notifyObservers(int event, const String &section, const String &key){
+	List<Observer*>::iterator i;
+	
+	for(i=_observers.begin(); i!=_observers.end() ;++i) {
+		(*i)->configFileChanged(event, section, key);
+	}
+}
+	
+void ConfigFile::registerObserver(Observer *ob){
+	_observers.push_back(ob);
+}
 
+
+#pragma mark -
+
 bool ConfigFile::Section::hasKey(const String &key) const {
 	return getKey(key) != 0;
 }
@@ -344,6 +392,7 @@
 			return &(*i);
 		}
 	}
+	
 	return 0;
 }
 
@@ -354,7 +403,7 @@
 			return;
 		}
 	}
-
+	
 	KeyValue newKV;
 	newKV.key = key;
 	newKV.value = value;
@@ -368,6 +417,6 @@
 			return;
 		}
 	}
-}
+}	
 
 }	// End of namespace Common
Index: common/system.cpp
===================================================================
--- common/system.cpp	(revision 32664)
+++ common/system.cpp	(working copy)
@@ -135,7 +135,7 @@
 #endif
 
 FilesystemFactory *OSystem::getFilesystemFactory() {
-	#if defined(__amigaos4__) || defined(__DC__) || defined(__SYMBIAN32__) || defined(UNIX) || defined(WIN32) || defined(__WII__) || defined(__PSP__) || defined(__DS__)
+	#if defined(__amigaos4__) || defined(__DC__) || defined(__SYMBIAN32__) || defined(UNIX) || defined(WIN32) || defined(__WII__) || defined(__PSP__) || defined(__DS__) || defined(MACOSX)
 		// These ports already implement this function, so it should never be called.
 		return 0;
 	#elif defined(PALMOS_MODE)
Index: engines/engine.cpp
===================================================================
--- engines/engine.cpp	(revision 32664)
+++ engines/engine.cpp	(working copy)
@@ -52,7 +52,7 @@
 		_timer(_system->getTimerManager()),
 		_eventMan(_system->getEventManager()),
 		_saveFileMan(_system->getSavefileManager()),
-		_targetName(ConfMan.getActiveDomainName()),
+		_targetName(ConfMan.getActiveSectionName()),
 		_gameDataPath(ConfMan.get("path")),
 		_pauseLevel(0) {
 
@@ -77,18 +77,18 @@
 }
 
 void Engine::initCommonGFX(bool defaultTo1XScaler) {
-	const Common::ConfigManager::Domain *transientDomain = ConfMan.getDomain(Common::ConfigManager::kTransientDomain);
-	const Common::ConfigManager::Domain *gameDomain = ConfMan.getActiveDomain();
+	const Common::ConfigFile::Section *transientSection = ConfMan.getSection(Common::ConfigManager::kTransientSection);
+	const Common::ConfigFile::Section *gameSection = ConfMan.getActiveSection();
 
-	assert(transientDomain);
+	assert(transientSection);
 
 	const bool useDefaultGraphicsMode =
-		!transientDomain->contains("gfx_mode") &&
+		!transientSection->hasKey("gfx_mode") &&
 		(
-		!gameDomain ||
-		!gameDomain->contains("gfx_mode") ||
-		!scumm_stricmp(gameDomain->get("gfx_mode").c_str(), "normal") ||
-		!scumm_stricmp(gameDomain->get("gfx_mode").c_str(), "default")
+		!gameSection ||
+		!gameSection->hasKey("gfx_mode") ||
+		!scumm_stricmp(gameSection->getKey("gfx_mode")->value.c_str(), "normal") ||
+		!scumm_stricmp(gameSection->getKey("gfx_mode")->value.c_str(), "default")
 		);
 
 	// See if the game should default to 1x scaler
@@ -112,11 +112,11 @@
 	// we get here. Hence we only do something
 
 	// (De)activate aspect-ratio correction as determined by the config settings
-	if (gameDomain && gameDomain->contains("aspect_ratio"))
+	if (gameSection && gameSection->hasKey("aspect_ratio"))
 		_system->setFeatureState(OSystem::kFeatureAspectRatioCorrection, ConfMan.getBool("aspect_ratio"));
 
 	// (De)activate fullscreen mode as determined by the config settings
-	if (gameDomain && gameDomain->contains("fullscreen"))
+	if (gameSection && gameSection->hasKey("fullscreen"))
 		_system->setFeatureState(OSystem::kFeatureFullscreenMode, ConfMan.getBool("fullscreen"));
 }
 
Index: backends/saves/default/default-saves.cpp
===================================================================
--- backends/saves/default/default-saves.cpp	(revision 32664)
+++ backends/saves/default/default-saves.cpp	(working copy)
@@ -271,7 +271,7 @@
 	// Work around a bug (#999122) in the original 0.6.1 release of
 	// ScummVM, which would insert a bad savepath value into config files.
 	if (dir == "None") {
-		ConfMan.removeKey("savepath", ConfMan.getActiveDomainName());
+		ConfMan.removeKey("savepath", ConfMan.getActiveSectionName());
 		ConfMan.flushToDisk();
 		dir = ConfMan.get("savepath");
 	}
Index: backends/platform/sdl/sdl.cpp
===================================================================
--- backends/platform/sdl/sdl.cpp	(revision 32664)
+++ backends/platform/sdl/sdl.cpp	(working copy)
@@ -45,7 +45,7 @@
  */
 #if defined(__amigaos4__)
 	#include "backends/fs/amigaos4/amigaos4-fs-factory.h"
-#elif defined(UNIX)
+#elif defined(UNIX) || defined(MACOSX)
 	#include "backends/fs/posix/posix-fs-factory.h"
 #elif defined(WIN32)
 	#include "backends/fs/windows/windows-fs-factory.h"
Index: backends/platform/sdl/main.cpp
===================================================================
--- backends/platform/sdl/main.cpp	(revision 32664)
+++ backends/platform/sdl/main.cpp	(working copy)
@@ -31,7 +31,7 @@
 
 #include "backends/platform/sdl/sdl.h"
 #include "backends/plugins/sdl/sdl-provider.h"
-#include "base/main.h"
+#include "base/main.h" 
 
 #if defined(__SYMBIAN32__)
 #include "SymbianOs.h"
Index: base/main.cpp
===================================================================
--- base/main.cpp	(revision 32664)
+++ base/main.cpp	(working copy)
@@ -82,7 +82,7 @@
 	const EnginePlugin *plugin = 0;
 
 	// Make sure the gameid is set in the config manager, and that it is lowercase.
-	Common::String gameid(ConfMan.getActiveDomainName());
+	Common::String gameid(ConfMan.getActiveSectionName());
 	assert(!gameid.empty());
 	if (ConfMan.hasKey("gameid"))
 		gameid = ConfMan.get("gameid");
@@ -90,7 +90,7 @@
 	ConfMan.set("gameid", gameid);
 
 	// Query the plugins and find one that will handle the specified gameid
-	printf("User picked target '%s' (gameid '%s')...\n", ConfMan.getActiveDomainName().c_str(), gameid.c_str());
+	printf("User picked target '%s' (gameid '%s')...\n", ConfMan.getActiveSectionName().c_str(), gameid.c_str());
 	printf("  Looking for a plugin supporting this gameid... ");
 	GameDescriptor game = EngineMan.findGame(gameid, &plugin);
 
@@ -118,7 +118,7 @@
 #endif
 					&& gameDataPath.lastChar() != '\\') {
 		gameDataPath += '/';
-		ConfMan.set("path", gameDataPath, Common::ConfigManager::kTransientDomain);
+		ConfMan.set("path", gameDataPath, Common::ConfigManager::kTransientSection);
 	}
 
 	// We add the game "path" to the file search path via File::addDefaultDirectory(),
@@ -163,7 +163,7 @@
 		warning("%s failed to instantiate engine: %s (target '%s', path '%s')",
 			plugin->getName(),
 			errMsg,
-			ConfMan.getActiveDomainName().c_str(),
+			ConfMan.getActiveSectionName().c_str(),
 			path.c_str()
 			);
 		return 0;
@@ -176,7 +176,7 @@
 	if (caption.empty() && !desc.empty())
 		caption = desc;
 	if (caption.empty())
-		caption = ConfMan.getActiveDomainName();	// Use the domain (=target) name
+		caption = ConfMan.getActiveSectionName();	// Use the domain (=target) name
 	if (!caption.empty())	{
 		system.setWindowCaption(caption.c_str());
 	}
@@ -190,8 +190,8 @@
 	if (ConfMan.hasKey("extrapath"))
 		Common::File::addDefaultDirectoryRecursive(ConfMan.get("extrapath"));
 
-	if (ConfMan.hasKey("extrapath", Common::ConfigManager::kApplicationDomain))
-		Common::File::addDefaultDirectoryRecursive(ConfMan.get("extrapath", Common::ConfigManager::kApplicationDomain));
+	if (ConfMan.hasKey("extrapath", Common::ConfigManager::kApplicationSection))
+		Common::File::addDefaultDirectoryRecursive(ConfMan.getKey("extrapath", Common::ConfigManager::kApplicationSection));
 
 #ifdef DATA_PATH
 	// Add the global DATA_PATH to the directory search list
@@ -256,7 +256,7 @@
 	}
 
 	// Update the config file
-	ConfMan.set("versioninfo", gScummVMVersion, Common::ConfigManager::kApplicationDomain);
+	ConfMan.set("versioninfo", gScummVMVersion, Common::ConfigManager::kApplicationSection);
 
 
 	// Load and setup the debuglevel and the debug flags. We do this at the
@@ -287,20 +287,20 @@
 	system.initBackend();
 
 	// Unless a game was specified, show the launcher dialog
-	if (0 == ConfMan.getActiveDomain()) {
+	if (0 == ConfMan.getActiveSection()) {
 		launcherDialog(system);
 
 		// Discard any command line options. Those that affect the graphics
 		// mode etc. already have should have been handled by the backend at
 		// this point. And the others (like bootparam etc.) should not
 		// blindly be passed to the first game launched from the launcher.
-		ConfMan.getDomain(Common::ConfigManager::kTransientDomain)->clear();
+		ConfMan.getSection(Common::ConfigManager::kTransientSection)->clear();
 	}
 
 	// FIXME: We're now looping the launcher. This, of course, doesn't
 	// work as well as it should. In theory everything should be destroyed
 	// cleanly, so this is now enabled to encourage people to fix bits :)
-	while (0 != ConfMan.getActiveDomain()) {
+	while (0 != ConfMan.getActiveSection()) {
 		// Try to find a plugin which feels responsible for the specified game.
 		const EnginePlugin *plugin = detectPlugin();
 		if (plugin) {
@@ -318,10 +318,10 @@
 
 			// Discard any command line options. It's unlikely that the user
 			// wanted to apply them to *all* games ever launched.
-			ConfMan.getDomain(Common::ConfigManager::kTransientDomain)->clear();
+			ConfMan.getSection(Common::ConfigManager::kTransientSection)->clear();
 
 			// Clear the active config domain
-			ConfMan.setActiveDomain("");
+			ConfMan.setActiveSection("");
 
 			// PluginManager::instance().unloadPlugins();
 			PluginManager::instance().loadPlugins();
Index: base/commandLine.cpp
===================================================================
--- base/commandLine.cpp	(revision 32664)
+++ base/commandLine.cpp	(working copy)
@@ -580,11 +580,11 @@
 	       "-------------------- ------------------------------------------------------\n");
 
 	using namespace Common;
-	const ConfigManager::DomainMap &domains = ConfMan.getGameDomains();
-	ConfigManager::DomainMap::const_iterator iter;
-	for (iter = domains.begin(); iter != domains.end(); ++iter) {
-		Common::String name(iter->_key);
-		Common::String description(iter->_value.get("description"));
+	const ConfigManager::SectionRefList &sections = ConfMan.getGameSections();
+	ConfigManager::SectionRefList::const_iterator iter;
+	for (iter = sections.begin(); iter != sections.end(); ++iter) {
+		Common::String name((*iter)->name);
+		Common::String description((*iter)->getKey("description")->value);
 
 		if (description.empty()) {
 			// FIXME: At this point, we should check for a "gameid" override
@@ -607,12 +607,12 @@
 	g_system->initBackend();
 
 	// Grab the "target" domain, if any
-	const Common::ConfigManager::Domain *domain = ConfMan.getDomain(target);
+	const Common::ConfigFile::Section *section = ConfMan.getSection(target);
 
 	// Grab the gameid from the domain resp. use the target as gameid
 	Common::String gameid;
-	if (domain)
-		gameid = domain->get("gameid");
+	if (section)
+		gameid = section->getKey("gameid")->value;
 	if (gameid.empty())
 		gameid = target;
 	gameid.toLowercase();	// Normalize it to lower case
@@ -648,13 +648,13 @@
 	// for the given path. It then prints out the result and also checks
 	// whether the result agrees with the settings of the target.
 
-	const Common::ConfigManager::DomainMap &domains = ConfMan.getGameDomains();
-	Common::ConfigManager::DomainMap::const_iterator iter = domains.begin();
+	const Common::ConfigManager::SectionRefList &sections = ConfMan.getGameSections();
+	Common::ConfigManager::SectionRefList::const_iterator iter;
 	int success = 0, failure = 0;
-	for (iter = domains.begin(); iter != domains.end(); ++iter) {
-		Common::String name(iter->_key);
-		Common::String gameid(iter->_value.get("gameid"));
-		Common::String path(iter->_value.get("path"));
+	for (iter = sections.begin(); iter != sections.end(); ++iter) {
+		Common::String name((*iter)->name);
+		Common::String gameid((*iter)->getKey("gameid")->value);
+		Common::String path((*iter)->getKey("path")->value);
 		printf("Looking at target '%s', gameid '%s', path '%s' ...\n",
 				name.c_str(), gameid.c_str(), path.c_str());
 		if (path.empty()) {
@@ -705,7 +705,7 @@
 				   Common::getPlatformCode(x->platform()));
 		}
 	}
-	int total = domains.size();
+	int total = sections.size();
 	printf("Detector test run: %d fail, %d success, %d skipped, out of %d\n",
 			failure, success, total - failure - success, total);
 }
@@ -746,7 +746,7 @@
 	// whether there is a gameid matching that name.
 	if (!command.empty()) {
 		GameDescriptor gd = EngineMan.findGame(command);
-		if (ConfMan.hasGameDomain(command) || !gd.gameid().empty()) {
+		if (ConfMan.hasGameSection(command) || !gd.gameid().empty()) {
 			bool idCameFromCommandLine = false;
 
 			// WORKAROUND: Fix for bug #1719463: "DETECTOR: Launching
@@ -755,11 +755,11 @@
 			// We designate gameids which come strictly from command line
 			// so AdvancedDetector will not save config file with invalid
 			// gameid in case target autoupgrade was performed
-			if (!ConfMan.hasGameDomain(command)) {
+			if (!ConfMan.hasGameSection(command)) {
 				idCameFromCommandLine = true;
 			}
 
-			ConfMan.setActiveDomain(command);
+			ConfMan.setActiveSection(command);
 
 			if (idCameFromCommandLine)
 				ConfMan.set("id_came_from_command_line", "1");
@@ -801,7 +801,7 @@
 				*c = '_';
 
 		// Store it into ConfMan.
-		ConfMan.set(key, value, Common::ConfigManager::kTransientDomain);
+		ConfMan.set(key, value, Common::ConfigManager::kTransientSection);
 	}
 
 	return true;
