3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #include "exceptions.h"
26 #include "util/string.h"
27 #include "util/basic_macros.h"
29 class UnknownKeycode : public BaseException
32 UnknownKeycode(const char *s) :
39 wchar_t Char; // L'\0' means no character assigned
40 const char *LangName; // NULL means it doesn't have a human description
43 #define DEFINEKEY1(x, lang) /* Irrlicht key without character */ \
44 { #x, irr::x, L'\0', lang },
45 #define DEFINEKEY2(x, ch, lang) /* Irrlicht key with character */ \
46 { #x, irr::x, ch, lang },
47 #define DEFINEKEY3(ch) /* single Irrlicht key (e.g. KEY_KEY_X) */ \
48 { "KEY_KEY_" TOSTRING(ch), irr::KEY_KEY_ ## ch, (wchar_t) *TOSTRING(ch), TOSTRING(ch) },
49 #define DEFINEKEY4(ch) /* single Irrlicht function key (e.g. KEY_F3) */ \
50 { "KEY_F" TOSTRING(ch), irr::KEY_F ## ch, L'\0', "F" TOSTRING(ch) },
51 #define DEFINEKEY5(ch) /* key without Irrlicht keycode */ \
52 { ch, irr::KEY_KEY_CODES_COUNT, (wchar_t) *ch, ch },
56 static const struct table_key table[] = {
57 // Keys that can be reliably mapped between Char and Key
94 DEFINEKEY2(KEY_PLUS, L'+', "+")
95 DEFINEKEY2(KEY_COMMA, L',', ",")
96 DEFINEKEY2(KEY_MINUS, L'-', "-")
97 DEFINEKEY2(KEY_PERIOD, L'.', ".")
99 // Keys without a Char
100 DEFINEKEY1(KEY_LBUTTON, N_("Left Button"))
101 DEFINEKEY1(KEY_RBUTTON, N_("Right Button"))
102 DEFINEKEY1(KEY_CANCEL, N_("Cancel"))
103 DEFINEKEY1(KEY_MBUTTON, N_("Middle Button"))
104 DEFINEKEY1(KEY_XBUTTON1, N_("X Button 1"))
105 DEFINEKEY1(KEY_XBUTTON2, N_("X Button 2"))
106 DEFINEKEY1(KEY_BACK, N_("Back"))
107 DEFINEKEY1(KEY_TAB, N_("Tab"))
108 DEFINEKEY1(KEY_CLEAR, N_("Clear"))
109 DEFINEKEY1(KEY_RETURN, N_("Return"))
110 DEFINEKEY1(KEY_SHIFT, N_("Shift"))
111 DEFINEKEY1(KEY_CONTROL, N_("Control"))
112 DEFINEKEY1(KEY_MENU, N_("Menu"))
113 DEFINEKEY1(KEY_PAUSE, N_("Pause"))
114 DEFINEKEY1(KEY_CAPITAL, N_("Caps Lock"))
115 DEFINEKEY1(KEY_SPACE, N_("Space"))
116 DEFINEKEY1(KEY_PRIOR, N_("Prior"))
117 DEFINEKEY1(KEY_NEXT, N_("Next"))
118 DEFINEKEY1(KEY_END, N_("End"))
119 DEFINEKEY1(KEY_HOME, N_("Home"))
120 DEFINEKEY1(KEY_LEFT, N_("Left"))
121 DEFINEKEY1(KEY_UP, N_("Up"))
122 DEFINEKEY1(KEY_RIGHT, N_("Right"))
123 DEFINEKEY1(KEY_DOWN, N_("Down"))
124 DEFINEKEY1(KEY_SELECT, N_("Select"))
125 DEFINEKEY1(KEY_PRINT, N_("Print"))
126 DEFINEKEY1(KEY_EXECUT, N_("Execute"))
127 DEFINEKEY1(KEY_SNAPSHOT, N_("Snapshot"))
128 DEFINEKEY1(KEY_INSERT, N_("Insert"))
129 DEFINEKEY1(KEY_DELETE, N_("Delete"))
130 DEFINEKEY1(KEY_HELP, N_("Help"))
131 DEFINEKEY1(KEY_LWIN, N_("Left Windows"))
132 DEFINEKEY1(KEY_RWIN, N_("Right Windows"))
133 DEFINEKEY1(KEY_NUMPAD0, N_("Numpad 0")) // These are not assigned to a char
134 DEFINEKEY1(KEY_NUMPAD1, N_("Numpad 1")) // to prevent interference with KEY_KEY_[0-9].
135 DEFINEKEY1(KEY_NUMPAD2, N_("Numpad 2"))
136 DEFINEKEY1(KEY_NUMPAD3, N_("Numpad 3"))
137 DEFINEKEY1(KEY_NUMPAD4, N_("Numpad 4"))
138 DEFINEKEY1(KEY_NUMPAD5, N_("Numpad 5"))
139 DEFINEKEY1(KEY_NUMPAD6, N_("Numpad 6"))
140 DEFINEKEY1(KEY_NUMPAD7, N_("Numpad 7"))
141 DEFINEKEY1(KEY_NUMPAD8, N_("Numpad 8"))
142 DEFINEKEY1(KEY_NUMPAD9, N_("Numpad 9"))
143 DEFINEKEY1(KEY_MULTIPLY, N_("Numpad *"))
144 DEFINEKEY1(KEY_ADD, N_("Numpad +"))
145 DEFINEKEY1(KEY_SEPARATOR, N_("Numpad ."))
146 DEFINEKEY1(KEY_SUBTRACT, N_("Numpad -"))
147 DEFINEKEY1(KEY_DECIMAL, NULL)
148 DEFINEKEY1(KEY_DIVIDE, N_("Numpad /"))
173 DEFINEKEY1(KEY_NUMLOCK, N_("Num Lock"))
174 DEFINEKEY1(KEY_SCROLL, N_("Scroll Lock"))
175 DEFINEKEY1(KEY_LSHIFT, N_("Left Shift"))
176 DEFINEKEY1(KEY_RSHIFT, N_("Right Shift"))
177 DEFINEKEY1(KEY_LCONTROL, N_("Left Control"))
178 DEFINEKEY1(KEY_RCONTROL, N_("Right Control"))
179 DEFINEKEY1(KEY_LMENU, N_("Left Menu"))
180 DEFINEKEY1(KEY_RMENU, N_("Right Menu"))
183 DEFINEKEY1(KEY_KANA, "Kana")
184 DEFINEKEY1(KEY_HANGUEL, "Hangul")
185 DEFINEKEY1(KEY_HANGUL, "Hangul")
186 DEFINEKEY1(KEY_JUNJA, "Junja")
187 DEFINEKEY1(KEY_FINAL, "Final")
188 DEFINEKEY1(KEY_KANJI, "Kanji")
189 DEFINEKEY1(KEY_HANJA, "Hanja")
190 DEFINEKEY1(KEY_ESCAPE, N_("IME Escape"))
191 DEFINEKEY1(KEY_CONVERT, N_("IME Convert"))
192 DEFINEKEY1(KEY_NONCONVERT, N_("IME Nonconvert"))
193 DEFINEKEY1(KEY_ACCEPT, N_("IME Accept"))
194 DEFINEKEY1(KEY_MODECHANGE, N_("IME Mode Change"))
195 DEFINEKEY1(KEY_APPS, N_("Apps"))
196 DEFINEKEY1(KEY_SLEEP, N_("Sleep"))
197 #if !(IRRLICHT_VERSION_MAJOR <= 1 && IRRLICHT_VERSION_MINOR <= 7 && IRRLICHT_VERSION_REVISION < 3)
198 DEFINEKEY1(KEY_OEM_1, "OEM 1") // KEY_OEM_[0-9] and KEY_OEM_102 are assigned to multiple
199 DEFINEKEY1(KEY_OEM_2, "OEM 2") // different chars (on different platforms too) and thus w/o char
200 DEFINEKEY1(KEY_OEM_3, "OEM 3")
201 DEFINEKEY1(KEY_OEM_4, "OEM 4")
202 DEFINEKEY1(KEY_OEM_5, "OEM 5")
203 DEFINEKEY1(KEY_OEM_6, "OEM 6")
204 DEFINEKEY1(KEY_OEM_7, "OEM 7")
205 DEFINEKEY1(KEY_OEM_8, "OEM 8")
206 DEFINEKEY1(KEY_OEM_AX, "OEM AX")
207 DEFINEKEY1(KEY_OEM_102, "OEM 102")
209 DEFINEKEY1(KEY_ATTN, "Attn")
210 DEFINEKEY1(KEY_CRSEL, "CrSel")
211 DEFINEKEY1(KEY_EXSEL, "ExSel")
212 DEFINEKEY1(KEY_EREOF, N_("Erase EOF"))
213 DEFINEKEY1(KEY_PLAY, N_("Play"))
214 DEFINEKEY1(KEY_ZOOM, N_("Zoom"))
215 DEFINEKEY1(KEY_PA1, "PA1")
216 DEFINEKEY1(KEY_OEM_CLEAR, N_("OEM Clear"))
218 // Keys without Irrlicht keycode
247 struct table_key lookup_keyname(const char *name)
249 for (u16 i = 0; i < ARRLEN(table); i++) {
250 if (strcmp(table[i].Name, name) == 0)
254 throw UnknownKeycode(name);
257 struct table_key lookup_keykey(irr::EKEY_CODE key)
259 for (u16 i = 0; i < ARRLEN(table); i++) {
260 if (table[i].Key == key)
264 std::ostringstream os;
265 os << "<Keycode " << (int) key << ">";
266 throw UnknownKeycode(os.str().c_str());
269 struct table_key lookup_keychar(wchar_t Char)
271 for (u16 i = 0; i < ARRLEN(table); i++) {
272 if (table[i].Char == Char)
276 std::ostringstream os;
277 os << "<Char " << hex_encode((char*) &Char, sizeof(wchar_t)) << ">";
278 throw UnknownKeycode(os.str().c_str());
281 KeyPress::KeyPress(const char *name)
283 if (strlen(name) == 0) {
284 Key = irr::KEY_KEY_CODES_COUNT;
288 } else if (strlen(name) <= 4) {
289 // Lookup by resulting character
290 int chars_read = mbtowc(&Char, name, 1);
291 FATAL_ERROR_IF(chars_read != 1, "Unexpected multibyte character");
293 struct table_key k = lookup_keychar(Char);
297 } catch (UnknownKeycode &e) {};
302 struct table_key k = lookup_keyname(name);
306 } catch (UnknownKeycode &e) {};
309 // It's not a known key, complain and try to do something
310 Key = irr::KEY_KEY_CODES_COUNT;
311 int chars_read = mbtowc(&Char, name, 1);
312 FATAL_ERROR_IF(chars_read != 1, "Unexpected multibyte character");
314 warningstream << "KeyPress: Unknown key '" << name << "', falling back to first char.";
317 KeyPress::KeyPress(const irr::SEvent::SKeyInput &in, bool prefer_character)
319 if (prefer_character)
320 Key = irr::KEY_KEY_CODES_COUNT;
326 if (valid_kcode(Key))
327 m_name = lookup_keykey(Key).Name;
329 m_name = lookup_keychar(Char).Name;
330 } catch (UnknownKeycode &e) {
335 const char *KeyPress::sym() const
337 return m_name.c_str();
340 const char *KeyPress::name() const
345 if (valid_kcode(Key))
346 ret = lookup_keykey(Key).LangName;
348 ret = lookup_keychar(Char).LangName;
349 return ret ? ret : "<Unnamed key>";
352 const KeyPress EscapeKey("KEY_ESCAPE");
353 const KeyPress CancelKey("KEY_CANCEL");
359 // A simple cache for quicker lookup
360 std::map<std::string, KeyPress> g_key_setting_cache;
362 KeyPress getKeySetting(const char *settingname)
364 std::map<std::string, KeyPress>::iterator n;
365 n = g_key_setting_cache.find(settingname);
366 if(n != g_key_setting_cache.end())
369 KeyPress k(g_settings->get(settingname).c_str());
370 g_key_setting_cache[settingname] = k;
376 g_key_setting_cache.clear();
379 irr::EKEY_CODE keyname_to_keycode(const char *name)
381 return lookup_keyname(name).Key;