summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/Makefile.am1
-rw-r--r--src/inputmanager.cpp3
-rw-r--r--src/inputmanager.h5
-rw-r--r--src/keyboardconfig.cpp310
-rw-r--r--src/keyboardconfig.h38
-rw-r--r--src/keyboarddata.h12
-rw-r--r--src/keydata.h40
8 files changed, 305 insertions, 105 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 0318d2fc2..959c1d5c6 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -568,6 +568,7 @@ SET(SRCS
keyboardconfig.cpp
keyboardconfig.h
keyboarddata.h
+ keydata.h
listener.cpp
listener.h
localconsts.h
diff --git a/src/Makefile.am b/src/Makefile.am
index 54911f281..90688a620 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -575,6 +575,7 @@ manaplus_SOURCES += gui/widgets/avatarlistbox.cpp \
keyboardconfig.cpp \
keyboardconfig.h \
keyboarddata.h \
+ keydata.h \
listener.cpp \
listener.h \
localconsts.h \
diff --git a/src/inputmanager.cpp b/src/inputmanager.cpp
index 5e30f3894..32c4ac1f1 100644
--- a/src/inputmanager.cpp
+++ b/src/inputmanager.cpp
@@ -22,6 +22,7 @@
#include "game.h"
#include "keyboardconfig.h"
+#include "keydata.h"
#include "localplayer.h"
#include "gui/chatwindow.h"
@@ -150,7 +151,7 @@ int InputManager::getInputConditionMask()
return mask;
}
-bool InputManager::checkKey(KeyFunction *key, int mask)
+bool InputManager::checkKey(const KeyData *key, int mask)
{
// logger->log("mask=%d, condition=%d", mask, key->condition);
if (!key || (key->condition & mask) != key->condition)
diff --git a/src/inputmanager.h b/src/inputmanager.h
index 7a6ac6d05..635e27a33 100644
--- a/src/inputmanager.h
+++ b/src/inputmanager.h
@@ -26,7 +26,8 @@
#include <string>
#include <map>
-struct KeyFunction;
+struct KeyData;
+//struct KeyFunction;
enum KeyCondition
{
@@ -56,7 +57,7 @@ class InputManager
int getInputConditionMask();
- bool checkKey(KeyFunction *key, int mask);
+ bool checkKey(const KeyData *key, int mask);
};
extern InputManager inputManager;
diff --git a/src/keyboardconfig.cpp b/src/keyboardconfig.cpp
index 67d31f7a8..e2b226b5d 100644
--- a/src/keyboardconfig.cpp
+++ b/src/keyboardconfig.cpp
@@ -48,7 +48,7 @@ class KeyFunctor
return keys[key1].priority >= keys[key2].priority;
}
- KeyFunction *keys;
+ const KeyData *keys;
} keySorter;
@@ -56,32 +56,17 @@ void KeyboardConfig::init()
{
for (int i = 0; i < KEY_TOTAL; i++)
{
- mKey[i].configField = keyData[i].configField;
- mKey[i].defaultValue = keyData[i].defaultValue;
-// mKey[i].caption = gettext(keyData[i].caption.c_str());
- mKey[i].value = KEY_NO_VALUE;
- mKey[i].grp = keyData[i].grp;
- mKey[i].action = keyData[i].action;
- mKey[i].modKeyIndex = keyData[i].modKeyIndex;
- mKey[i].priority = keyData[i].priority;
- mKey[i].condition = keyData[i].condition;
- }
-/*
- for (int i = KEY_EMOTE_1; i <= KEY_EMOTE_48; i ++)
- {
- mKey[i].caption = strprintf(
- _("Emote Shortcut %d"), i - KEY_EMOTE_1 + 1);
- }
- for (int i = KEY_SHORTCUT_1; i <= KEY_SHORTCUT_20; i ++)
- {
- mKey[i].caption = strprintf(
- _("Item Shortcut %d"), i - KEY_SHORTCUT_1 + 1);
+ for (int f = 0; f < KeyFunctionSize; f ++)
+ {
+ mKey[i].values[f].type = INPUT_UNKNOWN;
+ mKey[i].values[f].value = -1;
+ }
}
-*/
mNewKeyIndex = KEY_NO_VALUE;
mEnabled = true;
+ makeDefault();
retrieve();
updateKeyActionMap();
}
@@ -90,12 +75,45 @@ void KeyboardConfig::retrieve()
{
for (int i = 0; i < KEY_TOTAL; i++)
{
- if (*mKey[i].configField)
+ if (*keyData[i].configField)
{
- mKey[i].value = static_cast<int>(config.getValue(
- mKey[i].configField, mKey[i].defaultValue));
- if (mKey[i].value < -255 || mKey[i].value >= SDLK_LAST)
- mKey[i].value = KEY_NO_VALUE;
+ KeyFunction &kf = mKey[i];
+ std::string keyStr = config.getValue(keyData[i].configField,
+ toString(keyData[i].defaultValue));
+ StringVect keys;
+ splitToStringVector(keys, keyStr, ',');
+ StringVectCIter it = keys.begin();
+ StringVectCIter it_end = keys.end();
+ int i2 = 0;
+ for (; it != it_end && i2 < KeyFunctionSize; ++ it)
+ {
+ std::string keyStr2 = *it;
+ if (keyStr.size() < 2)
+ continue;
+ int type = INPUT_KEYBOARD;
+ if ((keyStr2[0] < '0' || keyStr2[0] > '9')
+ && keyStr2[0] != '-')
+ {
+ switch (keyStr2[0])
+ {
+ case 'm':
+ type = INPUT_MOUSE;
+ break;
+ case 'j':
+ type = INPUT_JOYSTICK;
+ break;
+ default:
+ break;
+ }
+ keyStr2 = keyStr2.substr(1);
+ }
+ int key = atoi(keyStr2.c_str());
+ if (key >= -255 && key < SDLK_LAST)
+ {
+ kf.values[i2] = KeyItem(type, key);
+ i2 ++;
+ }
+ }
}
}
}
@@ -104,42 +122,102 @@ void KeyboardConfig::store()
{
for (int i = 0; i < KEY_TOTAL; i++)
{
- if (*mKey[i].configField)
- config.setValue(mKey[i].configField, mKey[i].value);
+ if (*keyData[i].configField)
+ {
+ std::string keyStr;
+
+ for (size_t i2 = 0; i2 < KeyFunctionSize; i2 ++)
+ {
+ const KeyItem &key = mKey[i].values[i2];
+ if (key.type != INPUT_UNKNOWN)
+ {
+ std::string tmp = "k";
+ switch(key.type)
+ {
+ case INPUT_MOUSE:
+ tmp = "m";
+ break;
+ case INPUT_JOYSTICK:
+ tmp = "j";
+ break;
+ default:
+ break;
+ }
+ if (key.value >= 0)
+ {
+ if (keyStr.empty())
+ {
+ keyStr = tmp + toString(key.value);
+ }
+ else
+ {
+ keyStr += strprintf(",%s%d", tmp.c_str(), key.value);
+ }
+ }
+ }
+ }
+ if (keyStr.empty())
+ keyStr = "-1";
+
+ config.setValue(keyData[i].configField, keyStr);
+ }
}
}
void KeyboardConfig::makeDefault()
{
for (int i = 0; i < KEY_TOTAL; i++)
- mKey[i].value = mKey[i].defaultValue;
+ {
+ for (size_t i2 = 1; i2 < KeyFunctionSize; i2 ++)
+ {
+ mKey[i].values[i2].type = INPUT_UNKNOWN;
+ mKey[i].values[i2].value = -1;
+ }
+ mKey[i].values[0].type = INPUT_KEYBOARD;
+ mKey[i].values[0].value = keyData[i].defaultValue;
+ }
}
bool KeyboardConfig::hasConflicts(int &key1, int &key2)
{
- int i, j;
+ size_t i;
+ size_t j;
/**
* No need to parse the square matrix: only check one triangle
* that's enough to detect conflicts
*/
for (i = 0; i < KEY_TOTAL; i++)
{
- if (mKey[i].value == KEY_NO_VALUE || !*mKey[i].configField)
+ if (!*keyData[i].configField)
continue;
- for (j = i, j++; j < KEY_TOTAL; j++)
+ for (size_t i2 = 0; i2 < KeyFunctionSize; i2 ++)
{
- // Allow for item shortcut and emote keys to overlap
- // as well as emote and ignore keys, but no other keys
- if (mKey[j].value != KEY_NO_VALUE &&
- mKey[i].value == mKey[j].value &&
- ((mKey[i].grp & mKey[j].grp) != 0 &&
- *mKey[i].configField)
- )
+ if (mKey[i].values[i2].value == KEY_NO_VALUE)
+ continue;
+
+ for (j = i, j++; j < KEY_TOTAL; j++)
{
- key1 = i;
- key2 = j;
- return true;
+
+ if ((keyData[i].grp & keyData[j].grp) == 0 ||
+ !*keyData[i].configField)
+ {
+ continue;
+ }
+
+ for (size_t j2 = 0; j2 < KeyFunctionSize; j2 ++)
+ {
+ // Allow for item shortcut and emote keys to overlap
+ // as well as emote and ignore keys, but no other keys
+ if (mKey[j].values[j2].type != INPUT_UNKNOWN
+ && mKey[i].values[i2].value == mKey[j].values[j2].value
+ && mKey[i].values[i2].type == mKey[j].values[j2].type)
+ {
+ key1 = i;
+ key2 = j;
+ return true;
+ }
+ }
}
}
}
@@ -163,12 +241,16 @@ int KeyboardConfig::getKeyValueFromEvent(const SDL_Event &event) const
int KeyboardConfig::getKeyIndex(const SDL_Event &event, int grp) const
{
const int keyValue = getKeyValueFromEvent(event);
- for (int i = 0; i < KEY_TOTAL; i++)
+ for (size_t i = 0; i < KEY_TOTAL; i++)
{
- if (keyValue == mKey[i].value &&
- (grp & mKey[i].grp) != 0)
+ for (size_t i2 = 0; i2 < KeyFunctionSize; i2 ++)
{
- return i;
+ if (keyValue == mKey[i].values[i2].value
+ && (grp & keyData[i].grp) != 0
+ && mKey[i].values[i2].type == INPUT_KEYBOARD)
+ {
+ return i;
+ }
}
}
return KEY_NO_VALUE;
@@ -178,11 +260,14 @@ bool KeyboardConfig::isActionActive(int index) const
{
if (!mActiveKeys)
return false;
- const int value = mKey[index].value;
- if (value >= 0)
- return mActiveKeys[value];
- else
- return false; // scan codes active state now not implimented
+
+ for (size_t i = 0; i < KeyFunctionSize; i ++)
+ {
+ const int value = mKey[index].values[i].value;
+ if (value >= 0 && mActiveKeys[value])
+ return true;
+ }
+ return false;
}
void KeyboardConfig::refreshActiveKeys()
@@ -192,32 +277,61 @@ void KeyboardConfig::refreshActiveKeys()
std::string KeyboardConfig::getKeyStringLong(int index) const
{
- const int keyValue = getKeyValue(index);
- if (keyValue >= 0)
- return SDL_GetKeyName(static_cast<SDLKey>(keyValue));
- else if (keyValue < -1)
- return strprintf(_("key_%d"), -keyValue);
- else
+ std::string keyStr;
+
+ for (size_t i = 0; i < KeyFunctionSize; i ++)
+ {
+ const KeyItem &key = mKey[index].values[i];
+ if (key.type == INPUT_KEYBOARD)
+ {
+ if (key.value >= 0)
+ {
+ if (keyStr.empty())
+ {
+ keyStr = SDL_GetKeyName(static_cast<SDLKey>(key.value));
+ }
+ else
+ {
+ keyStr += std::string(" ") + SDL_GetKeyName(
+ static_cast<SDLKey>(key.value));
+ }
+ }
+ }
+ }
+
+ if (keyStr.empty())
return _("unknown key");
+ return keyStr;
}
std::string KeyboardConfig::getKeyValueString(int index) const
{
- const int keyValue = getKeyValue(index);
- if (keyValue >= 0)
- {
- std::string key = SDL_GetKeyName(static_cast<SDLKey>(keyValue));
- return getKeyShortString(key);
- }
- else if (keyValue < -1)
+ std::string keyStr;
+
+ for (size_t i = 0; i < KeyFunctionSize; i ++)
{
- return strprintf("#%d", -keyValue);
+ const KeyItem &key = mKey[index].values[i];
+ if (key.type == INPUT_KEYBOARD)
+ {
+ if (key.value >= 0)
+ {
+ if (keyStr.empty())
+ {
+ keyStr = getKeyShortString(SDL_GetKeyName(
+ static_cast<SDLKey>(key.value)));
+ }
+ else
+ {
+ keyStr += " " + getKeyShortString(SDL_GetKeyName(
+ static_cast<SDLKey>(key.value)));
+ }
+ }
+ }
}
- else
- {
- // TRANSLATORS: Unknown key short string. This string must be maximum 5 chars
+
+ if (keyStr.empty())
return _("u key");
- }
+ return keyStr;
}
std::string KeyboardConfig::getKeyShortString(const std::string &key) const
@@ -241,13 +355,42 @@ SDLKey KeyboardConfig::getKeyFromEvent(const SDL_Event &event) const
void KeyboardConfig::setNewKey(const SDL_Event &event)
{
- mKey[mNewKeyIndex].value = getKeyValueFromEvent(event);
+ int idx = -1;
+ KeyFunction &key = mKey[mNewKeyIndex];
+ int val = getKeyValueFromEvent(event);
+
+ for (size_t i = 0; i < KeyFunctionSize; i ++)
+ {
+ if (key.values[i].type == INPUT_UNKNOWN
+ || (key.values[i].type == INPUT_KEYBOARD
+ && key.values[i].value == val))
+ {
+ idx = i;
+ break;
+ }
+ }
+ if (idx == -1)
+ {
+ for (size_t i = 1; i < KeyFunctionSize; i ++)
+ {
+ key.values[i - 1].type = key.values[i].type;
+ key.values[i - 1].value = key.values[i].value;
+ }
+ idx = KeyFunctionSize - 1;
+ }
+
+ key.values[idx] = KeyItem(INPUT_KEYBOARD, val);
updateKeyActionMap();
}
void KeyboardConfig::unassignKey()
{
- mKey[mNewKeyIndex].value = KEY_NO_VALUE;
+ KeyFunction &key = mKey[mNewKeyIndex];
+ for (size_t i = 0; i < KeyFunctionSize; i ++)
+ {
+ key.values[i].type = INPUT_UNKNOWN;
+ key.values[i].value = -1;
+ }
updateKeyActionMap();
}
@@ -255,13 +398,19 @@ void KeyboardConfig::updateKeyActionMap()
{
mKeyToAction.clear();
- for (int i = 0; i < KEY_TOTAL; i++)
+ for (size_t i = 0; i < KEY_TOTAL; i++)
{
- if (mKey[i].value != KEY_NO_VALUE && mKey[i].action)
- mKeyToAction[mKey[i].value].push_back(i);
+ if (keyData[i].action)
+ {
+ for (size_t i2 = 0; i2 < KeyFunctionSize; i2 ++)
+ {
+ if (mKey[i].values[i2].type == INPUT_KEYBOARD)
+ mKeyToAction[mKey[i].values[i2].value].push_back(i);
+ }
+ }
}
- keySorter.keys = &mKey[0];
+ keySorter.keys = &keyData[0];
KeyToActionMapIter it = mKeyToAction.begin();
KeyToActionMapIter it_end = mKeyToAction.end();
for (; it != it_end; ++ it)
@@ -291,10 +440,10 @@ bool KeyboardConfig::triggerAction(const SDL_Event &event)
if (keyNum < 0 || keyNum >= KEY_TOTAL)
continue;
- if (inputManager.checkKey(&mKey[keyNum], mask))
+ if (inputManager.checkKey(&keyData[keyNum], mask))
{
InputEvent evt(keyNum, mask);
- if ((*(mKey[keyNum].action))(evt))
+ if ((*(keyData[keyNum].action))(evt))
{
return true;
}
@@ -303,3 +452,8 @@ bool KeyboardConfig::triggerAction(const SDL_Event &event)
}
return false;
}
+
+int KeyboardConfig::getKeyValue(int index) const
+{
+ return mKey[index].values[0].value;
+}
diff --git a/src/keyboardconfig.h b/src/keyboardconfig.h
index 3299dcf51..5ebbe075e 100644
--- a/src/keyboardconfig.h
+++ b/src/keyboardconfig.h
@@ -41,19 +41,35 @@ typedef KeysVector::const_iterator KeysVectorCIter;
typedef std::map<int, KeysVector> KeyToActionMap;
typedef KeyToActionMap::iterator KeyToActionMapIter;
+enum KeyTypes
+{
+ INPUT_UNKNOWN = 0,
+ INPUT_KEYBOARD = 1,
+ INPUT_MOUSE = 2,
+ INPUT_JOYSTICK = 3
+};
+
+struct KeyItem
+{
+ KeyItem() : type(-1), value(-1)
+ { }
+
+ KeyItem(int type0, int value0) : type(type0), value(value0)
+ { }
+
+ int type;
+
+ int value;
+};
+
+#define KeyFunctionSize 3
+
/**
* Each key represents a key function. Such as 'Move up', 'Attack' etc.
*/
struct KeyFunction
{
- const char* configField; /** Field index that is in the config file. */
- int defaultValue; /** The default key value used. */
- int value; /** The actual value that is used. */
- int grp; /** The key group */
- ActionFuncPtr action; /** The key action function */
- int modKeyIndex; /** Modifier what enable this key action */
- int priority; /** Action priority */
- int condition; /** Condition for allow use key */
+ KeyItem values[KeyFunctionSize];
};
class Setup_Keyboard;
@@ -94,11 +110,7 @@ class KeyboardConfig
/**
* Obtain the value stored in memory.
*/
- int getKeyValue(int index) const
- { return mKey[index].value; }
-
- bool isSeparator(int index) const
- { return !*mKey[index].configField; }
+ int getKeyValue(int index) const;
/**
* Get the index of the new key to be assigned.
diff --git a/src/keyboarddata.h b/src/keyboarddata.h
index b6ae17815..7ade46d6e 100644
--- a/src/keyboarddata.h
+++ b/src/keyboarddata.h
@@ -26,6 +26,7 @@
#include "actionmanager.h"
#include "inputmanager.h"
#include "keyboardconfig.h"
+#include "keydata.h"
#include "localconsts.h"
#include "utils/gettext.h"
@@ -33,17 +34,6 @@
#include <string>
-struct KeyData
-{
- const char *configField;
- int defaultValue;
- int grp;
- ActionFuncPtr action;
- int modKeyIndex;
- int priority;
- int condition;
-};
-
// keyData must be in same order as enum keyAction.
static KeyData const keyData[KeyboardConfig::KEY_TOTAL] = {
{"keyMoveUp", SDLK_UP,
diff --git a/src/keydata.h b/src/keydata.h
new file mode 100644
index 000000000..841e0adaa
--- /dev/null
+++ b/src/keydata.h
@@ -0,0 +1,40 @@
+/*
+ * Custom keyboard shortcuts configuration
+ * Copyright (C) 2007 Joshua Langley <joshlangley@optusnet.com.au>
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2012 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef KEYDATA_H
+#define KEYDATA_H
+
+#include "actionmanager.h"
+
+#include <string>
+
+struct KeyData
+{
+ const char *configField;
+ int defaultValue;
+ int grp;
+ ActionFuncPtr action;
+ int modKeyIndex;
+ int priority;
+ int condition;
+};
+#endif