1
/*
2
 *  Custom keyboard shortcuts configuration
3
 *  Copyright (C) 2007  Joshua Langley <joshlangley@optusnet.com.au>
4
 *
5
 *  This file is part of The Mana World.
6
 *
7
 *  This program is free software; you can redistribute it and/or modify
8
 *  it under the terms of the GNU General Public License as published by
9
 *  the Free Software Foundation; either version 2 of the License, or
10
 *  any later version.
11
 *
12
 *  This program is distributed in the hope that it will be useful,
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 *  GNU General Public License for more details.
16
 *
17
 *  You should have received a copy of the GNU General Public License
18
 *  along with this program; if not, write to the Free Software
19
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
 */
21
22
#include "configuration.h"
23
#include "keyboardconfig.h"
24
#include "log.h"
25
26
#include "gui/sdlinput.h"
27
#include "gui/setup_keyboard.h"
28
29
#include "utils/gettext.h"
30
#include "utils/stringutils.h"
31
32
struct KeyData
33
{
34
    const char *configField;
35
    int defaultValue;
36
    std::string caption;
37
};
38
39
// keyData must be in same order as enum keyAction.
40
static KeyData const keyData[KeyboardConfig::KEY_TOTAL] = {
41
    {"keyMoveUp", SDLK_UP, _("Move Up")},
42
    {"keyMoveDown", SDLK_DOWN, _("Move Down")},
43
    {"keyMoveLeft", SDLK_LEFT, _("Move Left")},
44
    {"keyMoveRight", SDLK_RIGHT, _("Move Right")},
45
    {"keyAttack", SDLK_LCTRL, _("Attack")},
46
    {"keyTargetAttack", SDLK_x, _("Target & Attack")},
47
    {"keySmilie", SDLK_LALT, _("Smilie")},
48
    {"keyTalk", SDLK_t, _("Talk")},
49
    {"keyTarget", SDLK_LSHIFT, _("Stop Attack")},
50
    {"keyTargetClosest", SDLK_a, _("Target Closest")},
51
    {"keyTargetNPC", SDLK_n, _("Target NPC")},
52
    {"keyTargetPlayer", SDLK_q, _("Target Player")},
53
    {"keyPickup", SDLK_z, _("Pickup")},
54
    {"keyHideWindows", SDLK_h, _("Hide Windows")},
55
    {"keyBeingSit", SDLK_s, _("Sit")},
56
    {"keyScreenshot", SDLK_p, _("Screenshot")},
57
    {"keyTrade", SDLK_r, _("Enable/Disable Trading")},
58
    {"keyPathfind", SDLK_f, _("Find Path to Mouse")},
59
    {"keyShortcut1", SDLK_1, strprintf(_("Item Shortcut %d"), 1)},
60
    {"keyShortcut2", SDLK_2, strprintf(_("Item Shortcut %d"), 2)},
61
    {"keyShortcut3", SDLK_3, strprintf(_("Item Shortcut %d"), 3)},
62
    {"keyShortcut4", SDLK_4, strprintf(_("Item Shortcut %d"), 4)},
63
    {"keyShortcut5", SDLK_5, strprintf(_("Item Shortcut %d"), 5)},
64
    {"keyShortcut6", SDLK_6, strprintf(_("Item Shortcut %d"), 6)},
65
    {"keyShortcut7", SDLK_7, strprintf(_("Item Shortcut %d"), 7)},
66
    {"keyShortcut8", SDLK_8, strprintf(_("Item Shortcut %d"), 8)},
67
    {"keyShortcut9", SDLK_9, strprintf(_("Item Shortcut %d"), 9)},
68
    {"keyShortcut10", SDLK_0, strprintf(_("Item Shortcut %d"), 10)},
69
    {"keyShortcut11", SDLK_MINUS, strprintf(_("Item Shortcut %d"), 11)},
70
    {"keyShortcut12", SDLK_EQUALS, strprintf(_("Item Shortcut %d"), 12)},
71
    {"keyWindowHelp", SDLK_F1, _("Help Window")},
72
    {"keyWindowStatus", SDLK_F2, _("Status Window")},
73
    {"keyWindowInventory", SDLK_F3, _("Inventory Window")},
74
    {"keyWindowEquipment", SDLK_F4, _("Equipment Window")},
75
    {"keyWindowSkill", SDLK_F5, _("Skill Window")},
76
    {"keyWindowMinimap", SDLK_F6, _("Minimap Window")},
77
    {"keyWindowChat", SDLK_F7, _("Chat Window")},
78
    {"keyWindowShortcut", SDLK_F8, _("Item Shortcut Window")},
79
    {"keyWindowSetup", SDLK_F9, _("Setup Window")},
80
    {"keyWindowDebug", SDLK_F10, _("Debug Window")},
81
    {"keyWindowParty", SDLK_F11, _("Party Window")},
82
    {"keyWindowEmoteBar", SDLK_F12, _("Emote Shortcut Window")},
83
    {"keyWindowOutfit", SDLK_o, _("Outfits Window")},
84
    {"keyEmoteShortcut1", SDLK_1, strprintf(_("Emote Shortcut %d"), 1)},
85
    {"keyEmoteShortcut2", SDLK_2, strprintf(_("Emote Shortcut %d"), 2)},
86
    {"keyEmoteShortcut3", SDLK_3, strprintf(_("Emote Shortcut %d"), 3)},
87
    {"keyEmoteShortcut4", SDLK_4, strprintf(_("Emote Shortcut %d"), 4)},
88
    {"keyEmoteShortcut5", SDLK_5, strprintf(_("Emote Shortcut %d"), 5)},
89
    {"keyEmoteShortcut6", SDLK_6, strprintf(_("Emote Shortcut %d"), 6)},
90
    {"keyEmoteShortcut7", SDLK_7, strprintf(_("Emote Shortcut %d"), 7)},
91
    {"keyEmoteShortcut8", SDLK_8, strprintf(_("Emote Shortcut %d"), 8)},
92
    {"keyEmoteShortcut9", SDLK_9, strprintf(_("Emote Shortcut %d"), 9)},
93
    {"keyEmoteShortcut10", SDLK_0, strprintf(_("Emote Shortcut %d"), 10)},
94
    {"keyEmoteShortcut11", SDLK_MINUS, strprintf(_("Emote Shortcut %d"), 11)},
95
    {"keyEmoteShortcut12", SDLK_EQUALS, strprintf(_("Emote Shortcut %d"), 12)},
96
    {"keyChat", SDLK_RETURN, _("Toggle Chat")},
97
    {"keyChatScrollUp", SDLK_PAGEUP, _("Scroll Chat Up")},
98
    {"keyChatScrollDown", SDLK_PAGEDOWN, _("Scroll Chat Down")},
99
    {"keyChatPrevTab", SDLK_LEFTBRACKET, _("Previous Chat Tab")},
100
    {"keyChatNextTab", SDLK_RIGHTBRACKET, _("Next Chat Tab")},
101
    {"keyOK", SDLK_SPACE, _("Select OK")},
102
    {"keyQuit", SDLK_ESCAPE, _("Quit")},
103
    {"keyIgnoreInput1", SDLK_LSUPER, _("Ignore input 1")},
104
    {"keyIgnoreInput2", SDLK_RSUPER, _("Ignore input 2")}
105
};
106
107
void KeyboardConfig::init()
108
{
109
    for (int i = 0; i < KEY_TOTAL; i++)
110
    {
111
        mKey[i].configField = keyData[i].configField;
112
        mKey[i].defaultValue = keyData[i].defaultValue;
113
        mKey[i].caption = keyData[i].caption;
114
        mKey[i].value = KEY_NO_VALUE;
115
    }
116
    mNewKeyIndex = KEY_NO_VALUE;
117
    mEnabled = true;
118
119
    retrieve();
120
}
121
122
void KeyboardConfig::retrieve()
123
{
124
    for (int i = 0; i < KEY_TOTAL; i++)
125
    {
126
        mKey[i].value = (int) config.getValue(
127
            mKey[i].configField, mKey[i].defaultValue);
128
    }
129
}
130
131
void KeyboardConfig::store()
132
{
133
    for (int i = 0; i < KEY_TOTAL; i++)
134
    {
135
        config.setValue(mKey[i].configField, mKey[i].value);
136
    }
137
}
138
139
void KeyboardConfig::makeDefault()
140
{
141
    for (int i = 0; i < KEY_TOTAL; i++)
142
    {
143
        mKey[i].value = mKey[i].defaultValue;
144
    }
145
}
146
147
bool KeyboardConfig::hasConflicts()
148
{
149
    int i, j;
150
    /**
151
     * No need to parse the square matrix: only check one triangle
152
     * that's enough to detect conflicts
153
     */
154
    for (i = 0; i < KEY_TOTAL; i++)
155
    {
156
        for (j = i, j++; j < KEY_TOTAL; j++)
157
        {
158
            // Allow for item shortcut and emote keys to overlap
159
            // as well as emote and ignore keys, but no other keys
160
            if (!((((i >= KEY_SHORTCUT_1) && (i <= KEY_SHORTCUT_12)) &&
161
                   ((j >= KEY_EMOTE_1) && (j <= KEY_EMOTE_12))) ||
162
                   ((i == KEY_TOGGLE_CHAT) && (j == KEY_OK)) ||
163
                   ((i == KEY_EMOTE) &&
164
                    (j == KEY_IGNORE_INPUT_1 || j == KEY_IGNORE_INPUT_2))) &&
165
                   (mKey[i].value == mKey[j].value)
166
               )
167
            {
168
                return true;
169
            }
170
        }
171
    }
172
    return false;
173
}
174
175
void KeyboardConfig::callbackNewKey()
176
{
177
    mSetupKey->newKeyCallback(mNewKeyIndex);
178
}
179
180
int KeyboardConfig::getKeyIndex(int keyValue) const
181
{
182
    for (int i = 0; i < KEY_TOTAL; i++)
183
    {
184
        if (keyValue == mKey[i].value)
185
        {
186
            return i;
187
        }
188
    }
189
    return KEY_NO_VALUE;
190
}
191
192
193
int KeyboardConfig::getKeyEmoteOffset(int keyValue) const
194
{
195
    for (int i = KEY_EMOTE_1; i <= KEY_EMOTE_12; i++)
196
    {
197
        if (keyValue == mKey[i].value)
198
        {
199
            return 1 + i - KEY_EMOTE_1;
200
        }
201
    }
202
    return 0;
203
}
204
205
bool KeyboardConfig::isKeyActive(int index) const
206
{
207
    if (!mActiveKeys)
208
        return false;
209
    return mActiveKeys[mKey[index].value];
210
}
211
212
void KeyboardConfig::refreshActiveKeys()
213
{
214
    mActiveKeys = SDL_GetKeyState(NULL);
215
}