aboutsummaryrefslogtreecommitdiff
path: root/backends/keymapper
diff options
context:
space:
mode:
Diffstat (limited to 'backends/keymapper')
-rw-r--r--backends/keymapper/action.cpp60
-rw-r--r--backends/keymapper/action.h115
-rw-r--r--backends/keymapper/hardware-key.h129
-rw-r--r--backends/keymapper/keymap-manager.cpp168
-rw-r--r--backends/keymapper/keymap-manager.h97
-rw-r--r--backends/keymapper/keymap.cpp164
-rw-r--r--backends/keymapper/keymap.h135
-rw-r--r--backends/keymapper/keymapper.cpp146
-rw-r--r--backends/keymapper/keymapper.h131
9 files changed, 1145 insertions, 0 deletions
diff --git a/backends/keymapper/action.cpp b/backends/keymapper/action.cpp
new file mode 100644
index 0000000000..eefd482de7
--- /dev/null
+++ b/backends/keymapper/action.cpp
@@ -0,0 +1,60 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* $URL$
+* $Id$
+*
+*/
+
+#include "backends/keymapper/action.h"
+#include "backends/keymapper/keymap.h"
+
+namespace Common {
+
+Action::Action(int32 i, String des,
+ ActionCategory cat, ActionType typ,
+ int pri, int grp, int flg) {
+ id = i;
+ description = des;
+ category = cat;
+ type = typ;
+ priority = pri;
+ group = grp;
+ flags = flg;
+ _hwKey = 0;
+ _parent = 0;
+}
+
+void Action::setParent(Keymap *parent) {
+ _parent = parent;
+}
+
+void Action::mapKey(const HardwareKey *key) {
+ assert(_parent);
+ if (_hwKey) _parent->unregisterMapping(this);
+ _hwKey = key;
+ if (_hwKey) _parent->registerMapping(this, key);
+}
+
+const HardwareKey *Action::getMappedKey() const {
+ return _hwKey;
+}
+
+} // end of namespace Common
diff --git a/backends/keymapper/action.h b/backends/keymapper/action.h
new file mode 100644
index 0000000000..d9ecb873b3
--- /dev/null
+++ b/backends/keymapper/action.h
@@ -0,0 +1,115 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* $URL$
+* $Id$
+*
+*/
+
+#ifndef COMMON_ACTION
+#define COMMON_ACTION
+
+#include "common/events.h"
+#include "common/func.h"
+#include "common/list.h"
+#include "common/str.h"
+
+namespace Common {
+
+struct HardwareKey;
+class Keymap;
+
+
+enum ActionType {
+ kGenericActionType,
+
+ // common actions
+ kDirectionUpAction,
+ kDirectionDownAction,
+ kDirectionLeftAction,
+ kDirectionRightAction,
+ kLeftClickAction,
+ kRightClickAction,
+ kSaveAction,
+ kMenuAction,
+ kQuitAction,
+ kVirtualKeyboardAction,
+ kKeyRemapAction,
+ kVolumeUpAction,
+ kVolumeDownAction,
+
+
+ kActionTypeMax
+};
+
+enum ActionCategory {
+ kGenericActionCategory,
+ // classes of action - probably need to be slightly more specific than this
+ kInGameAction, // effects the actual gameplay
+ kSystemAction, //show a menu / change volume / etc
+
+ kActionCategoryMax
+};
+
+struct Action {
+ /** unique id used for saving/loading to config */
+ int32 id;
+ /** Human readable description */
+ String description;
+
+ /** Events to be sent when mapped key is pressed */
+ List<Event> events;
+ ActionCategory category;
+ ActionType type;
+ int priority;
+ int group;
+ int flags;
+
+private:
+ /** Hardware key that is mapped to this Action */
+ const HardwareKey *_hwKey;
+ Keymap *_parent;
+
+public:
+ Action( int32 id,
+ String des = "",
+ ActionCategory cat = kGenericActionCategory,
+ ActionType typ = kGenericActionType,
+ int pri = 0, int grp = 0, int flg = 0 );
+
+ void addEvent(const Event &evt) { events.push_back(evt); }
+ void setParent(Keymap *parent);
+ void mapKey(const HardwareKey *key);
+ const HardwareKey *getMappedKey() const;
+
+};
+
+struct ActionPriorityComp : public BinaryFunction<Action, Action, bool> {
+ bool operator()(const Action *x, const Action *y) const {
+ return x->priority > y->priority;
+ }
+ bool operator()(const Action &x, const Action &y) const {
+ return x.priority > y.priority;
+ }
+};
+
+} // end of namespace Common
+
+#endif
diff --git a/backends/keymapper/hardware-key.h b/backends/keymapper/hardware-key.h
new file mode 100644
index 0000000000..40fb2a0cbd
--- /dev/null
+++ b/backends/keymapper/hardware-key.h
@@ -0,0 +1,129 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* $URL$
+* $Id$
+*
+*/
+
+#ifndef COMMON_HARDWAREKEY
+#define COMMON_HARDWAREKEY
+
+#include "backends/keymapper/action.h"
+
+namespace Common {
+
+/**
+* Describes an available hardware key
+*/
+struct HardwareKey {
+ /** unique id used for saving/loading to config */
+ int32 id;
+ /** Human readable description */
+ String description;
+ /**
+ * The KeyState that is generated by the back-end
+ * when this hardware key is pressed.
+ */
+ KeyState key;
+
+ ActionCategory preferredCategory;
+ ActionType preferredType;
+ int16 group;
+
+ HardwareKey(int32 i, KeyState ks = KeyState(), String des = "",
+ ActionCategory cat = kGenericActionCategory,
+ ActionType ty = kGenericActionType, int gr = 0) {
+ id = i;
+ key = ks;
+ description = des;
+ preferredCategory = cat;
+ preferredType = ty;
+ group = gr;
+ }
+};
+
+
+/**
+ * Simple class to encapsulate a device's set of HardwareKeys.
+ * Each device should extend this and call addHardwareKey a number of times
+ * in its constructor to define the device's available keys.
+ */
+class HardwareKeySet {
+public:
+
+ HardwareKeySet() {}
+ virtual ~HardwareKeySet() {
+ List<HardwareKey*>::iterator it;
+ for (it = _keys.begin(); it != _keys.end(); it++)
+ delete *it;
+ }
+
+ void addHardwareKey(HardwareKey *key) {
+ checkForKey(key);
+ _keys.push_back(key);
+ }
+
+ const HardwareKey *findHardwareKey(int32 id) const {
+ List<HardwareKey*>::iterator it;
+ for (it = _keys.begin(); it != _keys.end(); it++) {
+ if ((*it)->id == id)
+ return (*it);
+ }
+ return 0;
+ }
+
+ const HardwareKey *findHardwareKey(const KeyState& keystate) const {
+ List<HardwareKey*>::iterator it;
+ for (it = _keys.begin(); it != _keys.end(); it++) {
+ if ((*it)->key == keystate)
+ return (*it);
+ }
+ return 0;
+ }
+
+ List<HardwareKey*> getHardwareKeys() const {
+ return _keys;
+ }
+
+ uint count() const {
+ return _keys.size();
+ }
+
+
+private:
+
+ void checkForKey(HardwareKey *key) {
+ List<HardwareKey*>::iterator it;
+ for (it = _keys.begin(); it != _keys.end(); it++) {
+ if ((*it)->id == key->id)
+ error("Error adding HardwareKey '%s' - id of %d already in use!", key->description.c_str(), key->id);
+ else if ((*it)->key == key->key)
+ error("Error adding HardwareKey '%s' - key already in use!", key->description.c_str());
+ }
+ }
+
+ List<HardwareKey*> _keys;
+};
+
+
+} // end of namespace Common
+
+#endif
diff --git a/backends/keymapper/keymap-manager.cpp b/backends/keymapper/keymap-manager.cpp
new file mode 100644
index 0000000000..c8b4420289
--- /dev/null
+++ b/backends/keymapper/keymap-manager.cpp
@@ -0,0 +1,168 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* $URL$
+* $Id$
+*
+*/
+
+#include "backends/keymapper/keymap-manager.h"
+#include "common/algorithm.h"
+
+namespace Common {
+
+void KeymapManager::Domain::setDefaultKeymap(Keymap *map) {
+ delete _defaultKeymap;
+ _defaultKeymap = map;
+}
+
+void KeymapManager::Domain::addKeymap(const String& name, Keymap *map) {
+ KeymapMap::iterator it = _keymaps.find(name);
+ if (it != _keymaps.end())
+ delete _keymaps[name];
+ _keymaps[name] = map;
+}
+
+void KeymapManager::Domain::deleteAllKeyMaps() {
+ KeymapMap::iterator it;
+ for (it = _keymaps.begin(); it != _keymaps.end(); it++) {
+ //it->_value->saveMappings(_configDomain, it->_key);
+ delete it->_value;
+ }
+ _keymaps.clear();
+ if (_defaultKeymap) {
+ //_defaultKeymap->saveMappings(_configDomain, "default");
+ delete _defaultKeymap;
+ }
+}
+
+Keymap *KeymapManager::Domain::getDefaultKeymap() {
+ return _defaultKeymap;
+}
+
+Keymap *KeymapManager::Domain::getKeymap(const String& name) {
+ KeymapMap::iterator it = _keymaps.find(name);
+ if (it != _keymaps.end())
+ return it->_value;
+ else
+ return 0;
+}
+
+KeymapManager::KeymapManager() {
+ _hardwareKeys = 0;
+ _globalDomain.setConfigDomain(ConfMan.getDomain(ConfigManager::kApplicationDomain));
+}
+
+KeymapManager::~KeymapManager() {
+ delete _hardwareKeys;
+}
+
+void KeymapManager::registerHardwareKeySet(HardwareKeySet *keys) {
+ if (_hardwareKeys)
+ error("Hardware key set already registered!");
+ _hardwareKeys = keys;
+}
+
+void KeymapManager::registerDefaultGlobalKeymap(Keymap *map) {
+ ConfigManager::Domain *dom = ConfMan.getDomain(ConfigManager::kApplicationDomain);
+ assert(dom);
+
+ initKeymap(dom, "default", map);
+ _globalDomain.setDefaultKeymap(map);
+}
+
+void KeymapManager::registerGlobalKeymap(const String& name, Keymap *map) {
+ ConfigManager::Domain *dom = ConfMan.getDomain(ConfigManager::kApplicationDomain);
+ assert(dom);
+
+ initKeymap(dom, name, map);
+ _globalDomain.addKeymap(name, map);
+}
+
+void KeymapManager::refreshGameDomain() {
+ if (_gameDomain.getConfigDomain() != ConfMan.getActiveDomain()) {
+ _gameDomain.deleteAllKeyMaps();
+ _gameDomain.setConfigDomain(ConfMan.getActiveDomain());
+ }
+}
+
+void KeymapManager::registerDefaultGameKeymap(Keymap *map) {
+ refreshGameDomain();
+ initKeymap(_gameDomain.getConfigDomain(), "default", map);
+ _gameDomain.setDefaultKeymap(map);
+}
+
+void KeymapManager::registerGameKeymap(const String& name, Keymap *map) {
+ refreshGameDomain();
+ initKeymap(_gameDomain.getConfigDomain(), name, map);
+ _gameDomain.addKeymap(name, map);
+}
+
+void KeymapManager::initKeymap(ConfigManager::Domain *domain,
+ const String& name,
+ Keymap *map) {
+ map->loadMappings(domain, name, _hardwareKeys);
+ if (map->isComplete(_hardwareKeys) == false)
+ automaticMap(map);
+}
+
+void KeymapManager::automaticMap(Keymap *map) {
+ List<Action*> actions(map->getActions()), unmapped;
+ List<Action*>::iterator actIt;
+ List<HardwareKey*> keys = _hardwareKeys->getHardwareKeys();
+ List<HardwareKey*>::iterator keyIt, selectedKey;
+
+ // sort by priority
+ ActionPriorityComp priorityComp;
+ sort(actions.begin(), actions.end(), priorityComp);
+
+ for (actIt = actions.begin(); actIt != actions.end(); actIt++) {
+ selectedKey = keys.end();
+ Action *act = *actIt;
+ for (keyIt = keys.begin(); keyIt != keys.end(); keyIt++) {
+ if ((*keyIt)->preferredType == act->type) {
+ selectedKey = keyIt;
+ break;
+ } else if ((*keyIt)->preferredCategory == act->category && selectedKey == keys.end()) {
+ selectedKey = keyIt;
+ }
+ }
+ if (selectedKey != keys.end()) {
+ act->mapKey(*selectedKey);
+ keys.erase(selectedKey);
+ } else
+ unmapped.push_back(act);
+ }
+
+ actIt = unmapped.begin();
+ keyIt = keys.begin();
+ while (actIt != unmapped.end() && keyIt != keys.end())
+ (*actIt)->mapKey(*keyIt);
+
+}
+
+Keymap *KeymapManager::getKeymap(const String& name) {
+ Keymap *keymap = _gameDomain.getKeymap(name);
+ if (!keymap)
+ _globalDomain.getKeymap(name);
+ return keymap;
+}
+
+} // end of namespace Common
diff --git a/backends/keymapper/keymap-manager.h b/backends/keymapper/keymap-manager.h
new file mode 100644
index 0000000000..171da3ac5e
--- /dev/null
+++ b/backends/keymapper/keymap-manager.h
@@ -0,0 +1,97 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* $URL$
+* $Id$
+*
+*/
+
+#ifndef COMMON_KEYMAP_MANAGER
+#define COMMON_KEYMAP_MANAGER
+
+#include "backends/keymapper/hardware-key.h"
+#include "backends/keymapper/keymap.h"
+#include "common/hash-str.h"
+#include "common/hashmap.h"
+
+namespace Common {
+
+class KeymapManager {
+public:
+
+ class Domain {
+ public:
+ Domain() : _defaultKeymap(0), _configDomain(0) {}
+ ~Domain() {
+ deleteAllKeyMaps();
+ }
+
+ void setConfigDomain(ConfigManager::Domain *confDom) {
+ _configDomain = confDom;
+ }
+ ConfigManager::Domain *getConfigDomain() {
+ return _configDomain;
+ }
+
+ void setDefaultKeymap(Keymap *map);
+ void addKeymap(const String& name, Keymap *map);
+
+ void deleteAllKeyMaps();
+
+ Keymap *getDefaultKeymap();
+ Keymap *getKeymap(const String& name);
+
+ private:
+ typedef HashMap<String, Keymap*,
+ IgnoreCase_Hash, IgnoreCase_EqualTo> KeymapMap;
+
+ ConfigManager::Domain *_configDomain;
+ Keymap *_defaultKeymap;
+ KeymapMap _keymaps;
+ };
+
+ KeymapManager();
+ ~KeymapManager();
+
+ void registerHardwareKeySet(HardwareKeySet *keys);
+
+ void registerDefaultGlobalKeymap(Keymap *map);
+ void registerGlobalKeymap(const String& name, Keymap *map);
+
+ void refreshGameDomain();
+ void registerDefaultGameKeymap(Keymap *map);
+ void registerGameKeymap(const String& name, Keymap *map);
+
+ Keymap *getKeymap(const String& name);
+
+private:
+
+ void initKeymap(ConfigManager::Domain *domain, const String& name, Keymap *keymap);
+ void automaticMap(Keymap *map);
+
+ Domain _globalDomain;
+ Domain _gameDomain;
+
+ HardwareKeySet *_hardwareKeys;
+};
+
+} // end of namespace Common
+
+#endif
diff --git a/backends/keymapper/keymap.cpp b/backends/keymapper/keymap.cpp
new file mode 100644
index 0000000000..3f190dcd48
--- /dev/null
+++ b/backends/keymapper/keymap.cpp
@@ -0,0 +1,164 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* $URL$
+* $Id$
+*
+*/
+
+#include "backends/keymapper/keymap.h"
+#include "backends/keymapper/hardware-key.h"
+
+namespace Common {
+
+Keymap::Keymap(const Keymap& km) : _actions(km._actions), _keymap() {
+ List<Action*>::iterator it;
+ for (it = _actions.begin(); it != _actions.end(); it++) {
+ const HardwareKey *hwKey = (*it)->getMappedKey();
+ if (hwKey) {
+ _keymap[hwKey->key] = *it;
+ }
+ }
+}
+
+void Keymap::addAction(Action *action) {
+ if (findAction(action->id))
+ error("Action with id %d already in KeyMap!", action->id);
+ action->setParent(this);
+ _actions.push_back(action);
+}
+
+void Keymap::registerMapping(Action *action, const HardwareKey *hwKey) {
+ HashMap<KeyState, Action*>::iterator it;
+ it = _keymap.find(hwKey->key);
+ // if key is already mapped to an action then un-map it
+ if (it != _keymap.end())
+ it->_value->mapKey(0);
+
+ _keymap[hwKey->key] = action;
+}
+
+void Keymap::unregisterMapping(Action *action) {
+ const HardwareKey *hwKey = action->getMappedKey();
+ if (hwKey)
+ _keymap[hwKey->key] = 0;
+}
+
+Action *Keymap::getAction(int32 id) {
+ return findAction(id);
+}
+
+Action *Keymap::findAction(int32 id) {
+ List<Action*>::iterator it;
+ for (it = _actions.begin(); it != _actions.end(); it++) {
+ if ((*it)->id == id)
+ return *it;
+ }
+ return 0;
+}
+
+const Action *Keymap::findAction(int32 id) const {
+ List<Action*>::const_iterator it;
+ for (it = _actions.begin(); it != _actions.end(); it++) {
+ if ((*it)->id == id)
+ return *it;
+ }
+ return 0;
+}
+
+Action *Keymap::getMappedAction(const KeyState& ks) const {
+ HashMap<KeyState, Action*>::iterator it;
+ it = _keymap.find(ks);
+ if (it == _keymap.end())
+ return 0;
+ else
+ return it->_value;
+}
+
+void Keymap::loadMappings(ConfigManager::Domain *domain, const String& name, const HardwareKeySet *hwKeys) {
+ ConfigManager::Domain::iterator it;
+ String prefix = "km_" + name + "_";
+ for (it = domain->begin(); it != domain->end(); it++) {
+ const String& key = it->_key;
+ if (!key.hasPrefix(prefix.c_str()))
+ continue;
+
+ // parse Action ID
+ const char *actionIdStart = key.c_str() + prefix.size();
+ char *err;
+ int32 actionId = (int32) strtol(actionIdStart, &err, 0);
+ if (err == actionIdStart) {
+ warning("'%s' is not a valid Action ID", err);
+ continue;
+ }
+ Action *ua = getAction(actionId);
+ if (!ua) {
+ warning("'%s' keymap does not contain Action with ID %d",
+ name.c_str(), (int)actionId);
+ continue;
+ }
+
+ // parse HardwareKey ID
+ int32 hwKeyId = (int32) strtol(it->_value.c_str(), &err, 0);
+ if (err == it->_value.c_str()) {
+ warning("'%s' is not a valid HardwareKey ID", err);
+ continue;
+ }
+ const HardwareKey *hwKey = hwKeys->findHardwareKey(hwKeyId);
+ if (!hwKey) {
+ warning("HardwareKey with ID %d not known", (int)hwKeyId);
+ continue;
+ }
+
+ ua->mapKey(hwKey);
+ }
+}
+
+void Keymap::saveMappings(ConfigManager::Domain *domain, const String& name) {
+ if (!domain) return;
+ List<Action*>::const_iterator it;
+ char buf[11];
+ for (it = _actions.begin(); it != _actions.end(); it++) {
+ String key("km_");
+ sprintf(buf, "%d", (*it)->id);
+ key += name + "_" + buf;
+ if ((*it)->getMappedKey())
+ sprintf(buf, "%d", (*it)->getMappedKey()->id);
+ else
+ strcpy(buf, "");
+ domain->setVal(key, buf);
+ }
+}
+
+bool Keymap::isComplete(const HardwareKeySet *hwKeys) {
+ List<Action*>::iterator it;
+ bool allMapped = true;
+ uint numberMapped = 0;
+ for (it = _actions.begin(); it != _actions.end(); it++) {
+ if ((*it)->getMappedKey()) {
+ numberMapped++;
+ } else {
+ allMapped = false;
+ }
+ }
+ return allMapped || (numberMapped == hwKeys->count());
+}
+
+} // end of namespace Common
diff --git a/backends/keymapper/keymap.h b/backends/keymapper/keymap.h
new file mode 100644
index 0000000000..21904397a1
--- /dev/null
+++ b/backends/keymapper/keymap.h
@@ -0,0 +1,135 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* $URL$
+* $Id$
+*
+*/
+
+#ifndef COMMON_KEYMAP
+#define COMMON_KEYMAP
+
+#include "common/config-manager.h"
+#include "common/func.h"
+#include "common/hashmap.h"
+#include "common/keyboard.h"
+#include "common/list.h"
+#include "backends/keymapper/action.h"
+
+namespace Common {
+
+struct HardwareKey;
+class HardwareKeySet;
+
+/**
+ * Hash function for KeyState
+ */
+template<> struct Hash<KeyState>
+ : public UnaryFunction<KeyState, uint> {
+
+ uint operator()(const KeyState &val) const {
+ return (uint)(val.keycode * (val.flags << 1));
+ }
+};
+
+class Keymap {
+public:
+ Keymap() {}
+ Keymap(const Keymap& km);
+
+public:
+ /**
+ * Adds a new Action to this Map,
+ * adding it at the back of the internal array
+ * @param action the Action to add
+ */
+ void addAction(Action *action);
+
+ /**
+ * Retrieves the Action with the given id
+ * @param id id of Action to retrieve
+ * @return Pointer to the Action or 0 if not found
+ */
+ Action *getAction(int32 id);
+
+ /**
+ * Get a read-only array of all the Actions contained in this Keymap
+ */
+ const List<Action*>& getActions() const { return _actions; }
+
+ /**
+ * Find the Action that a key is mapped to
+ * @param key the key that is mapped to the required Action
+ * @return a pointer to the Action or 0 if no
+ */
+ Action *getMappedAction(const KeyState& ks) const;
+
+ /**
+ * Load this keymap's mappings from the given config domain and hardware key set
+ * @param domain config domain to load keymap from
+ * @param name name of the keymap to load
+ * @param hwKeys the set to retrieve hardware key pointers from
+ */
+ void loadMappings(ConfigManager::Domain *domain, const String& name, const HardwareKeySet *hwKeys);
+
+ /**
+ * Save this keymap's mappings to the given config domain
+ * @param domain config domain to save keymap to
+ * @param name name to save the keymap under
+ */
+ void saveMappings(ConfigManager::Domain *domain, const String& name);
+
+ /**
+ * Returns true if all UserAction's in Keymap are mapped, or,
+ * all HardwareKey's from the given set have been used up.
+ */
+ bool isComplete(const HardwareKeySet *hwKeys);
+
+private:
+ friend struct Action;
+ /**
+ * Registers a HardwareKey to the given Action
+ * @param action Action in this Keymap
+ * @param key pointer to HardwareKey to map
+ * @see Action::mapKey
+ */
+ void registerMapping(Action *action, const HardwareKey *key);
+
+ /**
+ * Unregisters a HardwareKey from the given Action (if one is mapped)
+ * @param action Action in this Keymap
+ * @see Action::mapKey
+ */
+ void unregisterMapping(Action *action);
+
+ Action *findAction(int32 id);
+ const Action *findAction(int32 id) const;
+
+ void internalMapKey(Action *action, HardwareKey *hwKey);
+
+ List<Action*> _actions;
+ HashMap<KeyState, Action*> _keymap;
+
+};
+
+
+} // end of namespace Common
+
+#endif
diff --git a/backends/keymapper/keymapper.cpp b/backends/keymapper/keymapper.cpp
new file mode 100644
index 0000000000..fb1f72e84e
--- /dev/null
+++ b/backends/keymapper/keymapper.cpp
@@ -0,0 +1,146 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* $URL$
+* $Id$
+*
+*/
+
+#include "backends/keymapper/keymapper.h"
+#include "common/config-manager.h"
+namespace Common {
+
+Keymapper::Keymapper(EventManager *evtMgr) {
+ _eventMan = evtMgr;
+ _keymapMan = new KeymapManager();
+}
+
+Keymapper::~Keymapper() {
+ delete _keymapMan;
+}
+
+void Keymapper::registerHardwareKeySet(HardwareKeySet *keys) {
+ _keymapMan->registerHardwareKeySet(keys);
+}
+
+void Keymapper::addGlobalKeymap(const String& name, Keymap *keymap) {
+ _keymapMan->registerGlobalKeymap(name, keymap);
+}
+
+void Keymapper::setDefaultGlobalKeymap(Keymap *keymap) {
+ _keymapMan->registerDefaultGlobalKeymap(keymap);
+ pushKeymap(keymap, false);
+}
+
+void Keymapper::addGameKeymap(const String& name, Keymap *keymap) {
+ if (ConfMan.getActiveDomain() == 0)
+ error("Call to Keymapper::initGame when no game loaded");
+
+ _keymapMan->registerGameKeymap(name, keymap);
+}
+
+void Keymapper::setDefaultGameKeymap(Keymap *keymap) {
+ if (ConfMan.getActiveDomain() == 0)
+ error("Call to Keymapper::initGame when no game loaded");
+
+ _keymapMan->registerDefaultGameKeymap(keymap);
+ pushKeymap(keymap, true);
+}
+
+bool Keymapper::pushKeymap(const String& name, bool inherit) {
+ Keymap *newMap = _keymapMan->getKeymap(name);
+ if (!newMap) {
+ warning("Keymap '%s' not registered", name.c_str());
+ return false;
+ }
+ pushKeymap(newMap, inherit);
+ return true;
+}
+
+void Keymapper::pushKeymap(Keymap *newMap, bool inherit) {
+ MapRecord mr;
+ mr.inherit = inherit;
+ mr.keymap = newMap;
+ _activeMaps.push(mr);
+}
+
+void Keymapper::popKeymap() {
+ if (!_activeMaps.empty())
+ _activeMaps.pop();
+}
+
+bool Keymapper::mapKeyDown(const KeyState& key) {
+ return mapKey(key, true);
+}
+
+bool Keymapper::mapKeyUp(const KeyState& key) {
+ return mapKey(key, false);
+}
+
+bool Keymapper::mapKey(const KeyState& key, bool isKeyDown) {
+ if (_activeMaps.empty()) return false;
+
+ Action *action = 0;
+ for (int i = _activeMaps.size() - 1; !action && i >= 0; i++) {
+ MapRecord mr = _activeMaps[i];
+ action = mr.keymap->getMappedAction(key);
+ if (mr.inherit == false) break;
+ }
+ if (!action) return false;
+
+ List<Event>::iterator it;
+ for (it = action->events.begin(); it != action->events.end(); it++) {
+ Event evt = *it;
+ bool pushEvent = true;
+ switch (evt.type) {
+ case EVENT_KEYDOWN:
+ if (!isKeyDown) evt.type = EVENT_KEYUP;
+ break;
+ case EVENT_KEYUP:
+ if (isKeyDown) evt.type = EVENT_KEYDOWN;
+ break;
+ case EVENT_LBUTTONDOWN:
+ if (!isKeyDown) evt.type = EVENT_LBUTTONUP;
+ break;
+ case EVENT_LBUTTONUP:
+ if (isKeyDown) evt.type = EVENT_LBUTTONDOWN;
+ break;
+ case EVENT_RBUTTONDOWN:
+ if (!isKeyDown) evt.type = EVENT_RBUTTONUP;
+ break;
+ case EVENT_RBUTTONUP:
+ if (isKeyDown) evt.type = EVENT_RBUTTONDOWN;
+ break;
+ case EVENT_MBUTTONDOWN:
+ if (!isKeyDown) evt.type = EVENT_MBUTTONUP;
+ break;
+ case EVENT_MBUTTONUP:
+ if (isKeyDown) evt.type = EVENT_MBUTTONDOWN;
+ break;
+ default:
+ // don't deliver other events on key up
+ if (!isKeyDown) pushEvent = false;
+ }
+ if (pushEvent) _eventMan->pushEvent(evt);
+ }
+ return true;
+}
+
+} // end of namespace Common
diff --git a/backends/keymapper/keymapper.h b/backends/keymapper/keymapper.h
new file mode 100644
index 0000000000..1052903b77
--- /dev/null
+++ b/backends/keymapper/keymapper.h
@@ -0,0 +1,131 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+* $URL$
+* $Id$
+*
+*/
+
+#ifndef COMMON_KEYMAPPER
+#define COMMON_KEYMAPPER
+
+#include "common/events.h"
+#include "common/list.h"
+#include "common/stack.h"
+#include "backends/keymapper/hardware-key.h"
+#include "backends/keymapper/keymap.h"
+#include "backends/keymapper/keymap-manager.h"
+
+namespace Common {
+
+class Keymapper {
+public:
+
+ Keymapper(EventManager *eventMan);
+ ~Keymapper();
+
+ /**
+ * Registers a HardwareKeySet with the Keymapper
+ * @note should only be called once (during backend initialisation)
+ */
+ void registerHardwareKeySet(HardwareKeySet *keys);
+
+
+ /**
+ * Add a general keymap to the global domain.
+ * If a saved key setup exists for it in the ini file it will be used.
+ * Else, the key setup will be automatically mapped.
+ */
+ void addGlobalKeymap(const String& name, Keymap *keymap);
+
+ /**
+ * Sets the default keymap for the global domain.
+ */
+ void setDefaultGlobalKeymap(Keymap *keymap);
+
+ /**
+ * Add a general keymap to the game domain.
+ * @see addGlobalKeyMap
+ * @note initGame() should be called before any game keymaps are added.
+ */
+ void addGameKeymap(const String& name, Keymap *keymap);
+
+ /**
+ * Sets the default keymap for the game domain.
+ */
+ void setDefaultGameKeymap(Keymap *keymap);
+
+ /**
+ * Push a new keymap to the top of the active stack, activating it for use.
+ * @param name name of the keymap to push
+ * @param inherit if true
+ * @return true if successful
+ */
+ bool pushKeymap(const String& name, bool inherit = false);
+
+ /**
+ * Pop the active keymap off the stack.
+ */
+ void popKeymap();
+
+ /**
+ * @brief Map a key press event.
+ * If the active keymap contains a Action mapped to the given key, then
+ * the Action's events are pushed into the EventManager's event queue.
+ * @param key key that was pressed
+ * @param isKeyDown true for key down, false for key up
+ * @return true if key was mapped
+ */
+ bool mapKey(const KeyState& key, bool isKeyDown);
+
+ /**
+ * @brief Map a key down event.
+ * @see mapKey
+ */
+ bool mapKeyDown(const KeyState& key);
+
+ /**
+ * @brief Map a key up event.
+ * @see mapKey
+ */
+ bool mapKeyUp(const KeyState& key);
+
+private:
+
+ void pushKeymap(Keymap *newMap, bool inherit);
+
+ typedef List<HardwareKey*>::iterator Iterator;
+
+ EventManager *_eventMan;
+ KeymapManager *_keymapMan;
+
+
+ struct MapRecord {
+ Keymap* keymap;
+ bool inherit;
+ };
+
+ Stack<MapRecord> _activeMaps;
+
+};
+
+} // end of namespace Common
+
+#endif