Performance fix + SAO factorization
[oweals/minetest.git] / src / keycode.cpp
1 /*
2 Minetest
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
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.
9
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.
14
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.
18 */
19
20 #include "keycode.h"
21 #include "exceptions.h"
22 #include "settings.h"
23 #include "log.h"
24 #include "debug.h"
25 #include "util/hex.h"
26 #include "util/string.h"
27
28 class UnknownKeycode : public BaseException
29 {
30 public:
31         UnknownKeycode(const char *s) :
32                 BaseException(s) {};
33 };
34
35 struct table_key {
36         const char *Name;
37         irr::EKEY_CODE Key;
38         wchar_t Char; // L'\0' means no character assigned
39         const char *LangName; // NULL means it doesn't have a human description
40 };
41
42 #define DEFINEKEY1(x, lang) /* Irrlicht key without character */ \
43         { #x, irr::x, L'\0', lang },
44 #define DEFINEKEY2(x, ch, lang) /* Irrlicht key with character */ \
45         { #x, irr::x, ch, lang },
46 #define DEFINEKEY3(ch) /* single Irrlicht key (e.g. KEY_KEY_X) */ \
47         { "KEY_KEY_" TOSTRING(ch), irr::KEY_KEY_ ## ch, (wchar_t) *TOSTRING(ch), TOSTRING(ch) },
48 #define DEFINEKEY4(ch) /* single Irrlicht function key (e.g. KEY_F3) */ \
49         { "KEY_F" TOSTRING(ch), irr::KEY_F ## ch, L'\0', "F" TOSTRING(ch) },
50 #define DEFINEKEY5(ch) /* key without Irrlicht keycode */ \
51         { ch, irr::KEY_KEY_CODES_COUNT, (wchar_t) *ch, ch },
52
53 #define N_(text) text
54
55 static const struct table_key table[] = {
56         // Keys that can be reliably mapped between Char and Key
57         DEFINEKEY3(0)
58         DEFINEKEY3(1)
59         DEFINEKEY3(2)
60         DEFINEKEY3(3)
61         DEFINEKEY3(4)
62         DEFINEKEY3(5)
63         DEFINEKEY3(6)
64         DEFINEKEY3(7)
65         DEFINEKEY3(8)
66         DEFINEKEY3(9)
67         DEFINEKEY3(A)
68         DEFINEKEY3(B)
69         DEFINEKEY3(C)
70         DEFINEKEY3(D)
71         DEFINEKEY3(E)
72         DEFINEKEY3(F)
73         DEFINEKEY3(G)
74         DEFINEKEY3(H)
75         DEFINEKEY3(I)
76         DEFINEKEY3(J)
77         DEFINEKEY3(K)
78         DEFINEKEY3(L)
79         DEFINEKEY3(M)
80         DEFINEKEY3(N)
81         DEFINEKEY3(O)
82         DEFINEKEY3(P)
83         DEFINEKEY3(Q)
84         DEFINEKEY3(R)
85         DEFINEKEY3(S)
86         DEFINEKEY3(T)
87         DEFINEKEY3(U)
88         DEFINEKEY3(V)
89         DEFINEKEY3(W)
90         DEFINEKEY3(X)
91         DEFINEKEY3(Y)
92         DEFINEKEY3(Z)
93         DEFINEKEY2(KEY_PLUS, L'+', "+")
94         DEFINEKEY2(KEY_COMMA, L',', ",")
95         DEFINEKEY2(KEY_MINUS, L'-', "-")
96         DEFINEKEY2(KEY_PERIOD, L'.', ".")
97
98         // Keys without a Char
99         DEFINEKEY1(KEY_LBUTTON, N_("Left Button"))
100         DEFINEKEY1(KEY_RBUTTON, N_("Right Button"))
101         DEFINEKEY1(KEY_CANCEL, N_("Cancel"))
102         DEFINEKEY1(KEY_MBUTTON, N_("Middle Button"))
103         DEFINEKEY1(KEY_XBUTTON1, N_("X Button 1"))
104         DEFINEKEY1(KEY_XBUTTON2, N_("X Button 2"))
105         DEFINEKEY1(KEY_BACK, N_("Back"))
106         DEFINEKEY1(KEY_TAB, N_("Tab"))
107         DEFINEKEY1(KEY_CLEAR, N_("Clear"))
108         DEFINEKEY1(KEY_RETURN, N_("Return"))
109         DEFINEKEY1(KEY_SHIFT, N_("Shift"))
110         DEFINEKEY1(KEY_CONTROL, N_("Control"))
111         DEFINEKEY1(KEY_MENU, N_("Menu"))
112         DEFINEKEY1(KEY_PAUSE, N_("Pause"))
113         DEFINEKEY1(KEY_CAPITAL, N_("Caps Lock"))
114         DEFINEKEY1(KEY_SPACE, N_("Space"))
115         DEFINEKEY1(KEY_PRIOR, N_("Prior"))
116         DEFINEKEY1(KEY_NEXT, N_("Next"))
117         DEFINEKEY1(KEY_END, N_("End"))
118         DEFINEKEY1(KEY_HOME, N_("Home"))
119         DEFINEKEY1(KEY_LEFT, N_("Left"))
120         DEFINEKEY1(KEY_UP, N_("Up"))
121         DEFINEKEY1(KEY_RIGHT, N_("Right"))
122         DEFINEKEY1(KEY_DOWN, N_("Down"))
123         DEFINEKEY1(KEY_SELECT, N_("Select"))
124         DEFINEKEY1(KEY_PRINT, N_("Print"))
125         DEFINEKEY1(KEY_EXECUT, N_("Execute"))
126         DEFINEKEY1(KEY_SNAPSHOT, N_("Snapshot"))
127         DEFINEKEY1(KEY_INSERT, N_("Insert"))
128         DEFINEKEY1(KEY_DELETE, N_("Delete"))
129         DEFINEKEY1(KEY_HELP, N_("Help"))
130         DEFINEKEY1(KEY_LWIN, N_("Left Windows"))
131         DEFINEKEY1(KEY_RWIN, N_("Right Windows"))
132         DEFINEKEY1(KEY_NUMPAD0, N_("Numpad 0")) // These are not assigned to a char
133         DEFINEKEY1(KEY_NUMPAD1, N_("Numpad 1")) // to prevent interference with KEY_KEY_[0-9].
134         DEFINEKEY1(KEY_NUMPAD2, N_("Numpad 2"))
135         DEFINEKEY1(KEY_NUMPAD3, N_("Numpad 3"))
136         DEFINEKEY1(KEY_NUMPAD4, N_("Numpad 4"))
137         DEFINEKEY1(KEY_NUMPAD5, N_("Numpad 5"))
138         DEFINEKEY1(KEY_NUMPAD6, N_("Numpad 6"))
139         DEFINEKEY1(KEY_NUMPAD7, N_("Numpad 7"))
140         DEFINEKEY1(KEY_NUMPAD8, N_("Numpad 8"))
141         DEFINEKEY1(KEY_NUMPAD9, N_("Numpad 9"))
142         DEFINEKEY1(KEY_MULTIPLY, N_("Numpad *"))
143         DEFINEKEY1(KEY_ADD, N_("Numpad +"))
144         DEFINEKEY1(KEY_SEPARATOR, N_("Numpad ."))
145         DEFINEKEY1(KEY_SUBTRACT, N_("Numpad -"))
146         DEFINEKEY1(KEY_DECIMAL, NULL)
147         DEFINEKEY1(KEY_DIVIDE, N_("Numpad /"))
148         DEFINEKEY4(1)
149         DEFINEKEY4(2)
150         DEFINEKEY4(3)
151         DEFINEKEY4(4)
152         DEFINEKEY4(5)
153         DEFINEKEY4(6)
154         DEFINEKEY4(7)
155         DEFINEKEY4(8)
156         DEFINEKEY4(9)
157         DEFINEKEY4(10)
158         DEFINEKEY4(11)
159         DEFINEKEY4(12)
160         DEFINEKEY4(13)
161         DEFINEKEY4(14)
162         DEFINEKEY4(15)
163         DEFINEKEY4(16)
164         DEFINEKEY4(17)
165         DEFINEKEY4(18)
166         DEFINEKEY4(19)
167         DEFINEKEY4(20)
168         DEFINEKEY4(21)
169         DEFINEKEY4(22)
170         DEFINEKEY4(23)
171         DEFINEKEY4(24)
172         DEFINEKEY1(KEY_NUMLOCK, N_("Num Lock"))
173         DEFINEKEY1(KEY_SCROLL, N_("Scroll Lock"))
174         DEFINEKEY1(KEY_LSHIFT, N_("Left Shift"))
175         DEFINEKEY1(KEY_RSHIFT, N_("Right Shift"))
176         DEFINEKEY1(KEY_LCONTROL, N_("Left Control"))
177         DEFINEKEY1(KEY_RCONTROL, N_("Right Control"))
178         DEFINEKEY1(KEY_LMENU, N_("Left Menu"))
179         DEFINEKEY1(KEY_RMENU, N_("Right Menu"))
180
181         // Rare/weird keys
182         DEFINEKEY1(KEY_KANA, "Kana")
183         DEFINEKEY1(KEY_HANGUEL, "Hangul")
184         DEFINEKEY1(KEY_HANGUL, "Hangul")
185         DEFINEKEY1(KEY_JUNJA, "Junja")
186         DEFINEKEY1(KEY_FINAL, "Final")
187         DEFINEKEY1(KEY_KANJI, "Kanji")
188         DEFINEKEY1(KEY_HANJA, "Hanja")
189         DEFINEKEY1(KEY_ESCAPE, N_("IME Escape"))
190         DEFINEKEY1(KEY_CONVERT, N_("IME Convert"))
191         DEFINEKEY1(KEY_NONCONVERT, N_("IME Nonconvert"))
192         DEFINEKEY1(KEY_ACCEPT, N_("IME Accept"))
193         DEFINEKEY1(KEY_MODECHANGE, N_("IME Mode Change"))
194         DEFINEKEY1(KEY_APPS, N_("Apps"))
195         DEFINEKEY1(KEY_SLEEP, N_("Sleep"))
196 #if !(IRRLICHT_VERSION_MAJOR <= 1 && IRRLICHT_VERSION_MINOR <= 7 && IRRLICHT_VERSION_REVISION < 3)
197         DEFINEKEY1(KEY_OEM_1, "OEM 1") // KEY_OEM_[0-9] and KEY_OEM_102 are assigned to multiple
198         DEFINEKEY1(KEY_OEM_2, "OEM 2") // different chars (on different platforms too) and thus w/o char
199         DEFINEKEY1(KEY_OEM_3, "OEM 3")
200         DEFINEKEY1(KEY_OEM_4, "OEM 4")
201         DEFINEKEY1(KEY_OEM_5, "OEM 5")
202         DEFINEKEY1(KEY_OEM_6, "OEM 6")
203         DEFINEKEY1(KEY_OEM_7, "OEM 7")
204         DEFINEKEY1(KEY_OEM_8, "OEM 8")
205         DEFINEKEY1(KEY_OEM_AX, "OEM AX")
206         DEFINEKEY1(KEY_OEM_102, "OEM 102")
207 #endif
208         DEFINEKEY1(KEY_ATTN, "Attn")
209         DEFINEKEY1(KEY_CRSEL, "CrSel")
210         DEFINEKEY1(KEY_EXSEL, "ExSel")
211         DEFINEKEY1(KEY_EREOF, N_("Erase EOF"))
212         DEFINEKEY1(KEY_PLAY, N_("Play"))
213         DEFINEKEY1(KEY_ZOOM, N_("Zoom"))
214         DEFINEKEY1(KEY_PA1, "PA1")
215         DEFINEKEY1(KEY_OEM_CLEAR, N_("OEM Clear"))
216
217         // Keys without Irrlicht keycode
218         DEFINEKEY5("!")
219         DEFINEKEY5("\"")
220         DEFINEKEY5("#")
221         DEFINEKEY5("$")
222         DEFINEKEY5("%")
223         DEFINEKEY5("&")
224         DEFINEKEY5("'")
225         DEFINEKEY5("(")
226         DEFINEKEY5(")")
227         DEFINEKEY5("*")
228         DEFINEKEY5("/")
229         DEFINEKEY5(":")
230         DEFINEKEY5(";")
231         DEFINEKEY5("<")
232         DEFINEKEY5("=")
233         DEFINEKEY5(">")
234         DEFINEKEY5("?")
235         DEFINEKEY5("@")
236         DEFINEKEY5("[")
237         DEFINEKEY5("\\")
238         DEFINEKEY5("]")
239         DEFINEKEY5("^")
240         DEFINEKEY5("_")
241 };
242
243 #undef N_
244
245 #define ARRAYSIZE(a) (sizeof(a) / sizeof((a)[0]))
246
247 struct table_key lookup_keyname(const char *name)
248 {
249         for (u16 i = 0; i < ARRAYSIZE(table); i++) {
250                 if (strcmp(table[i].Name, name) == 0)
251                         return table[i];
252         }
253
254         throw UnknownKeycode(name);
255 }
256
257 struct table_key lookup_keykey(irr::EKEY_CODE key)
258 {
259         for (u16 i = 0; i < ARRAYSIZE(table); i++) {
260                 if (table[i].Key == key)
261                         return table[i];
262         }
263
264         std::ostringstream os;
265         os << "<Keycode " << (int) key << ">";
266         throw UnknownKeycode(os.str().c_str());
267 }
268
269 struct table_key lookup_keychar(wchar_t Char)
270 {
271         for (u16 i = 0; i < ARRAYSIZE(table); i++) {
272                 if (table[i].Char == Char)
273                         return table[i];
274         }
275
276         std::ostringstream os;
277         os << "<Char " << hex_encode((char*) &Char, sizeof(wchar_t)) << ">";
278         throw UnknownKeycode(os.str().c_str());
279 }
280
281 KeyPress::KeyPress() :
282         Key(irr::KEY_KEY_CODES_COUNT),
283         Char(L'\0'),
284         m_name("")
285 {}
286
287 KeyPress::KeyPress(const char *name)
288 {
289         if (strlen(name) == 0) {
290                 Key = irr::KEY_KEY_CODES_COUNT;
291                 Char = L'\0';
292                 m_name = "";
293                 return;
294         } else if (strlen(name) <= 4) {
295                 // Lookup by resulting character
296                 int chars_read = mbtowc(&Char, name, 1);
297                 FATAL_ERROR_IF(chars_read != 1, "Unexpected multibyte character");
298                 try {
299                         struct table_key k = lookup_keychar(Char);
300                         m_name = k.Name;
301                         Key = k.Key;
302                         return;
303                 } catch (UnknownKeycode &e) {};
304         } else {
305                 // Lookup by name
306                 m_name = name;
307                 try {
308                         struct table_key k = lookup_keyname(name);
309                         Key = k.Key;
310                         Char = k.Char;
311                         return;
312                 } catch (UnknownKeycode &e) {};
313         }
314
315         // It's not a known key, complain and try to do something
316         Key = irr::KEY_KEY_CODES_COUNT;
317         int chars_read = mbtowc(&Char, name, 1);
318         FATAL_ERROR_IF(chars_read != 1, "Unexpected multibyte character");
319         m_name = "";
320         warningstream << "KeyPress: Unknown key '" << name << "', falling back to first char.";
321 }
322
323 KeyPress::KeyPress(const irr::SEvent::SKeyInput &in, bool prefer_character)
324 {
325         if (prefer_character)
326                 Key = irr::KEY_KEY_CODES_COUNT;
327         else
328                 Key = in.Key;
329         Char = in.Char;
330
331         try {
332                 if (valid_kcode(Key))
333                         m_name = lookup_keykey(Key).Name;
334                 else
335                         m_name = lookup_keychar(Char).Name;
336         } catch (UnknownKeycode &e) {
337                 m_name = "";
338         };
339 }
340
341 const char *KeyPress::sym() const
342 {
343         return m_name.c_str();
344 }
345
346 const char *KeyPress::name() const
347 {
348         if (m_name == "")
349                 return "";
350         const char *ret;
351         if (valid_kcode(Key))
352                 ret = lookup_keykey(Key).LangName;
353         else
354                 ret = lookup_keychar(Char).LangName;
355         return ret ? ret : "<Unnamed key>";
356 }
357
358 const KeyPress EscapeKey("KEY_ESCAPE");
359 const KeyPress CancelKey("KEY_CANCEL");
360 const KeyPress NumberKey[] = {
361         KeyPress("0"), KeyPress("1"), KeyPress("2"), KeyPress("3"), KeyPress("4"),
362         KeyPress("5"), KeyPress("6"), KeyPress("7"), KeyPress("8"), KeyPress("9")
363 };
364
365 /*
366         Key config
367 */
368
369 // A simple cache for quicker lookup
370 std::map<std::string, KeyPress> g_key_setting_cache;
371
372 KeyPress getKeySetting(const char *settingname)
373 {
374         std::map<std::string, KeyPress>::iterator n;
375         n = g_key_setting_cache.find(settingname);
376         if(n != g_key_setting_cache.end())
377                 return n->second;
378
379         KeyPress k(g_settings->get(settingname).c_str());
380         g_key_setting_cache[settingname] = k;
381         return k;
382 }
383
384 void clearKeyCache()
385 {
386         g_key_setting_cache.clear();
387 }
388
389 irr::EKEY_CODE keyname_to_keycode(const char *name)
390 {
391         return lookup_keyname(name).Key;
392 }