From 2645ca48ad9bc219b43ab88cc5b071952297a992 Mon Sep 17 00:00:00 2001 From: Stephen Kennedy Date: Thu, 7 Aug 2008 16:38:39 +0000 Subject: * Moved VK code into backends/vkeybd * Moved Keymapper code into backends/keymapper svn-id: r33681 --- backends/common/action.cpp | 60 ---- backends/common/action.h | 115 -------- backends/common/hardware-key.h | 129 --------- backends/common/keymap-manager.cpp | 168 ----------- backends/common/keymap-manager.h | 97 ------- backends/common/keymap.cpp | 164 ----------- backends/common/keymap.h | 135 --------- backends/common/keymapper.cpp | 146 ---------- backends/common/keymapper.h | 131 --------- backends/common/virtual-keyboard-gui.cpp | 378 ------------------------ backends/common/virtual-keyboard-gui.h | 108 ------- backends/common/virtual-keyboard-parser.cpp | 430 ---------------------------- backends/common/virtual-keyboard-parser.h | 217 -------------- backends/common/virtual-keyboard.cpp | 347 ---------------------- backends/common/virtual-keyboard.h | 218 -------------- backends/events/default/default-events.cpp | 4 +- backends/keymapper/action.cpp | 60 ++++ backends/keymapper/action.h | 115 ++++++++ backends/keymapper/hardware-key.h | 129 +++++++++ backends/keymapper/keymap-manager.cpp | 168 +++++++++++ backends/keymapper/keymap-manager.h | 97 +++++++ backends/keymapper/keymap.cpp | 164 +++++++++++ backends/keymapper/keymap.h | 135 +++++++++ backends/keymapper/keymapper.cpp | 146 ++++++++++ backends/keymapper/keymapper.h | 131 +++++++++ backends/module.mk | 16 +- backends/platform/sdl/events.cpp | 2 +- backends/vkeybd/image-map.cpp | 69 +++++ backends/vkeybd/image-map.h | 53 ++++ backends/vkeybd/polygon.cpp | 55 ++++ backends/vkeybd/polygon.h | 114 ++++++++ backends/vkeybd/virtual-keyboard-gui.cpp | 376 ++++++++++++++++++++++++ backends/vkeybd/virtual-keyboard-gui.h | 108 +++++++ backends/vkeybd/virtual-keyboard-parser.cpp | 430 ++++++++++++++++++++++++++++ backends/vkeybd/virtual-keyboard-parser.h | 217 ++++++++++++++ backends/vkeybd/virtual-keyboard.cpp | 347 ++++++++++++++++++++++ backends/vkeybd/virtual-keyboard.h | 218 ++++++++++++++ 37 files changed, 3144 insertions(+), 2853 deletions(-) delete mode 100644 backends/common/action.cpp delete mode 100644 backends/common/action.h delete mode 100644 backends/common/hardware-key.h delete mode 100644 backends/common/keymap-manager.cpp delete mode 100644 backends/common/keymap-manager.h delete mode 100644 backends/common/keymap.cpp delete mode 100644 backends/common/keymap.h delete mode 100644 backends/common/keymapper.cpp delete mode 100644 backends/common/keymapper.h delete mode 100644 backends/common/virtual-keyboard-gui.cpp delete mode 100644 backends/common/virtual-keyboard-gui.h delete mode 100644 backends/common/virtual-keyboard-parser.cpp delete mode 100644 backends/common/virtual-keyboard-parser.h delete mode 100644 backends/common/virtual-keyboard.cpp delete mode 100644 backends/common/virtual-keyboard.h create mode 100644 backends/keymapper/action.cpp create mode 100644 backends/keymapper/action.h create mode 100644 backends/keymapper/hardware-key.h create mode 100644 backends/keymapper/keymap-manager.cpp create mode 100644 backends/keymapper/keymap-manager.h create mode 100644 backends/keymapper/keymap.cpp create mode 100644 backends/keymapper/keymap.h create mode 100644 backends/keymapper/keymapper.cpp create mode 100644 backends/keymapper/keymapper.h create mode 100644 backends/vkeybd/image-map.cpp create mode 100644 backends/vkeybd/image-map.h create mode 100644 backends/vkeybd/polygon.cpp create mode 100644 backends/vkeybd/polygon.h create mode 100644 backends/vkeybd/virtual-keyboard-gui.cpp create mode 100644 backends/vkeybd/virtual-keyboard-gui.h create mode 100644 backends/vkeybd/virtual-keyboard-parser.cpp create mode 100644 backends/vkeybd/virtual-keyboard-parser.h create mode 100644 backends/vkeybd/virtual-keyboard.cpp create mode 100644 backends/vkeybd/virtual-keyboard.h (limited to 'backends') diff --git a/backends/common/action.cpp b/backends/common/action.cpp deleted file mode 100644 index 49d63fafd4..0000000000 --- a/backends/common/action.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* 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/common/action.h" -#include "backends/common/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/common/action.h b/backends/common/action.h deleted file mode 100644 index d9ecb873b3..0000000000 --- a/backends/common/action.h +++ /dev/null @@ -1,115 +0,0 @@ -/* 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 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 { - 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/common/hardware-key.h b/backends/common/hardware-key.h deleted file mode 100644 index 1442dbd728..0000000000 --- a/backends/common/hardware-key.h +++ /dev/null @@ -1,129 +0,0 @@ -/* 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/common/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::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::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::iterator it; - for (it = _keys.begin(); it != _keys.end(); it++) { - if ((*it)->key == keystate) - return (*it); - } - return 0; - } - - List getHardwareKeys() const { - return _keys; - } - - uint count() const { - return _keys.size(); - } - - -private: - - void checkForKey(HardwareKey *key) { - List::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 _keys; -}; - - -} // end of namespace Common - -#endif diff --git a/backends/common/keymap-manager.cpp b/backends/common/keymap-manager.cpp deleted file mode 100644 index 39ad6d061e..0000000000 --- a/backends/common/keymap-manager.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* 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/common/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 actions(map->getActions()), unmapped; - List::iterator actIt; - List keys = _hardwareKeys->getHardwareKeys(); - List::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/common/keymap-manager.h b/backends/common/keymap-manager.h deleted file mode 100644 index c4db61da02..0000000000 --- a/backends/common/keymap-manager.h +++ /dev/null @@ -1,97 +0,0 @@ -/* 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/common/hardware-key.h" -#include "backends/common/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 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/common/keymap.cpp b/backends/common/keymap.cpp deleted file mode 100644 index ba6f758caa..0000000000 --- a/backends/common/keymap.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/* 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/common/keymap.h" -#include "backends/common/hardware-key.h" - -namespace Common { - -Keymap::Keymap(const Keymap& km) : _actions(km._actions), _keymap() { - List::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::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::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::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::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::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::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/common/keymap.h b/backends/common/keymap.h deleted file mode 100644 index d9d928ace9..0000000000 --- a/backends/common/keymap.h +++ /dev/null @@ -1,135 +0,0 @@ -/* 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/common/action.h" - -namespace Common { - -struct HardwareKey; -class HardwareKeySet; - -/** - * Hash function for KeyState - */ -template<> struct Hash - : public UnaryFunction { - - 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& 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 _actions; - HashMap _keymap; - -}; - - -} // end of namespace Common - -#endif diff --git a/backends/common/keymapper.cpp b/backends/common/keymapper.cpp deleted file mode 100644 index 59fb796187..0000000000 --- a/backends/common/keymapper.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* 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/common/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::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/common/keymapper.h b/backends/common/keymapper.h deleted file mode 100644 index c2113d5ca4..0000000000 --- a/backends/common/keymapper.h +++ /dev/null @@ -1,131 +0,0 @@ -/* 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/common/hardware-key.h" -#include "backends/common/keymap.h" -#include "backends/common/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::iterator Iterator; - - EventManager *_eventMan; - KeymapManager *_keymapMan; - - - struct MapRecord { - Keymap* keymap; - bool inherit; - }; - - Stack _activeMaps; - -}; - -} // end of namespace Common - -#endif diff --git a/backends/common/virtual-keyboard-gui.cpp b/backends/common/virtual-keyboard-gui.cpp deleted file mode 100644 index ca246a17a1..0000000000 --- a/backends/common/virtual-keyboard-gui.cpp +++ /dev/null @@ -1,378 +0,0 @@ -/* 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/common/virtual-keyboard-gui.h" -#include "graphics/cursorman.h" -#include "gui/newgui.h" - -namespace Common { - -VirtualKeyboardGUI::VirtualKeyboardGUI(VirtualKeyboard *kbd) { - _kbd = kbd; - - assert(g_system); - _system = g_system; - - _lastScreenChanged = _system->getScreenChangeID(); - - memset(_cursor, 0xFF, sizeof(_cursor)); - - _displaying = _needRedraw = _drag = false; - _firstRun = true; - - _displayEnabled = false; - - _cursorAnimateTimer = 0; -} - -void VirtualKeyboardGUI::initMode(VirtualKeyboard::Mode *mode) { - _kbdSurface = mode->image; - _kbdTransparentColor = mode->transparentColor; - _kbdBound.setWidth(_kbdSurface->w + 1); - _kbdBound.setHeight(_kbdSurface->h + 1); - _needRedraw = true; - - _displayEnabled = false; - if (!mode->displayArea) - return; - Rect r = *(mode->displayArea); - - // choose font - _dispFont = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont); - if (!fontIsSuitable(_dispFont, r)) { - _dispFont = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont); - if (!fontIsSuitable(_dispFont, r)) - return; - } - _dispX = r.left; - _dispY = r.top + (_dispFont->getFontHeight() - r.height() + 1) / 2; - _dispSurface.free(); - _dispSurface.create(r.width() + 1, _dispFont->getFontHeight(), sizeof(OverlayColor)); - _dispI = 0; - _dispForeColor = mode->displayFontColor; - _dispBackColor = _dispForeColor + 0xFF; - _displayEnabled = true; -} - -bool VirtualKeyboardGUI::fontIsSuitable(const Graphics::Font *font, const Rect& rect) { - return (font->getMaxCharWidth() < rect.width() && - font->getFontHeight() < rect.height()); -} - -void VirtualKeyboardGUI::run() { - if (_lastScreenChanged != _system->getScreenChangeID()) - screenChanged(); - - // TODO: set default position if position is somehow invalid - if (_firstRun) { - _firstRun = false; - setDefaultPosition(); - } - - if (!g_gui.isActive()) { - _system->showOverlay(); - _system->clearOverlay(); - } - _overlayBackup.create(_system->getOverlayWidth(), _system->getOverlayHeight(), sizeof(OverlayColor)); - _system->grabOverlay((OverlayColor*)_overlayBackup.pixels, _overlayBackup.w); - resetDirtyRect(); - - setupCursor(); - - _displaying = true; - mainLoop(); - - removeCursor(); - - _system->copyRectToOverlay((OverlayColor*)_overlayBackup.pixels, _overlayBackup.w, 0, 0, _overlayBackup.w, _overlayBackup.h); - if (!g_gui.isActive()) _system->hideOverlay(); - - _overlayBackup.free(); -} - -void VirtualKeyboardGUI::hide() { - _displaying = false; -} - -void VirtualKeyboardGUI::reset() { - _kbdBound.left = _kbdBound.top - = _kbdBound.right = _kbdBound.bottom = 0; - _displaying = _drag = false; - _firstRun = true; - _lastScreenChanged = _system->getScreenChangeID(); - _kbdSurface = 0; -} - -void VirtualKeyboardGUI::setDefaultPosition() -{ - int16 scrW = _system->getOverlayWidth(), scrH = _system->getOverlayHeight(); - int16 kbdW = _kbdBound.width(), kbdH = _kbdBound.height(); - int16 posX = 0, posY = 0; - if (scrW != kbdW) { - switch (_kbd->_hAlignment) { - case VirtualKeyboard::kAlignLeft: - posX = 0; - break; - case VirtualKeyboard::kAlignCentre: - posX = (scrW - kbdW) / 2; - break; - case VirtualKeyboard::kAlignRight: - posX = scrW - kbdW; - break; - } - } - if (scrH != kbdH) { - switch (_kbd->_vAlignment) { - case VirtualKeyboard::kAlignTop: - posY = 0; - break; - case VirtualKeyboard::kAlignMiddle: - posY = (scrH - kbdH) / 2; - break; - case VirtualKeyboard::kAlignBottom: - posY = scrH - kbdH; - break; - } - } - _kbdBound.moveTo(posX, posY); -} - -void VirtualKeyboardGUI::move(int16 x, int16 y) { - // add old position to dirty area - extendDirtyRect(_kbdBound); - _needRedraw = true; - - // snap to edge of screen - if (ABS(x) < SNAP_WIDTH) - x = 0; - int16 x2 = _system->getOverlayWidth() - _kbdBound.width(); - if (ABS(x - x2) < SNAP_WIDTH) - x = x2; - if (ABS(y) < SNAP_WIDTH) - y = 0; - int16 y2 = _system->getOverlayHeight() - _kbdBound.height(); - if (ABS(y - y2) < SNAP_WIDTH) - y = y2; - - _kbdBound.moveTo(x, y); -} - -void VirtualKeyboardGUI::screenChanged() { - _lastScreenChanged = _system->getScreenChangeID(); - if (!_kbd->checkModeResolutions()) - _displaying = false; -} - - -void VirtualKeyboardGUI::mainLoop() { - Common::EventManager *eventMan = _system->getEventManager(); - - while (_displaying) { - if (_displayEnabled) { - if (_kbd->_keyQueue.hasStringChanged()) - _refreshDisplay = true; - animateCaret(); - if (_refreshDisplay) updateDisplay();; - } - if (_needRedraw) redraw(); - animateCursor(); - _system->updateScreen(); - Common::Event event; - while (eventMan->pollEvent(event)) { - switch (event.type) { - case Common::EVENT_LBUTTONDOWN: - if (_kbdBound.contains(event.mouse)) { - _kbd->handleMouseDown(event.mouse.x - _kbdBound.left, - event.mouse.y - _kbdBound.top); - } - break; - case Common::EVENT_LBUTTONUP: - if (_kbdBound.contains(event.mouse)) { - _kbd->handleMouseUp(event.mouse.x - _kbdBound.left, - event.mouse.y - _kbdBound.top); - } - break; - case Common::EVENT_MOUSEMOVE: - if (_drag) - move(event.mouse.x - _dragPoint.x, - event.mouse.y - _dragPoint.y); - break; - case Common::EVENT_SCREEN_CHANGED: - screenChanged(); - break; - case Common::EVENT_QUIT: - _system->quit(); - return; - default: - break; - } - } - // Delay for a moment - _system->delayMillis(10); - } -} - -void VirtualKeyboardGUI::startDrag(int16 x, int16 y) { - _drag = true; - _dragPoint.x = x; - _dragPoint.y = y; -} - -void VirtualKeyboardGUI::endDrag() { - _drag = false; -} - -void VirtualKeyboardGUI::extendDirtyRect(const Rect &r) { - if (_dirtyRect.isValidRect()) { - _dirtyRect.extend(r); - } else { - _dirtyRect = r; - } - _dirtyRect.clip(Rect(0, 0, _overlayBackup.w, _overlayBackup.h)); -} - -void VirtualKeyboardGUI::resetDirtyRect() { - _dirtyRect.setWidth(-1); -} - -void VirtualKeyboardGUI::redraw() { - assert(_kbdSurface); - - extendDirtyRect(_kbdBound); - - Graphics::SurfaceKeyColored surf; - surf.create(_dirtyRect.width()+1, _dirtyRect.height()+1, sizeof(OverlayColor)); - - OverlayColor *scr = (OverlayColor *)surf.pixels; - const OverlayColor *ove = (OverlayColor *) _overlayBackup.getBasePtr(_dirtyRect.left, _dirtyRect.top); - int16 h = surf.h; - - while (h-- > 0) { - memcpy(scr, ove, surf.w * sizeof(OverlayColor)); - scr += surf.w; - ove += _overlayBackup.w; - } - - int16 keyX = _kbdBound.left - _dirtyRect.left; - int16 keyY = _kbdBound.top - _dirtyRect.top; - surf.blit(_kbdSurface, keyX, keyY, _kbdTransparentColor); - if (_displayEnabled) surf.blit(&_dispSurface, keyX + _dispX, keyY + _dispY, _dispBackColor); - _system->copyRectToOverlay((OverlayColor*)surf.pixels, surf.w, - _dirtyRect.left, _dirtyRect.top, surf.w, surf.h); - - surf.free(); - - _needRedraw = false; - - resetDirtyRect(); -} - -uint VirtualKeyboardGUI::calculateEndIndex(const String& str, uint startIndex) { - int16 w = 0; - while (w <= _dispSurface.w && startIndex < str.size()) { - w += _dispFont->getCharWidth(str[startIndex++]); - } - if (w > _dispSurface.w) startIndex--; - return startIndex; -} - -void VirtualKeyboardGUI::animateCaret() { - if (_system->getMillis() % kCaretBlinkTime < kCaretBlinkTime / 2) { - if (!_drawCaret) { - _drawCaret = true; - _refreshDisplay = true; - } - } else { - if (_drawCaret) { - _drawCaret = false; - _refreshDisplay = true; - } - } -} - -void VirtualKeyboardGUI::updateDisplay() { - if (!_displayEnabled) return; - - // calculate the text to display - uint cursorPos = _kbd->_keyQueue.getInsertIndex(); - String wholeText = _kbd->_keyQueue.getString(); - uint dispTextEnd; - if (_dispI > cursorPos) - _dispI = cursorPos; - - dispTextEnd = calculateEndIndex(wholeText, _dispI); - while (cursorPos > dispTextEnd) - dispTextEnd = calculateEndIndex(wholeText, ++_dispI); - - String dispText = String(wholeText.c_str() + _dispI, wholeText.c_str() + dispTextEnd); - - // draw to display surface - _dispSurface.fillRect(Rect(0, 0, _dispSurface.w, _dispSurface.h), _dispBackColor); - _dispFont->drawString(&_dispSurface, dispText, 0, 0, _dispSurface.w, _dispForeColor); - if (_drawCaret) { - String beforeCaret(wholeText.c_str() + _dispI, wholeText.c_str() + cursorPos); - int16 caretX = _dispFont->getStringWidth(beforeCaret); - _dispSurface.drawLine(caretX, 0, caretX, _dispSurface.h, _dispForeColor); - } - - _needRedraw = true; -} - -void VirtualKeyboardGUI::setupCursor() { - const byte palette[] = { - 255, 255, 255, 0, - 255, 255, 255, 0, - 171, 171, 171, 0, - 87, 87, 87, 0 - }; - - CursorMan.pushCursorPalette(palette, 0, 4); - CursorMan.pushCursor(NULL, 0, 0, 0, 0); - CursorMan.showMouse(true); -} - -void VirtualKeyboardGUI::animateCursor() { - int time = _system->getMillis(); - if (time > _cursorAnimateTimer + kCursorAnimateDelay) { - for (int i = 0; i < 15; i++) { - if ((i < 6) || (i > 8)) { - _cursor[16 * 7 + i] = _cursorAnimateCounter; - _cursor[16 * i + 7] = _cursorAnimateCounter; - } - } - - CursorMan.replaceCursor(_cursor, 16, 16, 7, 7); - - _cursorAnimateTimer = time; - _cursorAnimateCounter = (_cursorAnimateCounter + 1) % 4; - } -} - -void VirtualKeyboardGUI::removeCursor() { - CursorMan.popCursor(); - CursorMan.popCursorPalette(); -} - -} // end of namespace Common diff --git a/backends/common/virtual-keyboard-gui.h b/backends/common/virtual-keyboard-gui.h deleted file mode 100644 index 10b16f17f7..0000000000 --- a/backends/common/virtual-keyboard-gui.h +++ /dev/null @@ -1,108 +0,0 @@ -/* 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_VIRTUAL_KEYBOARD_GUI -#define COMMON_VIRTUAL_KEYBOARD_GUI - -#include "backends/common/virtual-keyboard.h" -#include "common/rect.h" -#include "common/system.h" -#include "graphics/fontman.h" -#include "graphics/surface-keycolored.h" - -namespace Common { - -class VirtualKeyboardGUI { - -public: - - VirtualKeyboardGUI(VirtualKeyboard *kbd); - void initMode(VirtualKeyboard::Mode *mode); - void run(); - void hide(); - bool isDisplaying() { return _displaying; } - void reset(); - void startDrag(int16 x, int16 y); - void endDrag(); - -private: - - OSystem *_system; - VirtualKeyboard *_kbd; - Graphics::Surface *_kbdSurface; - OverlayColor _kbdTransparentColor; - - static const int SNAP_WIDTH = 10; - - Graphics::Surface _overlayBackup; - - Rect _dirtyRect; - - bool _displayEnabled; - bool _refreshDisplay; - Graphics::Surface _dispSurface; - const Graphics::Font *_dispFont; - int16 _dispX, _dispY; - uint _dispI; - OverlayColor _dispForeColor, _dispBackColor; - - Rect _kbdBound; - - Point _dragPoint; - bool _drag; - - bool _displaying; - bool _firstRun; - bool _needRedraw; - int _lastScreenChanged; - - void setDefaultPosition(); - void move(int16 x, int16 y); - void screenChanged(); - void mainLoop(); - void extendDirtyRect(const Rect &r); - void resetDirtyRect(); - void redraw(); - void updateDisplay(); - bool fontIsSuitable(const Graphics::Font *font, const Rect& rect); - uint calculateEndIndex(const String& str, uint startIndex); - - bool _drawCaret; - static const int kCaretBlinkTime = 500; - void animateCaret(); - - static const int kCursorAnimateDelay = 250; - int _cursorAnimateCounter; - int _cursorAnimateTimer; - byte _cursor[2048]; - void setupCursor(); - void removeCursor(); - void animateCursor(); - -}; - -} // end of namespace Common - -#endif diff --git a/backends/common/virtual-keyboard-parser.cpp b/backends/common/virtual-keyboard-parser.cpp deleted file mode 100644 index 83f5c6f293..0000000000 --- a/backends/common/virtual-keyboard-parser.cpp +++ /dev/null @@ -1,430 +0,0 @@ -/* 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/common/virtual-keyboard-parser.h" - -#include "common/keyboard.h" -#include "graphics/imageman.h" -#include "common/util.h" - -namespace Common { - -VirtualKeyboardParser::VirtualKeyboardParser(VirtualKeyboard *kbd) : XMLParser() { - _keyboard = kbd; - - _callbacks["keyboard"] = &VirtualKeyboardParser::parserCallback_Keyboard; - _callbacks["mode"] = &VirtualKeyboardParser::parserCallback_Mode; - _callbacks["event"] = &VirtualKeyboardParser::parserCallback_Event; - _callbacks["layout"] = &VirtualKeyboardParser::parserCallback_Layout; - _callbacks["map"] = &VirtualKeyboardParser::parserCallback_Map; - _callbacks["area"] = &VirtualKeyboardParser::parserCallback_Area; - - _closedCallbacks["keyboard"] = &VirtualKeyboardParser::parserCallback_KeyboardClosed; - _closedCallbacks["mode"] = &VirtualKeyboardParser::parserCallback_ModeClosed; -} - -void VirtualKeyboardParser::cleanup() { - _mode = 0; - _kbdParsed = false; - _initialModeName.clear(); - if (_parseMode == kParseFull) { - // reset keyboard to remove existing config - _keyboard->reset(); - } -} - -bool VirtualKeyboardParser::keyCallback(String keyName) { - if (!_callbacks.contains(_activeKey.top()->name)) - return parserError("%s is not a valid key name.", keyName.c_str()); - - return (this->*(_callbacks[_activeKey.top()->name]))(); -} - -bool VirtualKeyboardParser::closedKeyCallback(String keyName) { - if (!_closedCallbacks.contains(_activeKey.top()->name)) - return true; - - return (this->*(_closedCallbacks[_activeKey.top()->name]))(); -} - -bool VirtualKeyboardParser::parserCallback_Keyboard() { - ParserNode *kbdNode = getActiveNode(); - - assert(kbdNode->name == "keyboard"); - - if (getParentNode(kbdNode) != 0) - return parserError("Keyboard element must be root"); - - if (_kbdParsed) - return parserError("Only a single keyboard element is allowed"); - - // if not full parse then we're done - if (_parseMode == kParseCheckResolutions) - return true; - - if (!kbdNode->values.contains("initial_mode")) - return parserError("Keyboard element must contain initial_mode attribute"); - - _initialModeName = kbdNode->values["initial_mode"]; - - if (kbdNode->values.contains("h_align")) { - String h = kbdNode->values["h_align"]; - if (h == "left") - _keyboard->_hAlignment = VirtualKeyboard::kAlignLeft; - else if (h == "centre" || h == "center") - _keyboard->_hAlignment = VirtualKeyboard::kAlignCentre; - else if (h == "right") - _keyboard->_hAlignment = VirtualKeyboard::kAlignRight; - } - - if (kbdNode->values.contains("v_align")) { - String v = kbdNode->values["h_align"]; - if (v == "top") - _keyboard->_vAlignment = VirtualKeyboard::kAlignTop; - else if (v == "middle" || v == "center") - _keyboard->_vAlignment = VirtualKeyboard::kAlignMiddle; - else if (v == "bottom") - _keyboard->_vAlignment = VirtualKeyboard::kAlignBottom; - } - - return true; -} - -bool VirtualKeyboardParser::parserCallback_KeyboardClosed() { - _kbdParsed = true; - if (!_keyboard->_initialMode) - return parserError("Initial mode of keyboard pack not defined"); - return true; -} - -bool VirtualKeyboardParser::parserCallback_Mode() { - ParserNode *modeNode = getActiveNode(); - - assert(modeNode->name == "mode"); - - if (getParentNode(modeNode) == 0 || getParentNode(modeNode)->name != "keyboard") - return parserError("Mode element must be child of keyboard element"); - - if (!modeNode->values.contains("name") || !modeNode->values.contains("resolutions")) - return parserError("Mode element must contain name and resolutions attributes"); - - String name = modeNode->values["name"]; - - if (_parseMode == kParseFull) { - // if full parse then add new mode to keyboard - - if (_keyboard->_modes.contains(name)) - return parserError("Mode '%s' has already been defined", name.c_str()); - - VirtualKeyboard::Mode mode; - mode.name = name; - _keyboard->_modes[name] = mode; - _mode = &(_keyboard->_modes[name]); - - if (name == _initialModeName) - _keyboard->_initialMode = _mode; - } else - _mode = &(_keyboard->_modes[name]); - - String resolutions = modeNode->values["resolutions"]; - StringTokenizer tok (resolutions, " ,"); - - // select best resolution simply by minimising the difference between the - // overlay size and the resolution dimensions. - // TODO: improve this by giving preference to a resolution that is smaller - // than the overlay res (so the keyboard can't be too big for the screen) - uint16 scrW = g_system->getOverlayWidth(), scrH = g_system->getOverlayHeight(); - uint32 diff = 0xFFFFFFFF; - String newResolution; - for (String res = tok.nextToken(); res.size() > 0; res = tok.nextToken()) { - int resW, resH; - if (sscanf(res.c_str(), "%dx%d", &resW, &resH) != 2) { - return parserError("Invalid resolution specification"); - } else { - if (resW == scrW && resH == scrH) { - newResolution = res; - break; - } else { - uint32 newDiff = ABS(scrW - resW) + ABS(scrH - resH); - if (newDiff < diff) { - diff = newDiff; - newResolution = res; - } - } - } - } - - if (newResolution.empty()) - return parserError("No acceptable resolution was found"); - - if (_parseMode == kParseCheckResolutions) { - if (_mode->resolution == newResolution) { - modeNode->ignore = true; - return true; - } else { - // remove data relating to old resolution - ImageMan.unregisterSurface(_mode->bitmapName); - _mode->bitmapName.clear(); - _mode->image = 0; - _mode->imageMap.removeAllAreas(); - } - } - - _mode->resolution = newResolution; - _layoutParsed = false; - - return true; -} - -bool VirtualKeyboardParser::parserCallback_ModeClosed() { - if (!_layoutParsed) { - return parserError("'%s' layout missing from '%s' mode", _mode->resolution.c_str(), _mode->name.c_str()); - } - return true; -} - -bool VirtualKeyboardParser::parserCallback_Event() { - ParserNode *evtNode = getActiveNode(); - - assert(evtNode->name == "event"); - - if (getParentNode(evtNode) == 0 || getParentNode(evtNode)->name != "mode") - return parserError("Event element must be child of mode element"); - - if (!evtNode->values.contains("name") || !evtNode->values.contains("type")) - return parserError("Event element must contain name and type attributes"); - - assert(_mode); - - // if just checking resolutions we're done - if (_parseMode == kParseCheckResolutions) - return true; - - String name = evtNode->values["name"]; - if (_mode->events.contains(name)) - return parserError("Event '%s' has already been defined", name.c_str()); - - VirtualKeyboard::Event *evt = new VirtualKeyboard::Event(); - evt->name = name; - - String type = evtNode->values["type"]; - if (type == "key") { - if (!evtNode->values.contains("code") || !evtNode->values.contains("ascii")) { - delete evt; - return parserError("Key event element must contain code and ascii attributes"); - } - - evt->type = VirtualKeyboard::kEventKey; - - KeyCode code = (KeyCode)atoi(evtNode->values["code"].c_str()); - uint16 ascii = atoi(evtNode->values["ascii"].c_str()); - - byte flags = 0; - if (evtNode->values.contains("modifiers")) - flags = parseFlags(evtNode->values["modifiers"]); - - evt->data = new KeyState(code, ascii, flags); - - } else if (type == "modifier") { - if (!evtNode->values.contains("modifiers")) { - delete evt; - return parserError("Key modifier element must contain modifier attributes"); - } - - evt->type = VirtualKeyboard::kEventModifier; - byte *flags = new byte; - *(flags) = parseFlags(evtNode->values["modifiers"]); - evt->data = flags; - - } else if (type == "switch_mode") { - if (!evtNode->values.contains("mode")) { - delete evt; - return parserError("Switch mode event element must contain mode attribute"); - } - - evt->type = VirtualKeyboard::kEventSwitchMode; - evt->data = new String(evtNode->values["mode"]); - } else if (type == "close") { - evt->type = VirtualKeyboard::kEventClose; - evt->data = 0; - } else { - delete evt; - return parserError("Event type '%s' not known", type.c_str()); - } - - _mode->events[name] = evt; - - return true; -} - -bool VirtualKeyboardParser::parserCallback_Layout() { - ParserNode *layoutNode = getActiveNode(); - - assert(layoutNode->name == "layout"); - - if (getParentNode(layoutNode) == 0 || getParentNode(layoutNode)->name != "mode") - return parserError("Layout element must be child of mode element"); - - if (!layoutNode->values.contains("resolution") || !layoutNode->values.contains("bitmap")) - return parserError("Layout element must contain resolution and bitmap attributes"); - - assert(!_mode->resolution.empty()); - - String res = layoutNode->values["resolution"]; - - if (res != _mode->resolution) { - layoutNode->ignore = true; - return true; - } - - _mode->bitmapName = layoutNode->values["bitmap"]; - _mode->image = ImageMan.getSurface(_mode->bitmapName); - if (!_mode->image) { - if (!ImageMan.registerSurface(_mode->bitmapName, 0)) - return parserError("Error loading bitmap '%s'", _mode->bitmapName.c_str()); - - _mode->image = ImageMan.getSurface(_mode->bitmapName); - if (!_mode->image) - return parserError("Error loading bitmap '%s'", _mode->bitmapName.c_str()); - } - - if (layoutNode->values.contains("transparent_color")) { - int r, g, b; - if (!parseIntegerKey(layoutNode->values["transparent_color"].c_str(), 3, &r, &g, &b)) - return parserError("Could not parse color value"); - _mode->transparentColor = g_system->RGBToColor(r, g, b); - } else - _mode->transparentColor = g_system->RGBToColor(255, 0, 255); // default to purple - - if (layoutNode->values.contains("display_font_color")) { - int r, g, b; - if (!parseIntegerKey(layoutNode->values["display_font_color"].c_str(), 3, &r, &g, &b)) - return parserError("Could not parse color value"); - _mode->displayFontColor = g_system->RGBToColor(r, g, b); - } else - _mode->displayFontColor = g_system->RGBToColor(0, 0, 0); // default to black - - _layoutParsed = true; - - return true; -} - -bool VirtualKeyboardParser::parserCallback_Map() { - ParserNode *mapNode = getActiveNode(); - - assert(mapNode->name == "map"); - - if (getParentNode(mapNode) == 0 || getParentNode(mapNode)->name != "layout") - return parserError("Map element must be child of layout element"); - - return true; -} - -bool VirtualKeyboardParser::parserCallback_Area() { - ParserNode *areaNode = getActiveNode(); - - assert(areaNode->name == "area"); - - if (getParentNode(areaNode) == 0 || getParentNode(areaNode)->name != "map") - return parserError("Area element must be child of map element"); - - if (!areaNode->values.contains("shape") || !areaNode->values.contains("coords") || !areaNode->values.contains("target")) - return parserError("Area element must contain shape, coords and target attributes"); - - String& shape = areaNode->values["shape"]; - String& target = areaNode->values["target"]; - String& coords = areaNode->values["coords"]; - - if (target == "display_area") { - if (shape != "rect") - return parserError("display_area must be a rect area"); - _mode->displayArea = new Rect(); - return parseRect(_mode->displayArea, coords); - } else if (shape == "rect") { - Polygon *poly = _mode->imageMap.createArea(target); - return parseRectAsPolygon(poly, coords); - } else if (shape == "poly") { - Polygon *poly = _mode->imageMap.createArea(target); - return parsePolygon(poly, coords); - } - return parserError("Area shape '%s' not known", shape.c_str()); -} - -byte VirtualKeyboardParser::parseFlags(const String& flags) { - if (flags.empty()) - return 0; - - StringTokenizer tok(flags, ", "); - byte val = 0; - for (String fl = tok.nextToken(); !fl.empty(); fl = tok.nextToken()) { - if (fl == "ctrl" || fl == "control") - val |= KBD_CTRL; - else if (fl == "alt") - val |= KBD_ALT; - else if (fl == "shift") - val |= KBD_SHIFT; - } - return val; -} - -bool VirtualKeyboardParser::parseRect(Rect *rect, const String& coords) { - int x1, y1, x2, y2; - if (!parseIntegerKey(coords.c_str(), 4, &x1, &y1, &x2, &y2)) - return parserError("Invalid coords for rect area"); - rect->left = x1; rect->top = y1; rect->right = x2; rect->bottom = y2; - if (!rect->isValidRect()) - return parserError("Rect area is not a valid rectangle"); - return true; -} - -bool VirtualKeyboardParser::parsePolygon(Polygon *poly, const String& coords) { - StringTokenizer tok (coords, ", "); - for (String st = tok.nextToken(); !st.empty(); st = tok.nextToken()) { - int x, y; - if (sscanf(st.c_str(), "%d", &x) != 1) - return parserError("Invalid coords for polygon area"); - st = tok.nextToken(); - if (sscanf(st.c_str(), "%d", &y) != 1) - return parserError("Invalid coords for polygon area"); - poly->addPoint(x, y); - } - if (poly->getPointCount() < 3) - return parserError("Invalid coords for polygon area"); - - return true; -} - -bool VirtualKeyboardParser::parseRectAsPolygon(Polygon *poly, const String& coords) { - Rect rect; - if (!parseRect(&rect, coords)) - return false; - poly->addPoint(rect.left, rect.top); - poly->addPoint(rect.right, rect.top); - poly->addPoint(rect.right, rect.bottom); - poly->addPoint(rect.left, rect.bottom); - return true; -} - -} // end of namespace GUI diff --git a/backends/common/virtual-keyboard-parser.h b/backends/common/virtual-keyboard-parser.h deleted file mode 100644 index ec6dd6dcec..0000000000 --- a/backends/common/virtual-keyboard-parser.h +++ /dev/null @@ -1,217 +0,0 @@ -/* 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_VIRTUAL_KEYBOARD_PARSER -#define COMMON_VIRTUAL_KEYBOARD_PARSER - -#include "common/xmlparser.h" -#include "backends/common/virtual-keyboard.h" - -/** - TODO - information about optional attributes and their default values - - - *************************************** - ** Virtual Keyboard Pack File Format ** - *************************************** - -The new virtual keyboard for ScummVM is implemented in the same way as a HTML -ImageMap. It uses a single bitmap of the entire keyboard layout and then a -image map description allows certain areas of the bitmap to be given special -actions. Most of these actions will be a virtual key press event, but there -will also be special keys that will change the keyboard layout or close the -keyboard. The HTML image map description is contained in a larger XML file that -can describe all the different modes of the keyboard, and also different -keyboard layouts for different screen resolutions. - - ******************************************** - ** Example keyboard pack description file ** - ******************************************** - - - - - - - - - ... - - - - - ... - - - - - ... - - - - - - - - ... - - - - - - ... - - - -************************* -** Description of tags ** -************************* - - - -This is the required, root element of the file format. - -attributes: - - modes: lists all the modes that the keyboard pack contains - - initial_mode: which mode the keyboard should show initially - - v_align/h_align: where on the screen should the keyboard appear initially - -child tags: - - mode - -------------------------------------------------------------------------------- - - - -This tag encapsulates a single mode of the keyboard. Within are a number of -layouts, which provide the specific implementation at different resolutions. - -attributes: - - name: the name of the mode - - resolutions: list of the different layout resolutions - -child tags: - - layout - - event - -------------------------------------------------------------------------------- - - - -These tags describe a particular event that will be triggered by a mouse click -on a particular area. The target attribute of each image map area should be the -same as an event's name. - -attributes: - - name: name of the event - - type: what sort of event is it (key | switch_mode | close) - - for key events - - code / ascii / modifiers: describe a key press in ScummVM KeyState format - - for switch_mode events - - mode: the mode that should be switched to - -------------------------------------------------------------------------------- - - - -These tags encapsulate an implementation of a mode at a particular resolution. - -attributes: - - resolution: the screen resolution that this layout is designed for - - bitmap: filename of the 24-bit bitmap that will be used for this layout - - transparent_color: color in r,b,g format that will be used for keycolor - transparency. - -child nodes: - - map: this describes the image map using the same format as html image maps - -------------------------------------------------------------------------------- - - - -These tags describe the image map for a particular layout. It uses the exact -same format as HTML image maps. The only area shapes that are supported are -rectangles and polygons. The target attribute of each area should be the name -of an event for this mode (see tag). For information on HTML image map -format see - - http://www.w3schools.com/TAGS/tag_map.asp - - http://www.w3schools.com/TAGS/tag_area.asp - -*/ - -namespace Common { - -enum ParseMode { - kParseFull, // when loading keyboard pack for first time - kParseCheckResolutions // when re-parsing following a change in screen size -}; - -class VirtualKeyboardParser : public Common::XMLParser { - - typedef bool (VirtualKeyboardParser::*ParserCallback)(); - -public: - - VirtualKeyboardParser(VirtualKeyboard *kbd); - void setParseMode(ParseMode m) { - _parseMode = m; - } - -protected: - VirtualKeyboard *_keyboard; - - /** internal state variables of parser */ - ParseMode _parseMode; - VirtualKeyboard::Mode *_mode; // pointer to mode currently being parsed - String _initialModeName; - bool _kbdParsed; - bool _layoutParsed; - - bool keyCallback(String keyName); - bool closedKeyCallback(String keyName); - void cleanup(); - - bool parserCallback_Keyboard(); - bool parserCallback_Mode(); - bool parserCallback_Event(); - bool parserCallback_Layout(); - bool parserCallback_Map(); - bool parserCallback_Area(); - - bool parserCallback_KeyboardClosed(); - bool parserCallback_ModeClosed(); - - byte parseFlags(const String& flags); - bool parseRect(Rect *rect, const String& coords); - bool parsePolygon(Polygon *poly, const String& coords); - bool parseRectAsPolygon(Polygon *poly, const String& coords); - - HashMap _callbacks; - HashMap _closedCallbacks; -}; - -} // end of namespace GUI - -#endif diff --git a/backends/common/virtual-keyboard.cpp b/backends/common/virtual-keyboard.cpp deleted file mode 100644 index 4a125bb727..0000000000 --- a/backends/common/virtual-keyboard.cpp +++ /dev/null @@ -1,347 +0,0 @@ -/* 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/common/virtual-keyboard.h" -#include "backends/common/virtual-keyboard-gui.h" -#include "backends/common/virtual-keyboard-parser.h" -#include "graphics/imageman.h" - -namespace Common { - -VirtualKeyboard::VirtualKeyboard() : _currentMode(0) { - assert(g_system); - _system = g_system; - - _parser = new VirtualKeyboardParser(this); - _kbdGUI = new VirtualKeyboardGUI(this); - _loaded = false; -} - -VirtualKeyboard::~VirtualKeyboard() { - deleteEvents(); - delete _kbdGUI; - delete _parser; -} - -void VirtualKeyboard::deleteEvents() { - ModeMap::iterator it_m; - EventMap::iterator it_e; - for (it_m = _modes.begin(); it_m != _modes.end(); it_m++) { - EventMap *evt = &(it_m->_value.events); - for (it_e = evt->begin(); it_e != evt->end(); it_e++) - delete it_e->_value; - } -} - -void VirtualKeyboard::reset() { - deleteEvents(); - _modes.clear(); - _initialMode = _currentMode = 0; - _hAlignment = kAlignCentre; - _vAlignment = kAlignBottom; - _keyQueue.clear(); - _loaded = false; - _kbdGUI->reset(); -} - -bool VirtualKeyboard::loadKeyboardPack(Common::String packName) { - if (Common::File::exists(packName + ".xml")) { - // uncompressed keyboard pack - if (!_parser->loadFile(packName + ".xml")) - return false; - - } else if (Common::File::exists(packName + ".zip")) { - // compressed keyboard pack -#ifdef USE_ZLIB - unzFile zipFile = unzOpen((packName + ".zip").c_str()); - if (zipFile && unzLocateFile(zipFile, (packName + ".xml").c_str(), 2) == UNZ_OK) { - unz_file_info fileInfo; - unzOpenCurrentFile(zipFile); - unzGetCurrentFileInfo(zipFile, &fileInfo, NULL, 0, NULL, 0, NULL, 0); - byte *buffer = (byte *)malloc(fileInfo.uncompressed_size+1 * sizeof(byte)); - assert(buffer); - memset(buffer, 0, (fileInfo.uncompressed_size+1)*sizeof(byte)); - unzReadCurrentFile(zipFile, buffer, fileInfo.uncompressed_size); - unzCloseCurrentFile(zipFile); - if (!_parser->loadBuffer(buffer, fileInfo.uncompressed_size+1, true)) { - unzClose(zipFile); - return false; - } - } else { - warning("Could not find %s.xml file in %s.zip keyboard pack", packName.c_str(), packName.c_str()); - unzClose(zipFile); - return false; - } - unzClose(zipFile); - - ImageMan.addArchive(packName + ".zip"); -#else - return false; -#endif - } else { - warning("Keyboard pack not found"); - return false; - } - - _parser->setParseMode(kParseFull); - _loaded = _parser->parse(); - if (_loaded) - printf("Keyboard pack '%s' loaded successfully!\n", packName.c_str()); - - return _loaded; -} - -bool VirtualKeyboard::checkModeResolutions() -{ - _parser->setParseMode(kParseCheckResolutions); - _loaded = _parser->parse(); - return _loaded; -} - -Common::String VirtualKeyboard::findArea(int16 x, int16 y) { - return _currentMode->imageMap.findMapArea(x, y); -} - -void VirtualKeyboard::processAreaClick(const Common::String& area) { - if (!_currentMode->events.contains(area)) return; - Event *evt = _currentMode->events[area]; - - switch (evt->type) { - case kEventKey: { - // add virtual keypress to queue - _keyQueue.insertKey(*(Common::KeyState*)evt->data); - break; - } - case kEventModifier: - _keyQueue.toggleFlags(*(byte*)(evt->data)); - break; - case kEventSwitchMode: - // switch to new mode - switchMode(*(Common::String *)evt->data); - _keyQueue.clearFlags(); - break; - case kEventClose: - // close virtual keyboard - _kbdGUI->hide(); - break; - } -} - -void VirtualKeyboard::switchMode(Mode *newMode) { - _kbdGUI->initMode(newMode); - _currentMode = newMode; -} - -void VirtualKeyboard::switchMode(const Common::String& newMode) { - if (!_modes.contains(newMode)) { - warning("Keyboard mode '%s' unknown", newMode.c_str()); - return; - } - switchMode(&_modes[newMode]); -} - -void VirtualKeyboard::handleMouseDown(int16 x, int16 y) { - _areaDown = findArea(x, y); - if (_areaDown.empty()) - _kbdGUI->startDrag(x, y); -} - -void VirtualKeyboard::handleMouseUp(int16 x, int16 y) { - if (!_areaDown.empty() && _areaDown == findArea(x, y)) { - processAreaClick(_areaDown); - _areaDown.clear(); - } - _kbdGUI->endDrag(); -} - -void VirtualKeyboard::show() { - if (!_loaded) { - // if not loaded then load default "vkeybd" pack - if (!loadKeyboardPack("vkeybd")) { - warning("Keyboard not loaded therefore can't be shown"); - return; - } - } - switchMode(_initialMode); - - _kbdGUI->run(); - - EventManager *eventMan = _system->getEventManager(); - assert(eventMan); - - // push keydown & keyup events into the event manager - Common::Event evt; - evt.synthetic = false; - while (!_keyQueue.empty()) { - evt.kbd = _keyQueue.pop(); - evt.type = Common::EVENT_KEYDOWN; - eventMan->pushEvent(evt); - evt.type = Common::EVENT_KEYUP; - eventMan->pushEvent(evt); - } -} - -void VirtualKeyboard::hide() { - _kbdGUI->hide(); -} - -bool VirtualKeyboard::isDisplaying() { - return _kbdGUI->isDisplaying(); -} - -VirtualKeyboard::KeyPressQueue::KeyPressQueue() { - _keyPos = _keys.end(); - _strPos = 0; -} - -void VirtualKeyboard::KeyPressQueue::toggleFlags(byte fl) { - _keyFlags ^= fl; - _strChanged = true; -} - -void VirtualKeyboard::KeyPressQueue::clearFlags() { - _keyFlags = 0; - _strChanged = true; -} - -void VirtualKeyboard::KeyPressQueue::insertKey(KeyState key) { - _strChanged = true; - switch (key.keycode) { - case KEYCODE_LEFT: - moveLeft(); - return; - case KEYCODE_RIGHT: - moveRight(); - return; - case KEYCODE_BACKSPACE: - deleteKey(); - return; - default: - ; - } - - key.flags ^= _keyFlags; - if ((key.keycode >= Common::KEYCODE_a) && (key.keycode <= Common::KEYCODE_z)) - key.ascii = (key.flags & Common::KBD_SHIFT) ? key.keycode - 32 : key.keycode; - clearFlags(); - - String keyStr; - if (key.keycode >= 32 && key.keycode <= 126) { - if (key.flags & KBD_CTRL) - keyStr += "Ctrl+"; - if (key.flags & KBD_ALT) - keyStr += "Alt+"; - if (key.flags & KBD_SHIFT && (key.ascii < 65 || key.ascii > 90)) - keyStr += "Shift+"; - keyStr += (char)key.ascii; - } - - const char *k = keyStr.c_str(); - while (char ch = *k++) - _str.insertChar(ch, _strPos++); - - VirtualKeyPress kp; - kp.key = key; - kp.strLen = keyStr.size(); - _keys.insert(_keyPos, kp); -} - -void VirtualKeyboard::KeyPressQueue::deleteKey() { - if (_keyPos == _keys.begin()) - return; - List::iterator it = _keyPos; - it--; - _strPos -= it->strLen; - while((it->strLen)-- > 0) - _str.deleteChar(_strPos); - _keys.erase(it); -} - -void VirtualKeyboard::KeyPressQueue::moveLeft() { - if (_keyPos == _keys.begin()) - return; - _keyPos--; - _strPos -= _keyPos->strLen; -} - -void VirtualKeyboard::KeyPressQueue::moveRight() { - if (_keyPos == _keys.end()) - return; - _strPos += _keyPos->strLen; - _keyPos++; -} - -KeyState VirtualKeyboard::KeyPressQueue::pop() { - bool front = (_keyPos == _keys.begin()); - VirtualKeyPress kp = *(_keys.begin()); - _keys.pop_front(); - - if (front) - _keyPos = _keys.begin(); - else - _strPos -= kp.strLen; - - while (kp.strLen-- > 0) - _str.deleteChar(0); - - return kp.key; -} - -void VirtualKeyboard::KeyPressQueue::clear() { - _keys.clear(); - _keyPos = _keys.end(); - _str.clear(); - _strPos = 0; - _keyFlags = 0; -} - -bool VirtualKeyboard::KeyPressQueue::empty() -{ - return _keys.empty(); -} - -String VirtualKeyboard::KeyPressQueue::getString() -{ - String flags; - if (_keyFlags & KBD_CTRL) - flags += "Ctrl+"; - if (_keyFlags & KBD_ALT) - flags += "Alt+"; - if (_keyFlags & KBD_SHIFT) - flags += "Shift+"; - return _str + flags; -} - -uint VirtualKeyboard::KeyPressQueue::getInsertIndex() { - return _strPos; -} - -bool VirtualKeyboard::KeyPressQueue::hasStringChanged() { - bool ret = _strChanged; - _strChanged = false; - return ret; -} - -} // end of namespace Common diff --git a/backends/common/virtual-keyboard.h b/backends/common/virtual-keyboard.h deleted file mode 100644 index c5b77aac0f..0000000000 --- a/backends/common/virtual-keyboard.h +++ /dev/null @@ -1,218 +0,0 @@ -/* 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_VIRTUAL_KEYBOARD_H -#define COMMON_VIRTUAL_KEYBOARD_H - -class OSystem; - -#include "common/events.h" -#include "common/hashmap.h" -#include "common/hash-str.h" -#include "common/image-map.h" -#include "common/keyboard.h" -#include "common/list.h" -#include "common/str.h" - -namespace Common { - -class VirtualKeyboardGUI; -class VirtualKeyboardParser; - -class VirtualKeyboard { -protected: - enum EventType { - kEventKey, - kEventModifier, - kEventSwitchMode, - kEventClose - }; - - struct Event { - Common::String name; - EventType type; - void *data; - - Event() : data(0) {} - ~Event() { - if (data) { - switch (type) { - case kEventKey: - delete (KeyState*)data; - break; - case kEventModifier: - delete (byte*)data; - break; - case kEventSwitchMode: - delete (String*)data; - break; - case kEventClose: - break; - } - } - } - }; - - typedef Common::HashMap EventMap; - - struct Mode { - Common::String name; - Common::String resolution; - Common::String bitmapName; - Graphics::Surface *image; - OverlayColor transparentColor; - Common::ImageMap imageMap; - EventMap events; - Common::Rect *displayArea; - OverlayColor displayFontColor; - - Mode() : image(0), displayArea(0) {} - ~Mode() { if (displayArea) delete displayArea; } - }; - - typedef Common::HashMap ModeMap; - - enum HorizontalAlignment { - kAlignLeft, - kAlignCentre, - kAlignRight - }; - - enum VerticalAlignment { - kAlignTop, - kAlignMiddle, - kAlignBottom - }; - - struct VirtualKeyPress { - Common::KeyState key; - uint strLen; - }; - - class KeyPressQueue { - public: - KeyPressQueue(); - void toggleFlags(byte fl); - void clearFlags(); - void insertKey(KeyState key); - void deleteKey(); - void moveLeft(); - void moveRight(); - KeyState pop(); - void clear(); - bool empty(); - String getString(); - uint getInsertIndex(); - bool hasStringChanged(); - - private: - byte _keyFlags; - - List _keys; - String _str; - - bool _strChanged; - - List::iterator _keyPos; - uint _strPos; - }; - -public: - VirtualKeyboard(); - virtual ~VirtualKeyboard(); - - /** - * Loads the keyboard pack with the given name. - * The system first looks for an uncompressed keyboard pack by searching - * for packName.xml in the filesystem, if this does not exist then it - * searches for a compressed keyboard pack by looking for packName.zip. - * @param packName name of the keyboard pack - */ - bool loadKeyboardPack(Common::String packName); - - /** - * Shows the keyboard, starting an event loop that will intercept all - * user input (like a modal GUI dialog). - * It is assumed that the game has been paused, before this is called - */ - void show(); - - /** - * Hides the keyboard, ending the event loop. - */ - void hide(); - - /** - * Returns true if the keyboard is currently being shown - */ - bool isDisplaying(); - - /** - * Returns true if the keyboard is loaded and ready to be shown - */ - bool isLoaded() { - return _loaded; - } - -protected: // TODO : clean up all this stuff - - OSystem *_system; - - friend class VirtualKeyboardGUI; - VirtualKeyboardGUI *_kbdGUI; - - KeyPressQueue _keyQueue; - - friend class VirtualKeyboardParser; - VirtualKeyboardParser *_parser; - - void reset(); - void deleteEvents(); - bool checkModeResolutions(); - void switchMode(Mode *newMode); - void switchMode(const Common::String& newMode); - void handleMouseDown(int16 x, int16 y); - void handleMouseUp(int16 x, int16 y); - String findArea(int16 x, int16 y); - void processAreaClick(const Common::String &area); - - bool _loaded; - - ModeMap _modes; - Mode *_initialMode; - Mode *_currentMode; - - HorizontalAlignment _hAlignment; - VerticalAlignment _vAlignment; - - String _areaDown; - -}; - - -} // End of namespace GUI - - -#endif diff --git a/backends/events/default/default-events.cpp b/backends/events/default/default-events.cpp index 9bafdd9e4f..026892a050 100644 --- a/backends/events/default/default-events.cpp +++ b/backends/events/default/default-events.cpp @@ -28,8 +28,8 @@ #include "common/system.h" #include "common/config-manager.h" #include "backends/events/default/default-events.h" -#include "backends/common/keymapper.h" -#include "backends/common/virtual-keyboard.h" +#include "backends/keymapper/keymapper.h" +#include "backends/vkeybd/virtual-keyboard.h" #include "engines/engine.h" #include "gui/message.h" 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 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 { + 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::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::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::iterator it; + for (it = _keys.begin(); it != _keys.end(); it++) { + if ((*it)->key == keystate) + return (*it); + } + return 0; + } + + List getHardwareKeys() const { + return _keys; + } + + uint count() const { + return _keys.size(); + } + + +private: + + void checkForKey(HardwareKey *key) { + List::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 _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 actions(map->getActions()), unmapped; + List::iterator actIt; + List keys = _hardwareKeys->getHardwareKeys(); + List::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 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::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::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::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::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::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::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::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 + : public UnaryFunction { + + 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& 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 _actions; + HashMap _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::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::iterator Iterator; + + EventManager *_eventMan; + KeymapManager *_keymapMan; + + + struct MapRecord { + Keymap* keymap; + bool inherit; + }; + + Stack _activeMaps; + +}; + +} // end of namespace Common + +#endif diff --git a/backends/module.mk b/backends/module.mk index 758dff13b2..49ef78326c 100644 --- a/backends/module.mk +++ b/backends/module.mk @@ -28,13 +28,15 @@ MODULE_OBJS := \ saves/default/default-saves.o \ saves/compressed/compressed-saves.o \ timer/default/default-timer.o \ - common/virtual-keyboard.o \ - common/virtual-keyboard-gui.o \ - common/virtual-keyboard-parser.o \ - common/keymap.o \ - common/keymap-manager.o \ - common/keymapper.o \ - common/action.o \ + keymapper/action.o \ + keymapper/keymap.o \ + keymapper/keymap-manager.o \ + keymapper/keymapper.o \ + vkeybd/image-map.o \ + vkeybd/polygon.o \ + vkeybd/virtual-keyboard.o \ + vkeybd/virtual-keyboard-gui.o \ + vkeybd/virtual-keyboard-parser.o # Include common rules include $(srcdir)/rules.mk diff --git a/backends/platform/sdl/events.cpp b/backends/platform/sdl/events.cpp index 830555e514..3b2baf6aa0 100644 --- a/backends/platform/sdl/events.cpp +++ b/backends/platform/sdl/events.cpp @@ -24,7 +24,7 @@ */ #include "backends/platform/sdl/sdl.h" -#include "backends/common/keymapper.h" +#include "backends/keymapper/keymapper.h" #include "common/util.h" #include "common/events.h" diff --git a/backends/vkeybd/image-map.cpp b/backends/vkeybd/image-map.cpp new file mode 100644 index 0000000000..d97b662c7d --- /dev/null +++ b/backends/vkeybd/image-map.cpp @@ -0,0 +1,69 @@ +/* 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/vkeybd/image-map.h" + +namespace Common { + +ImageMap::~ImageMap() { + removeAllAreas(); +} + +Polygon *ImageMap::createArea(const String& id) { + if (_areas.contains(id)) { + warning("Image map already contains an area with target of '%s'", id.c_str()); + return 0; + } + Polygon *p = new Polygon(); + _areas[id] = p; + return p; +} + +void ImageMap::removeArea(const String& id) { + if (!_areas.contains(id)) + return; + delete _areas[id]; + _areas.erase(id); +} + +void ImageMap::removeAllAreas() { + HashMap::iterator it; + for (it = _areas.begin(); it != _areas.end(); it++) { + delete it->_value; + } + _areas.clear(); +} + +String ImageMap::findMapArea(int16 x, int16 y) { + HashMap::iterator it; + for (it = _areas.begin(); it != _areas.end(); it++) { + if (it->_value->contains(x, y)) + return it->_key; + } + return ""; +} + + +} // End of namespace Common diff --git a/backends/vkeybd/image-map.h b/backends/vkeybd/image-map.h new file mode 100644 index 0000000000..ed6feaa26e --- /dev/null +++ b/backends/vkeybd/image-map.h @@ -0,0 +1,53 @@ +/* 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_IMAGEMAP_H +#define COMMON_IMAGEMAP_H + +#include "common/hashmap.h" +#include "common/hash-str.h" +#include "backends/vkeybd/polygon.h" + +namespace Common { + +class ImageMap { + +public: + + ~ImageMap(); + + Polygon *createArea(const String& id); + void removeArea(const String& id); + void removeAllAreas(); + String findMapArea(int16 x, int16 y); + +protected: + HashMap _areas; +}; + + +} // End of namespace Common + +#endif diff --git a/backends/vkeybd/polygon.cpp b/backends/vkeybd/polygon.cpp new file mode 100644 index 0000000000..77ef3f0f44 --- /dev/null +++ b/backends/vkeybd/polygon.cpp @@ -0,0 +1,55 @@ +/* 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/vkeybd/polygon.h" + +namespace Common { + +bool Polygon::contains(int16 x, int16 y) const { + int yflag0; + int yflag1; + bool inside_flag = false; + unsigned int pt; + + const Point *vtx0 = &_points[_points.size() - 1]; + const Point *vtx1 = &_points[0]; + + yflag0 = (vtx0->y >= y); + for (pt = 0; pt < _points.size(); pt++, vtx1++) { + yflag1 = (vtx1->y >= y); + if (yflag0 != yflag1) { + if (((vtx1->y - y) * (vtx0->x - vtx1->x) >= + (vtx1->x - x) * (vtx0->y - vtx1->y)) == yflag1) { + inside_flag = !inside_flag; + } + } + yflag0 = yflag1; + vtx0 = vtx1; + } + + return inside_flag; +} + +} // end of namespace Common diff --git a/backends/vkeybd/polygon.h b/backends/vkeybd/polygon.h new file mode 100644 index 0000000000..69df2c0ca3 --- /dev/null +++ b/backends/vkeybd/polygon.h @@ -0,0 +1,114 @@ +/* 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_POLYGON_H +#define COMMON_POLYGON_H + +#include "common/array.h" +#include "common/rect.h" + +namespace Common { + +struct Polygon { + + + Polygon() {} + Polygon(const Polygon& p) : _points(p._points), _bound(p._bound) {} + Polygon(Array p) : _points(p) { + if (p.empty()) return; + _bound = Rect(p[0].x, p[0].y, p[0].x, p[0].y); + for (uint i = 1; i < p.size(); i++) { + _bound.extend(Rect(p[i].x, p[i].y, p[i].x, p[i].y)); + } + } + Polygon(Point *p, int n) { + for (int i = 0; i < n; i++) { + addPoint(p[i]); + } + } + virtual ~Polygon() {} + + void addPoint(const Point& p) { + _points.push_back(p); + _bound.extend(Rect(p.x, p.y, p.x, p.y)); + } + + void addPoint(int16 x, int16 y) { + addPoint(Point(x,y)); + } + + uint getPointCount() { + return _points.size(); + } + + /*! @brief check if given position is inside this polygon + + @param x the horizontal position to check + @param y the vertical position to check + + @return true if the given position is inside this polygon, false otherwise + */ + virtual bool contains(int16 x, int16 y) const; + + /*! @brief check if given point is inside this polygon + + @param p the point to check + + @return true if the given point is inside this polygon, false otherwise + */ + virtual bool contains(const Point &p) const { + return contains(p.x, p.y); + } + + virtual void moveTo(int16 x, int16 y) { + int16 dx = x - ((_bound.right + _bound.left) / 2); + int16 dy = y - ((_bound.bottom + _bound.top) / 2); + translate(dx, dy); + } + + virtual void moveTo(const Point &p) { + moveTo(p.x, p.y); + } + + virtual void translate(int16 dx, int16 dy) { + Array::iterator it; + for (it = _points.begin(); it != _points.end(); it++) { + it->x += dx; + it->y += dy; + } + } + + virtual Rect getBoundingRect() const { + return _bound; + } + +private: + Array _points; + Rect _bound; +}; + +} // end of namespace Common + +#endif diff --git a/backends/vkeybd/virtual-keyboard-gui.cpp b/backends/vkeybd/virtual-keyboard-gui.cpp new file mode 100644 index 0000000000..0dcea70292 --- /dev/null +++ b/backends/vkeybd/virtual-keyboard-gui.cpp @@ -0,0 +1,376 @@ +/* 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/vkeybd/virtual-keyboard-gui.h" +#include "graphics/cursorman.h" +#include "gui/newgui.h" + +namespace Common { + +VirtualKeyboardGUI::VirtualKeyboardGUI(VirtualKeyboard *kbd) { + _kbd = kbd; + + assert(g_system); + _system = g_system; + + _lastScreenChanged = _system->getScreenChangeID(); + + memset(_cursor, 0xFF, sizeof(_cursor)); + + _displaying = _needRedraw = _drag = _drawCaret = _displayEnabled = false; + _firstRun = true; + + _cursorAnimateTimer = 0; +} + +void VirtualKeyboardGUI::initMode(VirtualKeyboard::Mode *mode) { + _kbdSurface = mode->image; + _kbdTransparentColor = mode->transparentColor; + _kbdBound.setWidth(_kbdSurface->w + 1); + _kbdBound.setHeight(_kbdSurface->h + 1); + _needRedraw = true; + + _displayEnabled = false; + if (!mode->displayArea) + return; + Rect r = *(mode->displayArea); + + // choose font + _dispFont = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont); + if (!fontIsSuitable(_dispFont, r)) { + _dispFont = FontMan.getFontByUsage(Graphics::FontManager::kGUIFont); + if (!fontIsSuitable(_dispFont, r)) + return; + } + _dispX = r.left; + _dispY = r.top + (_dispFont->getFontHeight() - r.height() + 1) / 2; + _dispSurface.free(); + _dispSurface.create(r.width() + 1, _dispFont->getFontHeight(), sizeof(OverlayColor)); + _dispI = 0; + _dispForeColor = mode->displayFontColor; + _dispBackColor = _dispForeColor + 0xFF; + _displayEnabled = true; +} + +bool VirtualKeyboardGUI::fontIsSuitable(const Graphics::Font *font, const Rect& rect) { + return (font->getMaxCharWidth() < rect.width() && + font->getFontHeight() < rect.height()); +} + +void VirtualKeyboardGUI::run() { + if (_lastScreenChanged != _system->getScreenChangeID()) + screenChanged(); + + // TODO: set default position if position is somehow invalid + if (_firstRun) { + _firstRun = false; + setDefaultPosition(); + } + + if (!g_gui.isActive()) { + _system->showOverlay(); + _system->clearOverlay(); + } + _overlayBackup.create(_system->getOverlayWidth(), _system->getOverlayHeight(), sizeof(OverlayColor)); + _system->grabOverlay((OverlayColor*)_overlayBackup.pixels, _overlayBackup.w); + resetDirtyRect(); + + setupCursor(); + + _displaying = true; + mainLoop(); + + removeCursor(); + + _system->copyRectToOverlay((OverlayColor*)_overlayBackup.pixels, _overlayBackup.w, 0, 0, _overlayBackup.w, _overlayBackup.h); + if (!g_gui.isActive()) _system->hideOverlay(); + + _overlayBackup.free(); +} + +void VirtualKeyboardGUI::hide() { + _displaying = false; +} + +void VirtualKeyboardGUI::reset() { + _kbdBound.left = _kbdBound.top + = _kbdBound.right = _kbdBound.bottom = 0; + _displaying = _drag = false; + _firstRun = true; + _lastScreenChanged = _system->getScreenChangeID(); + _kbdSurface = 0; +} + +void VirtualKeyboardGUI::setDefaultPosition() +{ + int16 scrW = _system->getOverlayWidth(), scrH = _system->getOverlayHeight(); + int16 kbdW = _kbdBound.width(), kbdH = _kbdBound.height(); + int16 posX = 0, posY = 0; + if (scrW != kbdW) { + switch (_kbd->_hAlignment) { + case VirtualKeyboard::kAlignLeft: + posX = 0; + break; + case VirtualKeyboard::kAlignCentre: + posX = (scrW - kbdW) / 2; + break; + case VirtualKeyboard::kAlignRight: + posX = scrW - kbdW; + break; + } + } + if (scrH != kbdH) { + switch (_kbd->_vAlignment) { + case VirtualKeyboard::kAlignTop: + posY = 0; + break; + case VirtualKeyboard::kAlignMiddle: + posY = (scrH - kbdH) / 2; + break; + case VirtualKeyboard::kAlignBottom: + posY = scrH - kbdH; + break; + } + } + _kbdBound.moveTo(posX, posY); +} + +void VirtualKeyboardGUI::move(int16 x, int16 y) { + // add old position to dirty area + extendDirtyRect(_kbdBound); + _needRedraw = true; + + // snap to edge of screen + if (ABS(x) < SNAP_WIDTH) + x = 0; + int16 x2 = _system->getOverlayWidth() - _kbdBound.width(); + if (ABS(x - x2) < SNAP_WIDTH) + x = x2; + if (ABS(y) < SNAP_WIDTH) + y = 0; + int16 y2 = _system->getOverlayHeight() - _kbdBound.height(); + if (ABS(y - y2) < SNAP_WIDTH) + y = y2; + + _kbdBound.moveTo(x, y); +} + +void VirtualKeyboardGUI::screenChanged() { + _lastScreenChanged = _system->getScreenChangeID(); + if (!_kbd->checkModeResolutions()) + _displaying = false; +} + + +void VirtualKeyboardGUI::mainLoop() { + Common::EventManager *eventMan = _system->getEventManager(); + + while (_displaying) { + if (_displayEnabled) { + if (_kbd->_keyQueue.hasStringChanged()) + _refreshDisplay = true; + animateCaret(); + if (_refreshDisplay) updateDisplay();; + } + if (_needRedraw) redraw(); + animateCursor(); + _system->updateScreen(); + Common::Event event; + while (eventMan->pollEvent(event)) { + switch (event.type) { + case Common::EVENT_LBUTTONDOWN: + if (_kbdBound.contains(event.mouse)) { + _kbd->handleMouseDown(event.mouse.x - _kbdBound.left, + event.mouse.y - _kbdBound.top); + } + break; + case Common::EVENT_LBUTTONUP: + if (_kbdBound.contains(event.mouse)) { + _kbd->handleMouseUp(event.mouse.x - _kbdBound.left, + event.mouse.y - _kbdBound.top); + } + break; + case Common::EVENT_MOUSEMOVE: + if (_drag) + move(event.mouse.x - _dragPoint.x, + event.mouse.y - _dragPoint.y); + break; + case Common::EVENT_SCREEN_CHANGED: + screenChanged(); + break; + case Common::EVENT_QUIT: + _system->quit(); + return; + default: + break; + } + } + // Delay for a moment + _system->delayMillis(10); + } +} + +void VirtualKeyboardGUI::startDrag(int16 x, int16 y) { + _drag = true; + _dragPoint.x = x; + _dragPoint.y = y; +} + +void VirtualKeyboardGUI::endDrag() { + _drag = false; +} + +void VirtualKeyboardGUI::extendDirtyRect(const Rect &r) { + if (_dirtyRect.isValidRect()) { + _dirtyRect.extend(r); + } else { + _dirtyRect = r; + } + _dirtyRect.clip(Rect(0, 0, _overlayBackup.w, _overlayBackup.h)); +} + +void VirtualKeyboardGUI::resetDirtyRect() { + _dirtyRect.setWidth(-1); +} + +void VirtualKeyboardGUI::redraw() { + assert(_kbdSurface); + + extendDirtyRect(_kbdBound); + + Graphics::SurfaceKeyColored surf; + surf.create(_dirtyRect.width()+1, _dirtyRect.height()+1, sizeof(OverlayColor)); + + OverlayColor *scr = (OverlayColor *)surf.pixels; + const OverlayColor *ove = (OverlayColor *) _overlayBackup.getBasePtr(_dirtyRect.left, _dirtyRect.top); + int16 h = surf.h; + + while (h-- > 0) { + memcpy(scr, ove, surf.w * sizeof(OverlayColor)); + scr += surf.w; + ove += _overlayBackup.w; + } + + int16 keyX = _kbdBound.left - _dirtyRect.left; + int16 keyY = _kbdBound.top - _dirtyRect.top; + surf.blit(_kbdSurface, keyX, keyY, _kbdTransparentColor); + if (_displayEnabled) surf.blit(&_dispSurface, keyX + _dispX, keyY + _dispY, _dispBackColor); + _system->copyRectToOverlay((OverlayColor*)surf.pixels, surf.w, + _dirtyRect.left, _dirtyRect.top, surf.w, surf.h); + + surf.free(); + + _needRedraw = false; + + resetDirtyRect(); +} + +uint VirtualKeyboardGUI::calculateEndIndex(const String& str, uint startIndex) { + int16 w = 0; + while (w <= _dispSurface.w && startIndex < str.size()) { + w += _dispFont->getCharWidth(str[startIndex++]); + } + if (w > _dispSurface.w) startIndex--; + return startIndex; +} + +void VirtualKeyboardGUI::animateCaret() { + if (_system->getMillis() % kCaretBlinkTime < kCaretBlinkTime / 2) { + if (!_drawCaret) { + _drawCaret = true; + _refreshDisplay = true; + } + } else { + if (_drawCaret) { + _drawCaret = false; + _refreshDisplay = true; + } + } +} + +void VirtualKeyboardGUI::updateDisplay() { + if (!_displayEnabled) return; + + // calculate the text to display + uint cursorPos = _kbd->_keyQueue.getInsertIndex(); + String wholeText = _kbd->_keyQueue.getString(); + uint dispTextEnd; + if (_dispI > cursorPos) + _dispI = cursorPos; + + dispTextEnd = calculateEndIndex(wholeText, _dispI); + while (cursorPos > dispTextEnd) + dispTextEnd = calculateEndIndex(wholeText, ++_dispI); + + String dispText = String(wholeText.c_str() + _dispI, wholeText.c_str() + dispTextEnd); + + // draw to display surface + _dispSurface.fillRect(Rect(0, 0, _dispSurface.w, _dispSurface.h), _dispBackColor); + _dispFont->drawString(&_dispSurface, dispText, 0, 0, _dispSurface.w, _dispForeColor); + if (_drawCaret) { + String beforeCaret(wholeText.c_str() + _dispI, wholeText.c_str() + cursorPos); + int16 caretX = _dispFont->getStringWidth(beforeCaret); + _dispSurface.drawLine(caretX, 0, caretX, _dispSurface.h, _dispForeColor); + } + + _needRedraw = true; +} + +void VirtualKeyboardGUI::setupCursor() { + const byte palette[] = { + 255, 255, 255, 0, + 255, 255, 255, 0, + 171, 171, 171, 0, + 87, 87, 87, 0 + }; + + CursorMan.pushCursorPalette(palette, 0, 4); + CursorMan.pushCursor(NULL, 0, 0, 0, 0); + CursorMan.showMouse(true); +} + +void VirtualKeyboardGUI::animateCursor() { + int time = _system->getMillis(); + if (time > _cursorAnimateTimer + kCursorAnimateDelay) { + for (int i = 0; i < 15; i++) { + if ((i < 6) || (i > 8)) { + _cursor[16 * 7 + i] = _cursorAnimateCounter; + _cursor[16 * i + 7] = _cursorAnimateCounter; + } + } + + CursorMan.replaceCursor(_cursor, 16, 16, 7, 7); + + _cursorAnimateTimer = time; + _cursorAnimateCounter = (_cursorAnimateCounter + 1) % 4; + } +} + +void VirtualKeyboardGUI::removeCursor() { + CursorMan.popCursor(); + CursorMan.popCursorPalette(); +} + +} // end of namespace Common diff --git a/backends/vkeybd/virtual-keyboard-gui.h b/backends/vkeybd/virtual-keyboard-gui.h new file mode 100644 index 0000000000..5836859262 --- /dev/null +++ b/backends/vkeybd/virtual-keyboard-gui.h @@ -0,0 +1,108 @@ +/* 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_VIRTUAL_KEYBOARD_GUI +#define COMMON_VIRTUAL_KEYBOARD_GUI + +#include "backends/vkeybd/virtual-keyboard.h" +#include "common/rect.h" +#include "common/system.h" +#include "graphics/fontman.h" +#include "graphics/surface-keycolored.h" + +namespace Common { + +class VirtualKeyboardGUI { + +public: + + VirtualKeyboardGUI(VirtualKeyboard *kbd); + void initMode(VirtualKeyboard::Mode *mode); + void run(); + void hide(); + bool isDisplaying() { return _displaying; } + void reset(); + void startDrag(int16 x, int16 y); + void endDrag(); + +private: + + OSystem *_system; + VirtualKeyboard *_kbd; + Graphics::Surface *_kbdSurface; + OverlayColor _kbdTransparentColor; + + static const int SNAP_WIDTH = 10; + + Graphics::Surface _overlayBackup; + + Rect _dirtyRect; + + bool _displayEnabled; + bool _refreshDisplay; + Graphics::Surface _dispSurface; + const Graphics::Font *_dispFont; + int16 _dispX, _dispY; + uint _dispI; + OverlayColor _dispForeColor, _dispBackColor; + + Rect _kbdBound; + + Point _dragPoint; + bool _drag; + + bool _displaying; + bool _firstRun; + bool _needRedraw; + int _lastScreenChanged; + + void setDefaultPosition(); + void move(int16 x, int16 y); + void screenChanged(); + void mainLoop(); + void extendDirtyRect(const Rect &r); + void resetDirtyRect(); + void redraw(); + void updateDisplay(); + bool fontIsSuitable(const Graphics::Font *font, const Rect& rect); + uint calculateEndIndex(const String& str, uint startIndex); + + bool _drawCaret; + static const int kCaretBlinkTime = 500; + void animateCaret(); + + static const int kCursorAnimateDelay = 250; + int _cursorAnimateCounter; + int _cursorAnimateTimer; + byte _cursor[2048]; + void setupCursor(); + void removeCursor(); + void animateCursor(); + +}; + +} // end of namespace Common + +#endif diff --git a/backends/vkeybd/virtual-keyboard-parser.cpp b/backends/vkeybd/virtual-keyboard-parser.cpp new file mode 100644 index 0000000000..f3d71057b7 --- /dev/null +++ b/backends/vkeybd/virtual-keyboard-parser.cpp @@ -0,0 +1,430 @@ +/* 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/vkeybd/virtual-keyboard-parser.h" + +#include "common/keyboard.h" +#include "graphics/imageman.h" +#include "common/util.h" + +namespace Common { + +VirtualKeyboardParser::VirtualKeyboardParser(VirtualKeyboard *kbd) : XMLParser() { + _keyboard = kbd; + + _callbacks["keyboard"] = &VirtualKeyboardParser::parserCallback_Keyboard; + _callbacks["mode"] = &VirtualKeyboardParser::parserCallback_Mode; + _callbacks["event"] = &VirtualKeyboardParser::parserCallback_Event; + _callbacks["layout"] = &VirtualKeyboardParser::parserCallback_Layout; + _callbacks["map"] = &VirtualKeyboardParser::parserCallback_Map; + _callbacks["area"] = &VirtualKeyboardParser::parserCallback_Area; + + _closedCallbacks["keyboard"] = &VirtualKeyboardParser::parserCallback_KeyboardClosed; + _closedCallbacks["mode"] = &VirtualKeyboardParser::parserCallback_ModeClosed; +} + +void VirtualKeyboardParser::cleanup() { + _mode = 0; + _kbdParsed = false; + _initialModeName.clear(); + if (_parseMode == kParseFull) { + // reset keyboard to remove existing config + _keyboard->reset(); + } +} + +bool VirtualKeyboardParser::keyCallback(String keyName) { + if (!_callbacks.contains(_activeKey.top()->name)) + return parserError("%s is not a valid key name.", keyName.c_str()); + + return (this->*(_callbacks[_activeKey.top()->name]))(); +} + +bool VirtualKeyboardParser::closedKeyCallback(String keyName) { + if (!_closedCallbacks.contains(_activeKey.top()->name)) + return true; + + return (this->*(_closedCallbacks[_activeKey.top()->name]))(); +} + +bool VirtualKeyboardParser::parserCallback_Keyboard() { + ParserNode *kbdNode = getActiveNode(); + + assert(kbdNode->name == "keyboard"); + + if (getParentNode(kbdNode) != 0) + return parserError("Keyboard element must be root"); + + if (_kbdParsed) + return parserError("Only a single keyboard element is allowed"); + + // if not full parse then we're done + if (_parseMode == kParseCheckResolutions) + return true; + + if (!kbdNode->values.contains("initial_mode")) + return parserError("Keyboard element must contain initial_mode attribute"); + + _initialModeName = kbdNode->values["initial_mode"]; + + if (kbdNode->values.contains("h_align")) { + String h = kbdNode->values["h_align"]; + if (h == "left") + _keyboard->_hAlignment = VirtualKeyboard::kAlignLeft; + else if (h == "centre" || h == "center") + _keyboard->_hAlignment = VirtualKeyboard::kAlignCentre; + else if (h == "right") + _keyboard->_hAlignment = VirtualKeyboard::kAlignRight; + } + + if (kbdNode->values.contains("v_align")) { + String v = kbdNode->values["h_align"]; + if (v == "top") + _keyboard->_vAlignment = VirtualKeyboard::kAlignTop; + else if (v == "middle" || v == "center") + _keyboard->_vAlignment = VirtualKeyboard::kAlignMiddle; + else if (v == "bottom") + _keyboard->_vAlignment = VirtualKeyboard::kAlignBottom; + } + + return true; +} + +bool VirtualKeyboardParser::parserCallback_KeyboardClosed() { + _kbdParsed = true; + if (!_keyboard->_initialMode) + return parserError("Initial mode of keyboard pack not defined"); + return true; +} + +bool VirtualKeyboardParser::parserCallback_Mode() { + ParserNode *modeNode = getActiveNode(); + + assert(modeNode->name == "mode"); + + if (getParentNode(modeNode) == 0 || getParentNode(modeNode)->name != "keyboard") + return parserError("Mode element must be child of keyboard element"); + + if (!modeNode->values.contains("name") || !modeNode->values.contains("resolutions")) + return parserError("Mode element must contain name and resolutions attributes"); + + String name = modeNode->values["name"]; + + if (_parseMode == kParseFull) { + // if full parse then add new mode to keyboard + + if (_keyboard->_modes.contains(name)) + return parserError("Mode '%s' has already been defined", name.c_str()); + + VirtualKeyboard::Mode mode; + mode.name = name; + _keyboard->_modes[name] = mode; + _mode = &(_keyboard->_modes[name]); + + if (name == _initialModeName) + _keyboard->_initialMode = _mode; + } else + _mode = &(_keyboard->_modes[name]); + + String resolutions = modeNode->values["resolutions"]; + StringTokenizer tok (resolutions, " ,"); + + // select best resolution simply by minimising the difference between the + // overlay size and the resolution dimensions. + // TODO: improve this by giving preference to a resolution that is smaller + // than the overlay res (so the keyboard can't be too big for the screen) + uint16 scrW = g_system->getOverlayWidth(), scrH = g_system->getOverlayHeight(); + uint32 diff = 0xFFFFFFFF; + String newResolution; + for (String res = tok.nextToken(); res.size() > 0; res = tok.nextToken()) { + int resW, resH; + if (sscanf(res.c_str(), "%dx%d", &resW, &resH) != 2) { + return parserError("Invalid resolution specification"); + } else { + if (resW == scrW && resH == scrH) { + newResolution = res; + break; + } else { + uint32 newDiff = ABS(scrW - resW) + ABS(scrH - resH); + if (newDiff < diff) { + diff = newDiff; + newResolution = res; + } + } + } + } + + if (newResolution.empty()) + return parserError("No acceptable resolution was found"); + + if (_parseMode == kParseCheckResolutions) { + if (_mode->resolution == newResolution) { + modeNode->ignore = true; + return true; + } else { + // remove data relating to old resolution + ImageMan.unregisterSurface(_mode->bitmapName); + _mode->bitmapName.clear(); + _mode->image = 0; + _mode->imageMap.removeAllAreas(); + } + } + + _mode->resolution = newResolution; + _layoutParsed = false; + + return true; +} + +bool VirtualKeyboardParser::parserCallback_ModeClosed() { + if (!_layoutParsed) { + return parserError("'%s' layout missing from '%s' mode", _mode->resolution.c_str(), _mode->name.c_str()); + } + return true; +} + +bool VirtualKeyboardParser::parserCallback_Event() { + ParserNode *evtNode = getActiveNode(); + + assert(evtNode->name == "event"); + + if (getParentNode(evtNode) == 0 || getParentNode(evtNode)->name != "mode") + return parserError("Event element must be child of mode element"); + + if (!evtNode->values.contains("name") || !evtNode->values.contains("type")) + return parserError("Event element must contain name and type attributes"); + + assert(_mode); + + // if just checking resolutions we're done + if (_parseMode == kParseCheckResolutions) + return true; + + String name = evtNode->values["name"]; + if (_mode->events.contains(name)) + return parserError("Event '%s' has already been defined", name.c_str()); + + VirtualKeyboard::Event *evt = new VirtualKeyboard::Event(); + evt->name = name; + + String type = evtNode->values["type"]; + if (type == "key") { + if (!evtNode->values.contains("code") || !evtNode->values.contains("ascii")) { + delete evt; + return parserError("Key event element must contain code and ascii attributes"); + } + + evt->type = VirtualKeyboard::kEventKey; + + KeyCode code = (KeyCode)atoi(evtNode->values["code"].c_str()); + uint16 ascii = atoi(evtNode->values["ascii"].c_str()); + + byte flags = 0; + if (evtNode->values.contains("modifiers")) + flags = parseFlags(evtNode->values["modifiers"]); + + evt->data = new KeyState(code, ascii, flags); + + } else if (type == "modifier") { + if (!evtNode->values.contains("modifiers")) { + delete evt; + return parserError("Key modifier element must contain modifier attributes"); + } + + evt->type = VirtualKeyboard::kEventModifier; + byte *flags = new byte; + *(flags) = parseFlags(evtNode->values["modifiers"]); + evt->data = flags; + + } else if (type == "switch_mode") { + if (!evtNode->values.contains("mode")) { + delete evt; + return parserError("Switch mode event element must contain mode attribute"); + } + + evt->type = VirtualKeyboard::kEventSwitchMode; + evt->data = new String(evtNode->values["mode"]); + } else if (type == "close") { + evt->type = VirtualKeyboard::kEventClose; + evt->data = 0; + } else { + delete evt; + return parserError("Event type '%s' not known", type.c_str()); + } + + _mode->events[name] = evt; + + return true; +} + +bool VirtualKeyboardParser::parserCallback_Layout() { + ParserNode *layoutNode = getActiveNode(); + + assert(layoutNode->name == "layout"); + + if (getParentNode(layoutNode) == 0 || getParentNode(layoutNode)->name != "mode") + return parserError("Layout element must be child of mode element"); + + if (!layoutNode->values.contains("resolution") || !layoutNode->values.contains("bitmap")) + return parserError("Layout element must contain resolution and bitmap attributes"); + + assert(!_mode->resolution.empty()); + + String res = layoutNode->values["resolution"]; + + if (res != _mode->resolution) { + layoutNode->ignore = true; + return true; + } + + _mode->bitmapName = layoutNode->values["bitmap"]; + _mode->image = ImageMan.getSurface(_mode->bitmapName); + if (!_mode->image) { + if (!ImageMan.registerSurface(_mode->bitmapName, 0)) + return parserError("Error loading bitmap '%s'", _mode->bitmapName.c_str()); + + _mode->image = ImageMan.getSurface(_mode->bitmapName); + if (!_mode->image) + return parserError("Error loading bitmap '%s'", _mode->bitmapName.c_str()); + } + + if (layoutNode->values.contains("transparent_color")) { + int r, g, b; + if (!parseIntegerKey(layoutNode->values["transparent_color"].c_str(), 3, &r, &g, &b)) + return parserError("Could not parse color value"); + _mode->transparentColor = g_system->RGBToColor(r, g, b); + } else + _mode->transparentColor = g_system->RGBToColor(255, 0, 255); // default to purple + + if (layoutNode->values.contains("display_font_color")) { + int r, g, b; + if (!parseIntegerKey(layoutNode->values["display_font_color"].c_str(), 3, &r, &g, &b)) + return parserError("Could not parse color value"); + _mode->displayFontColor = g_system->RGBToColor(r, g, b); + } else + _mode->displayFontColor = g_system->RGBToColor(0, 0, 0); // default to black + + _layoutParsed = true; + + return true; +} + +bool VirtualKeyboardParser::parserCallback_Map() { + ParserNode *mapNode = getActiveNode(); + + assert(mapNode->name == "map"); + + if (getParentNode(mapNode) == 0 || getParentNode(mapNode)->name != "layout") + return parserError("Map element must be child of layout element"); + + return true; +} + +bool VirtualKeyboardParser::parserCallback_Area() { + ParserNode *areaNode = getActiveNode(); + + assert(areaNode->name == "area"); + + if (getParentNode(areaNode) == 0 || getParentNode(areaNode)->name != "map") + return parserError("Area element must be child of map element"); + + if (!areaNode->values.contains("shape") || !areaNode->values.contains("coords") || !areaNode->values.contains("target")) + return parserError("Area element must contain shape, coords and target attributes"); + + String& shape = areaNode->values["shape"]; + String& target = areaNode->values["target"]; + String& coords = areaNode->values["coords"]; + + if (target == "display_area") { + if (shape != "rect") + return parserError("display_area must be a rect area"); + _mode->displayArea = new Rect(); + return parseRect(_mode->displayArea, coords); + } else if (shape == "rect") { + Polygon *poly = _mode->imageMap.createArea(target); + return parseRectAsPolygon(poly, coords); + } else if (shape == "poly") { + Polygon *poly = _mode->imageMap.createArea(target); + return parsePolygon(poly, coords); + } + return parserError("Area shape '%s' not known", shape.c_str()); +} + +byte VirtualKeyboardParser::parseFlags(const String& flags) { + if (flags.empty()) + return 0; + + StringTokenizer tok(flags, ", "); + byte val = 0; + for (String fl = tok.nextToken(); !fl.empty(); fl = tok.nextToken()) { + if (fl == "ctrl" || fl == "control") + val |= KBD_CTRL; + else if (fl == "alt") + val |= KBD_ALT; + else if (fl == "shift") + val |= KBD_SHIFT; + } + return val; +} + +bool VirtualKeyboardParser::parseRect(Rect *rect, const String& coords) { + int x1, y1, x2, y2; + if (!parseIntegerKey(coords.c_str(), 4, &x1, &y1, &x2, &y2)) + return parserError("Invalid coords for rect area"); + rect->left = x1; rect->top = y1; rect->right = x2; rect->bottom = y2; + if (!rect->isValidRect()) + return parserError("Rect area is not a valid rectangle"); + return true; +} + +bool VirtualKeyboardParser::parsePolygon(Polygon *poly, const String& coords) { + StringTokenizer tok (coords, ", "); + for (String st = tok.nextToken(); !st.empty(); st = tok.nextToken()) { + int x, y; + if (sscanf(st.c_str(), "%d", &x) != 1) + return parserError("Invalid coords for polygon area"); + st = tok.nextToken(); + if (sscanf(st.c_str(), "%d", &y) != 1) + return parserError("Invalid coords for polygon area"); + poly->addPoint(x, y); + } + if (poly->getPointCount() < 3) + return parserError("Invalid coords for polygon area"); + + return true; +} + +bool VirtualKeyboardParser::parseRectAsPolygon(Polygon *poly, const String& coords) { + Rect rect; + if (!parseRect(&rect, coords)) + return false; + poly->addPoint(rect.left, rect.top); + poly->addPoint(rect.right, rect.top); + poly->addPoint(rect.right, rect.bottom); + poly->addPoint(rect.left, rect.bottom); + return true; +} + +} // end of namespace GUI diff --git a/backends/vkeybd/virtual-keyboard-parser.h b/backends/vkeybd/virtual-keyboard-parser.h new file mode 100644 index 0000000000..59a770bdce --- /dev/null +++ b/backends/vkeybd/virtual-keyboard-parser.h @@ -0,0 +1,217 @@ +/* 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_VIRTUAL_KEYBOARD_PARSER +#define COMMON_VIRTUAL_KEYBOARD_PARSER + +#include "common/xmlparser.h" +#include "backends/vkeybd/virtual-keyboard.h" + +/** + TODO - information about optional attributes and their default values + + + *************************************** + ** Virtual Keyboard Pack File Format ** + *************************************** + +The new virtual keyboard for ScummVM is implemented in the same way as a HTML +ImageMap. It uses a single bitmap of the entire keyboard layout and then a +image map description allows certain areas of the bitmap to be given special +actions. Most of these actions will be a virtual key press event, but there +will also be special keys that will change the keyboard layout or close the +keyboard. The HTML image map description is contained in a larger XML file that +can describe all the different modes of the keyboard, and also different +keyboard layouts for different screen resolutions. + + ******************************************** + ** Example keyboard pack description file ** + ******************************************** + + + + + + + + + ... + + + + + ... + + + + + ... + + + + + + + + ... + + + + + + ... + + + +************************* +** Description of tags ** +************************* + + + +This is the required, root element of the file format. + +attributes: + - modes: lists all the modes that the keyboard pack contains + - initial_mode: which mode the keyboard should show initially + - v_align/h_align: where on the screen should the keyboard appear initially + +child tags: + - mode + +------------------------------------------------------------------------------- + + + +This tag encapsulates a single mode of the keyboard. Within are a number of +layouts, which provide the specific implementation at different resolutions. + +attributes: + - name: the name of the mode + - resolutions: list of the different layout resolutions + +child tags: + - layout + - event + +------------------------------------------------------------------------------- + + + +These tags describe a particular event that will be triggered by a mouse click +on a particular area. The target attribute of each image map area should be the +same as an event's name. + +attributes: + - name: name of the event + - type: what sort of event is it (key | switch_mode | close) + - for key events + - code / ascii / modifiers: describe a key press in ScummVM KeyState format + - for switch_mode events + - mode: the mode that should be switched to + +------------------------------------------------------------------------------- + + + +These tags encapsulate an implementation of a mode at a particular resolution. + +attributes: + - resolution: the screen resolution that this layout is designed for + - bitmap: filename of the 24-bit bitmap that will be used for this layout + - transparent_color: color in r,b,g format that will be used for keycolor + transparency. + +child nodes: + - map: this describes the image map using the same format as html image maps + +------------------------------------------------------------------------------- + + + +These tags describe the image map for a particular layout. It uses the exact +same format as HTML image maps. The only area shapes that are supported are +rectangles and polygons. The target attribute of each area should be the name +of an event for this mode (see tag). For information on HTML image map +format see + - http://www.w3schools.com/TAGS/tag_map.asp + - http://www.w3schools.com/TAGS/tag_area.asp + +*/ + +namespace Common { + +enum ParseMode { + kParseFull, // when loading keyboard pack for first time + kParseCheckResolutions // when re-parsing following a change in screen size +}; + +class VirtualKeyboardParser : public Common::XMLParser { + + typedef bool (VirtualKeyboardParser::*ParserCallback)(); + +public: + + VirtualKeyboardParser(VirtualKeyboard *kbd); + void setParseMode(ParseMode m) { + _parseMode = m; + } + +protected: + VirtualKeyboard *_keyboard; + + /** internal state variables of parser */ + ParseMode _parseMode; + VirtualKeyboard::Mode *_mode; // pointer to mode currently being parsed + String _initialModeName; + bool _kbdParsed; + bool _layoutParsed; + + bool keyCallback(String keyName); + bool closedKeyCallback(String keyName); + void cleanup(); + + bool parserCallback_Keyboard(); + bool parserCallback_Mode(); + bool parserCallback_Event(); + bool parserCallback_Layout(); + bool parserCallback_Map(); + bool parserCallback_Area(); + + bool parserCallback_KeyboardClosed(); + bool parserCallback_ModeClosed(); + + byte parseFlags(const String& flags); + bool parseRect(Rect *rect, const String& coords); + bool parsePolygon(Polygon *poly, const String& coords); + bool parseRectAsPolygon(Polygon *poly, const String& coords); + + HashMap _callbacks; + HashMap _closedCallbacks; +}; + +} // end of namespace GUI + +#endif diff --git a/backends/vkeybd/virtual-keyboard.cpp b/backends/vkeybd/virtual-keyboard.cpp new file mode 100644 index 0000000000..ae0fd86ee5 --- /dev/null +++ b/backends/vkeybd/virtual-keyboard.cpp @@ -0,0 +1,347 @@ +/* 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/vkeybd/virtual-keyboard.h" +#include "backends/vkeybd/virtual-keyboard-gui.h" +#include "backends/vkeybd/virtual-keyboard-parser.h" +#include "graphics/imageman.h" + +namespace Common { + +VirtualKeyboard::VirtualKeyboard() : _currentMode(0) { + assert(g_system); + _system = g_system; + + _parser = new VirtualKeyboardParser(this); + _kbdGUI = new VirtualKeyboardGUI(this); + _loaded = false; +} + +VirtualKeyboard::~VirtualKeyboard() { + deleteEvents(); + delete _kbdGUI; + delete _parser; +} + +void VirtualKeyboard::deleteEvents() { + ModeMap::iterator it_m; + EventMap::iterator it_e; + for (it_m = _modes.begin(); it_m != _modes.end(); it_m++) { + EventMap *evt = &(it_m->_value.events); + for (it_e = evt->begin(); it_e != evt->end(); it_e++) + delete it_e->_value; + } +} + +void VirtualKeyboard::reset() { + deleteEvents(); + _modes.clear(); + _initialMode = _currentMode = 0; + _hAlignment = kAlignCentre; + _vAlignment = kAlignBottom; + _keyQueue.clear(); + _loaded = false; + _kbdGUI->reset(); +} + +bool VirtualKeyboard::loadKeyboardPack(Common::String packName) { + if (Common::File::exists(packName + ".xml")) { + // uncompressed keyboard pack + if (!_parser->loadFile(packName + ".xml")) + return false; + + } else if (Common::File::exists(packName + ".zip")) { + // compressed keyboard pack +#ifdef USE_ZLIB + unzFile zipFile = unzOpen((packName + ".zip").c_str()); + if (zipFile && unzLocateFile(zipFile, (packName + ".xml").c_str(), 2) == UNZ_OK) { + unz_file_info fileInfo; + unzOpenCurrentFile(zipFile); + unzGetCurrentFileInfo(zipFile, &fileInfo, NULL, 0, NULL, 0, NULL, 0); + byte *buffer = (byte *)malloc(fileInfo.uncompressed_size+1 * sizeof(byte)); + assert(buffer); + memset(buffer, 0, (fileInfo.uncompressed_size+1)*sizeof(byte)); + unzReadCurrentFile(zipFile, buffer, fileInfo.uncompressed_size); + unzCloseCurrentFile(zipFile); + if (!_parser->loadBuffer(buffer, fileInfo.uncompressed_size+1, true)) { + unzClose(zipFile); + return false; + } + } else { + warning("Could not find %s.xml file in %s.zip keyboard pack", packName.c_str(), packName.c_str()); + unzClose(zipFile); + return false; + } + unzClose(zipFile); + + ImageMan.addArchive(packName + ".zip"); +#else + return false; +#endif + } else { + warning("Keyboard pack not found"); + return false; + } + + _parser->setParseMode(kParseFull); + _loaded = _parser->parse(); + if (_loaded) + printf("Keyboard pack '%s' loaded successfully!\n", packName.c_str()); + + return _loaded; +} + +bool VirtualKeyboard::checkModeResolutions() +{ + _parser->setParseMode(kParseCheckResolutions); + _loaded = _parser->parse(); + return _loaded; +} + +Common::String VirtualKeyboard::findArea(int16 x, int16 y) { + return _currentMode->imageMap.findMapArea(x, y); +} + +void VirtualKeyboard::processAreaClick(const Common::String& area) { + if (!_currentMode->events.contains(area)) return; + Event *evt = _currentMode->events[area]; + + switch (evt->type) { + case kEventKey: { + // add virtual keypress to queue + _keyQueue.insertKey(*(Common::KeyState*)evt->data); + break; + } + case kEventModifier: + _keyQueue.toggleFlags(*(byte*)(evt->data)); + break; + case kEventSwitchMode: + // switch to new mode + switchMode(*(Common::String *)evt->data); + _keyQueue.clearFlags(); + break; + case kEventClose: + // close virtual keyboard + _kbdGUI->hide(); + break; + } +} + +void VirtualKeyboard::switchMode(Mode *newMode) { + _kbdGUI->initMode(newMode); + _currentMode = newMode; +} + +void VirtualKeyboard::switchMode(const Common::String& newMode) { + if (!_modes.contains(newMode)) { + warning("Keyboard mode '%s' unknown", newMode.c_str()); + return; + } + switchMode(&_modes[newMode]); +} + +void VirtualKeyboard::handleMouseDown(int16 x, int16 y) { + _areaDown = findArea(x, y); + if (_areaDown.empty()) + _kbdGUI->startDrag(x, y); +} + +void VirtualKeyboard::handleMouseUp(int16 x, int16 y) { + if (!_areaDown.empty() && _areaDown == findArea(x, y)) { + processAreaClick(_areaDown); + _areaDown.clear(); + } + _kbdGUI->endDrag(); +} + +void VirtualKeyboard::show() { + if (!_loaded) { + // if not loaded then load default "vkeybd" pack + if (!loadKeyboardPack("vkeybd")) { + warning("Keyboard not loaded therefore can't be shown"); + return; + } + } + switchMode(_initialMode); + + _kbdGUI->run(); + + EventManager *eventMan = _system->getEventManager(); + assert(eventMan); + + // push keydown & keyup events into the event manager + Common::Event evt; + evt.synthetic = false; + while (!_keyQueue.empty()) { + evt.kbd = _keyQueue.pop(); + evt.type = Common::EVENT_KEYDOWN; + eventMan->pushEvent(evt); + evt.type = Common::EVENT_KEYUP; + eventMan->pushEvent(evt); + } +} + +void VirtualKeyboard::hide() { + _kbdGUI->hide(); +} + +bool VirtualKeyboard::isDisplaying() { + return _kbdGUI->isDisplaying(); +} + +VirtualKeyboard::KeyPressQueue::KeyPressQueue() { + _keyPos = _keys.end(); + _strPos = 0; +} + +void VirtualKeyboard::KeyPressQueue::toggleFlags(byte fl) { + _keyFlags ^= fl; + _strChanged = true; +} + +void VirtualKeyboard::KeyPressQueue::clearFlags() { + _keyFlags = 0; + _strChanged = true; +} + +void VirtualKeyboard::KeyPressQueue::insertKey(KeyState key) { + _strChanged = true; + switch (key.keycode) { + case KEYCODE_LEFT: + moveLeft(); + return; + case KEYCODE_RIGHT: + moveRight(); + return; + case KEYCODE_BACKSPACE: + deleteKey(); + return; + default: + ; + } + + key.flags ^= _keyFlags; + if ((key.keycode >= Common::KEYCODE_a) && (key.keycode <= Common::KEYCODE_z)) + key.ascii = (key.flags & Common::KBD_SHIFT) ? key.keycode - 32 : key.keycode; + clearFlags(); + + String keyStr; + if (key.keycode >= 32 && key.keycode <= 126) { + if (key.flags & KBD_CTRL) + keyStr += "Ctrl+"; + if (key.flags & KBD_ALT) + keyStr += "Alt+"; + if (key.flags & KBD_SHIFT && (key.ascii < 65 || key.ascii > 90)) + keyStr += "Shift+"; + keyStr += (char)key.ascii; + } + + const char *k = keyStr.c_str(); + while (char ch = *k++) + _str.insertChar(ch, _strPos++); + + VirtualKeyPress kp; + kp.key = key; + kp.strLen = keyStr.size(); + _keys.insert(_keyPos, kp); +} + +void VirtualKeyboard::KeyPressQueue::deleteKey() { + if (_keyPos == _keys.begin()) + return; + List::iterator it = _keyPos; + it--; + _strPos -= it->strLen; + while((it->strLen)-- > 0) + _str.deleteChar(_strPos); + _keys.erase(it); +} + +void VirtualKeyboard::KeyPressQueue::moveLeft() { + if (_keyPos == _keys.begin()) + return; + _keyPos--; + _strPos -= _keyPos->strLen; +} + +void VirtualKeyboard::KeyPressQueue::moveRight() { + if (_keyPos == _keys.end()) + return; + _strPos += _keyPos->strLen; + _keyPos++; +} + +KeyState VirtualKeyboard::KeyPressQueue::pop() { + bool front = (_keyPos == _keys.begin()); + VirtualKeyPress kp = *(_keys.begin()); + _keys.pop_front(); + + if (front) + _keyPos = _keys.begin(); + else + _strPos -= kp.strLen; + + while (kp.strLen-- > 0) + _str.deleteChar(0); + + return kp.key; +} + +void VirtualKeyboard::KeyPressQueue::clear() { + _keys.clear(); + _keyPos = _keys.end(); + _str.clear(); + _strPos = 0; + _keyFlags = 0; +} + +bool VirtualKeyboard::KeyPressQueue::empty() +{ + return _keys.empty(); +} + +String VirtualKeyboard::KeyPressQueue::getString() +{ + String flags; + if (_keyFlags & KBD_CTRL) + flags += "Ctrl+"; + if (_keyFlags & KBD_ALT) + flags += "Alt+"; + if (_keyFlags & KBD_SHIFT) + flags += "Shift+"; + return _str + flags; +} + +uint VirtualKeyboard::KeyPressQueue::getInsertIndex() { + return _strPos; +} + +bool VirtualKeyboard::KeyPressQueue::hasStringChanged() { + bool ret = _strChanged; + _strChanged = false; + return ret; +} + +} // end of namespace Common diff --git a/backends/vkeybd/virtual-keyboard.h b/backends/vkeybd/virtual-keyboard.h new file mode 100644 index 0000000000..f15eb4aece --- /dev/null +++ b/backends/vkeybd/virtual-keyboard.h @@ -0,0 +1,218 @@ +/* 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_VIRTUAL_KEYBOARD_H +#define COMMON_VIRTUAL_KEYBOARD_H + +class OSystem; + +#include "common/events.h" +#include "common/hashmap.h" +#include "common/hash-str.h" +#include "backends/vkeybd/image-map.h" +#include "common/keyboard.h" +#include "common/list.h" +#include "common/str.h" + +namespace Common { + +class VirtualKeyboardGUI; +class VirtualKeyboardParser; + +class VirtualKeyboard { +protected: + enum EventType { + kEventKey, + kEventModifier, + kEventSwitchMode, + kEventClose + }; + + struct Event { + Common::String name; + EventType type; + void *data; + + Event() : data(0) {} + ~Event() { + if (data) { + switch (type) { + case kEventKey: + delete (KeyState*)data; + break; + case kEventModifier: + delete (byte*)data; + break; + case kEventSwitchMode: + delete (String*)data; + break; + case kEventClose: + break; + } + } + } + }; + + typedef Common::HashMap EventMap; + + struct Mode { + Common::String name; + Common::String resolution; + Common::String bitmapName; + Graphics::Surface *image; + OverlayColor transparentColor; + Common::ImageMap imageMap; + EventMap events; + Common::Rect *displayArea; + OverlayColor displayFontColor; + + Mode() : image(0), displayArea(0) {} + ~Mode() { if (displayArea) delete displayArea; } + }; + + typedef Common::HashMap ModeMap; + + enum HorizontalAlignment { + kAlignLeft, + kAlignCentre, + kAlignRight + }; + + enum VerticalAlignment { + kAlignTop, + kAlignMiddle, + kAlignBottom + }; + + struct VirtualKeyPress { + Common::KeyState key; + uint strLen; + }; + + class KeyPressQueue { + public: + KeyPressQueue(); + void toggleFlags(byte fl); + void clearFlags(); + void insertKey(KeyState key); + void deleteKey(); + void moveLeft(); + void moveRight(); + KeyState pop(); + void clear(); + bool empty(); + String getString(); + uint getInsertIndex(); + bool hasStringChanged(); + + private: + byte _keyFlags; + + List _keys; + String _str; + + bool _strChanged; + + List::iterator _keyPos; + uint _strPos; + }; + +public: + VirtualKeyboard(); + virtual ~VirtualKeyboard(); + + /** + * Loads the keyboard pack with the given name. + * The system first looks for an uncompressed keyboard pack by searching + * for packName.xml in the filesystem, if this does not exist then it + * searches for a compressed keyboard pack by looking for packName.zip. + * @param packName name of the keyboard pack + */ + bool loadKeyboardPack(Common::String packName); + + /** + * Shows the keyboard, starting an event loop that will intercept all + * user input (like a modal GUI dialog). + * It is assumed that the game has been paused, before this is called + */ + void show(); + + /** + * Hides the keyboard, ending the event loop. + */ + void hide(); + + /** + * Returns true if the keyboard is currently being shown + */ + bool isDisplaying(); + + /** + * Returns true if the keyboard is loaded and ready to be shown + */ + bool isLoaded() { + return _loaded; + } + +protected: // TODO : clean up all this stuff + + OSystem *_system; + + friend class VirtualKeyboardGUI; + VirtualKeyboardGUI *_kbdGUI; + + KeyPressQueue _keyQueue; + + friend class VirtualKeyboardParser; + VirtualKeyboardParser *_parser; + + void reset(); + void deleteEvents(); + bool checkModeResolutions(); + void switchMode(Mode *newMode); + void switchMode(const Common::String& newMode); + void handleMouseDown(int16 x, int16 y); + void handleMouseUp(int16 x, int16 y); + String findArea(int16 x, int16 y); + void processAreaClick(const Common::String &area); + + bool _loaded; + + ModeMap _modes; + Mode *_initialMode; + Mode *_currentMode; + + HorizontalAlignment _hAlignment; + VerticalAlignment _vAlignment; + + String _areaDown; + +}; + + +} // End of namespace GUI + + +#endif -- cgit v1.2.3