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_("Backspace"))
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 //~ Key name, common on Windows keyboards
113 DEFINEKEY1(KEY_MENU
, N_("Menu"))
114 DEFINEKEY1(KEY_PAUSE
, N_("Pause"))
115 DEFINEKEY1(KEY_CAPITAL
, N_("Caps Lock"))
116 DEFINEKEY1(KEY_SPACE
, N_("Space"))
117 DEFINEKEY1(KEY_PRIOR
, N_("Page up"))
118 DEFINEKEY1(KEY_NEXT
, N_("Page down"))
119 DEFINEKEY1(KEY_END
, N_("End"))
120 DEFINEKEY1(KEY_HOME
, N_("Home"))
121 DEFINEKEY1(KEY_LEFT
, N_("Left"))
122 DEFINEKEY1(KEY_UP
, N_("Up"))
123 DEFINEKEY1(KEY_RIGHT
, N_("Right"))
124 DEFINEKEY1(KEY_DOWN
, N_("Down"))
126 DEFINEKEY1(KEY_SELECT
, N_("Select"))
127 //~ "Print screen" key
128 DEFINEKEY1(KEY_PRINT
, N_("Print"))
129 DEFINEKEY1(KEY_EXECUT
, N_("Execute"))
130 DEFINEKEY1(KEY_SNAPSHOT
, N_("Snapshot"))
131 DEFINEKEY1(KEY_INSERT
, N_("Insert"))
132 DEFINEKEY1(KEY_DELETE
, N_("Delete"))
133 DEFINEKEY1(KEY_HELP
, N_("Help"))
134 DEFINEKEY1(KEY_LWIN
, N_("Left Windows"))
135 DEFINEKEY1(KEY_RWIN
, N_("Right Windows"))
136 DEFINEKEY1(KEY_NUMPAD0
, N_("Numpad 0")) // These are not assigned to a char
137 DEFINEKEY1(KEY_NUMPAD1
, N_("Numpad 1")) // to prevent interference with KEY_KEY_[0-9].
138 DEFINEKEY1(KEY_NUMPAD2
, N_("Numpad 2"))
139 DEFINEKEY1(KEY_NUMPAD3
, N_("Numpad 3"))
140 DEFINEKEY1(KEY_NUMPAD4
, N_("Numpad 4"))
141 DEFINEKEY1(KEY_NUMPAD5
, N_("Numpad 5"))
142 DEFINEKEY1(KEY_NUMPAD6
, N_("Numpad 6"))
143 DEFINEKEY1(KEY_NUMPAD7
, N_("Numpad 7"))
144 DEFINEKEY1(KEY_NUMPAD8
, N_("Numpad 8"))
145 DEFINEKEY1(KEY_NUMPAD9
, N_("Numpad 9"))
146 DEFINEKEY1(KEY_MULTIPLY
, N_("Numpad *"))
147 DEFINEKEY1(KEY_ADD
, N_("Numpad +"))
148 DEFINEKEY1(KEY_SEPARATOR
, N_("Numpad ."))
149 DEFINEKEY1(KEY_SUBTRACT
, N_("Numpad -"))
150 DEFINEKEY1(KEY_DECIMAL
, NULL
)
151 DEFINEKEY1(KEY_DIVIDE
, N_("Numpad /"))
176 DEFINEKEY1(KEY_NUMLOCK
, N_("Num Lock"))
177 DEFINEKEY1(KEY_SCROLL
, N_("Scroll Lock"))
178 DEFINEKEY1(KEY_LSHIFT
, N_("Left Shift"))
179 DEFINEKEY1(KEY_RSHIFT
, N_("Right Shift"))
180 DEFINEKEY1(KEY_LCONTROL
, N_("Left Control"))
181 DEFINEKEY1(KEY_RCONTROL
, N_("Right Control"))
182 DEFINEKEY1(KEY_LMENU
, N_("Left Menu"))
183 DEFINEKEY1(KEY_RMENU
, N_("Right Menu"))
186 DEFINEKEY1(KEY_KANA
, "Kana")
187 DEFINEKEY1(KEY_HANGUEL
, "Hangul")
188 DEFINEKEY1(KEY_HANGUL
, "Hangul")
189 DEFINEKEY1(KEY_JUNJA
, "Junja")
190 DEFINEKEY1(KEY_FINAL
, "Final")
191 DEFINEKEY1(KEY_KANJI
, "Kanji")
192 DEFINEKEY1(KEY_HANJA
, "Hanja")
193 DEFINEKEY1(KEY_ESCAPE
, N_("IME Escape"))
194 DEFINEKEY1(KEY_CONVERT
, N_("IME Convert"))
195 DEFINEKEY1(KEY_NONCONVERT
, N_("IME Nonconvert"))
196 DEFINEKEY1(KEY_ACCEPT
, N_("IME Accept"))
197 DEFINEKEY1(KEY_MODECHANGE
, N_("IME Mode Change"))
198 DEFINEKEY1(KEY_APPS
, N_("Apps"))
199 DEFINEKEY1(KEY_SLEEP
, N_("Sleep"))
200 #if !(IRRLICHT_VERSION_MAJOR <= 1 && IRRLICHT_VERSION_MINOR <= 7 && IRRLICHT_VERSION_REVISION < 3)
201 DEFINEKEY1(KEY_OEM_1
, "OEM 1") // KEY_OEM_[0-9] and KEY_OEM_102 are assigned to multiple
202 DEFINEKEY1(KEY_OEM_2
, "OEM 2") // different chars (on different platforms too) and thus w/o char
203 DEFINEKEY1(KEY_OEM_3
, "OEM 3")
204 DEFINEKEY1(KEY_OEM_4
, "OEM 4")
205 DEFINEKEY1(KEY_OEM_5
, "OEM 5")
206 DEFINEKEY1(KEY_OEM_6
, "OEM 6")
207 DEFINEKEY1(KEY_OEM_7
, "OEM 7")
208 DEFINEKEY1(KEY_OEM_8
, "OEM 8")
209 DEFINEKEY1(KEY_OEM_AX
, "OEM AX")
210 DEFINEKEY1(KEY_OEM_102
, "OEM 102")
212 DEFINEKEY1(KEY_ATTN
, "Attn")
213 DEFINEKEY1(KEY_CRSEL
, "CrSel")
214 DEFINEKEY1(KEY_EXSEL
, "ExSel")
215 DEFINEKEY1(KEY_EREOF
, N_("Erase EOF"))
216 DEFINEKEY1(KEY_PLAY
, N_("Play"))
217 DEFINEKEY1(KEY_ZOOM
, N_("Zoom"))
218 DEFINEKEY1(KEY_PA1
, "PA1")
219 DEFINEKEY1(KEY_OEM_CLEAR
, N_("OEM Clear"))
221 // Keys without Irrlicht keycode
250 struct table_key
lookup_keyname(const char *name
)
252 for (const auto &table_key
: table
) {
253 if (strcmp(table_key
.Name
, name
) == 0)
257 throw UnknownKeycode(name
);
260 struct table_key
lookup_keykey(irr::EKEY_CODE key
)
262 for (const auto &table_key
: table
) {
263 if (table_key
.Key
== key
)
267 std::ostringstream os
;
268 os
<< "<Keycode " << (int) key
<< ">";
269 throw UnknownKeycode(os
.str().c_str());
272 struct table_key
lookup_keychar(wchar_t Char
)
274 for (const auto &table_key
: table
) {
275 if (table_key
.Char
== Char
)
279 std::ostringstream os
;
280 os
<< "<Char " << hex_encode((char*) &Char
, sizeof(wchar_t)) << ">";
281 throw UnknownKeycode(os
.str().c_str());
284 KeyPress::KeyPress(const char *name
)
286 if (strlen(name
) == 0) {
287 Key
= irr::KEY_KEY_CODES_COUNT
;
293 if (strlen(name
) <= 4) {
294 // Lookup by resulting character
295 int chars_read
= mbtowc(&Char
, name
, 1);
296 FATAL_ERROR_IF(chars_read
!= 1, "Unexpected multibyte character");
298 struct table_key k
= lookup_keychar(Char
);
302 } catch (UnknownKeycode
&e
) {};
307 struct table_key k
= lookup_keyname(name
);
311 } catch (UnknownKeycode
&e
) {};
314 // It's not a known key, complain and try to do something
315 Key
= irr::KEY_KEY_CODES_COUNT
;
316 int chars_read
= mbtowc(&Char
, name
, 1);
317 FATAL_ERROR_IF(chars_read
!= 1, "Unexpected multibyte character");
319 warningstream
<< "KeyPress: Unknown key '" << name
<< "', falling back to first char.";
322 KeyPress::KeyPress(const irr::SEvent::SKeyInput
&in
, bool prefer_character
)
324 if (prefer_character
)
325 Key
= irr::KEY_KEY_CODES_COUNT
;
331 if (valid_kcode(Key
))
332 m_name
= lookup_keykey(Key
).Name
;
334 m_name
= lookup_keychar(Char
).Name
;
335 } catch (UnknownKeycode
&e
) {
340 const char *KeyPress::sym() const
342 return m_name
.c_str();
345 const char *KeyPress::name() const
350 if (valid_kcode(Key
))
351 ret
= lookup_keykey(Key
).LangName
;
353 ret
= lookup_keychar(Char
).LangName
;
354 return ret
? ret
: "<Unnamed key>";
357 const KeyPress
EscapeKey("KEY_ESCAPE");
358 const KeyPress
CancelKey("KEY_CANCEL");
364 // A simple cache for quicker lookup
365 std::unordered_map
<std::string
, KeyPress
> g_key_setting_cache
;
367 KeyPress
getKeySetting(const char *settingname
)
369 std::unordered_map
<std::string
, KeyPress
>::iterator n
;
370 n
= g_key_setting_cache
.find(settingname
);
371 if (n
!= g_key_setting_cache
.end())
374 KeyPress
k(g_settings
->get(settingname
).c_str());
375 g_key_setting_cache
[settingname
] = k
;
381 g_key_setting_cache
.clear();
384 irr::EKEY_CODE
keyname_to_keycode(const char *name
)
386 return lookup_keyname(name
).Key
;