Fix some memory leak complaints from Valgrind
[lsnes.git] / src / platform / wxwidgets / keyboard.cpp
blob32f11e531cd2a8af3e1fff0b1ab10f32e181481c
1 #include "library/keyboard.hpp"
2 #include "core/keymapper.hpp"
3 #include "core/window.hpp"
5 #include <cstdint>
6 #include <map>
8 #include <wx/wx.h>
9 #include <wx/event.h>
10 #include <wx/control.h>
11 #include <wx/combobox.h>
13 int wx_escape_count = 0;
15 namespace
17 //Modifier table.
18 struct modifier_entry
20 int mod;
21 const char* name;
22 const char* lname;
23 keyboard::modifier* allocated;
24 } modifiers[] = {
25 { wxMOD_ALT, "alt", NULL, NULL },
26 { wxMOD_CONTROL, "ctrl", NULL, NULL },
27 { wxMOD_SHIFT, "shift", NULL, NULL },
28 { wxMOD_META, "meta", NULL, NULL },
29 #ifdef __WXMAC__
30 { wxMOD_CMD, "cmd", NULL, NULL },
31 #endif
32 { 0, NULL, NULL }
35 struct key_entry
37 int keynum;
38 const char* name;
39 const char* clazz;
40 keyboard::key_key* allocated;
41 } keys[] = {
42 { WXK_BACK, "back", "editing", NULL },
43 { WXK_TAB, "tab", "editing", NULL },
44 { WXK_RETURN, "return", "editing", NULL },
45 { WXK_ESCAPE, "escape", "editing", NULL },
46 { WXK_SPACE, "space", "characters", NULL },
47 { 33, "exclaim", "characters", NULL },
48 { 34, "quotedbl", "characters", NULL },
49 { 35, "hash", "characters", NULL },
50 { 36, "dollar", "characters", NULL },
51 { 37, "percent", "characters", NULL },
52 { 38, "ampersand", "characters", NULL },
53 { 39, "quote", "characters", NULL },
54 { 40, "leftparen", "characters", NULL },
55 { 41, "rightparen", "characters", NULL },
56 { 42, "asterisk", "characters", NULL },
57 { 43, "plus", "characters", NULL },
58 { 44, "comma", "characters", NULL },
59 { 45, "minus", "characters", NULL },
60 { 46, "period", "characters", NULL },
61 { 47, "slash", "characters", NULL },
62 { 48, "0", "numeric", NULL },
63 { 49, "1", "numeric", NULL },
64 { 50, "2", "numeric", NULL },
65 { 51, "3", "numeric", NULL },
66 { 52, "4", "numeric", NULL },
67 { 53, "5", "numeric", NULL },
68 { 54, "6", "numeric", NULL },
69 { 55, "7", "numeric", NULL },
70 { 56, "8", "numeric", NULL },
71 { 57, "9", "numeric", NULL },
72 { 58, "colon", "characters", NULL },
73 { 59, "semicolon", "characters", NULL },
74 { 60, "less", "characters", NULL },
75 { 61, "equals", "characters", NULL },
76 { 62, "greater", "characters", NULL },
77 { 63, "question", "characters", NULL },
78 { 64, "at", "characters", NULL },
79 { 65, "a", "alphabetic", NULL },
80 { 66, "b", "alphabetic", NULL },
81 { 67, "c", "alphabetic", NULL },
82 { 68, "d", "alphabetic", NULL },
83 { 69, "e", "alphabetic", NULL },
84 { 70, "f", "alphabetic", NULL },
85 { 71, "g", "alphabetic", NULL },
86 { 72, "h", "alphabetic", NULL },
87 { 73, "i", "alphabetic", NULL },
88 { 74, "j", "alphabetic", NULL },
89 { 75, "k", "alphabetic", NULL },
90 { 76, "l", "alphabetic", NULL },
91 { 77, "m", "alphabetic", NULL },
92 { 78, "n", "alphabetic", NULL },
93 { 79, "o", "alphabetic", NULL },
94 { 80, "p", "alphabetic", NULL },
95 { 81, "q", "alphabetic", NULL },
96 { 82, "r", "alphabetic", NULL },
97 { 83, "s", "alphabetic", NULL },
98 { 84, "t", "alphabetic", NULL },
99 { 85, "u", "alphabetic", NULL },
100 { 86, "v", "alphabetic", NULL },
101 { 87, "w", "alphabetic", NULL },
102 { 88, "x", "alphabetic", NULL },
103 { 89, "y", "alphabetic", NULL },
104 { 90, "z", "alphabetic", NULL },
105 { 91, "leftbracket", "characters", NULL },
106 { 92, "backslash", "characters", NULL },
107 { 93, "rightbracket", "characters", NULL },
108 { 94, "caret", "characters", NULL },
109 { 95, "underscore", "characters", NULL },
110 { 96, "backquote", "characters", NULL },
111 { 97, "a", "alphabetic", NULL },
112 { 98, "b", "alphabetic", NULL },
113 { 99, "c", "alphabetic", NULL },
114 { 100, "d", "alphabetic", NULL },
115 { 101, "e", "alphabetic", NULL },
116 { 102, "f", "alphabetic", NULL },
117 { 103, "g", "alphabetic", NULL },
118 { 104, "h", "alphabetic", NULL },
119 { 105, "i", "alphabetic", NULL },
120 { 106, "j", "alphabetic", NULL },
121 { 107, "k", "alphabetic", NULL },
122 { 108, "l", "alphabetic", NULL },
123 { 109, "m", "alphabetic", NULL },
124 { 110, "n", "alphabetic", NULL },
125 { 111, "o", "alphabetic", NULL },
126 { 112, "p", "alphabetic", NULL },
127 { 113, "q", "alphabetic", NULL },
128 { 114, "r", "alphabetic", NULL },
129 { 115, "s", "alphabetic", NULL },
130 { 116, "t", "alphabetic", NULL },
131 { 117, "u", "alphabetic", NULL },
132 { 118, "v", "alphabetic", NULL },
133 { 119, "w", "alphabetic", NULL },
134 { 120, "x", "alphabetic", NULL },
135 { 121, "y", "alphabetic", NULL },
136 { 122, "z", "alphabetic", NULL },
137 { 123, "leftcurly", "characters", NULL },
138 { 124, "pipe", "characters", NULL },
139 { 125, "rightcurly", "characters", NULL },
140 { 126, "tilde", "characters", NULL },
141 { WXK_DELETE, "delete", "editing", NULL },
142 { WXK_START, "start", "special", NULL },
143 { WXK_LBUTTON, "lbutton", "special", NULL },
144 { WXK_RBUTTON, "rbutton", "special", NULL },
145 { WXK_CANCEL, "cancel", "special", NULL },
146 { WXK_MBUTTON, "mbutton", "special", NULL },
147 { WXK_CLEAR, "clear", "editing", NULL },
148 { WXK_SHIFT, "shift", "modifiers", NULL },
149 { WXK_ALT, "alt", "modifiers", NULL },
150 { WXK_CONTROL, "control", "modifiers", NULL },
151 { WXK_MENU, "menu", "special", NULL },
152 { WXK_PAUSE, "pause", "special", NULL },
153 { WXK_CAPITAL, "capital", "locks", NULL },
154 { WXK_END, "end", "editing", NULL },
155 { WXK_HOME, "home", "editing", NULL },
156 { WXK_LEFT, "lefT", "editing", NULL },
157 { WXK_UP, "up", "editing", NULL },
158 { WXK_RIGHT, "right", "editing", NULL },
159 { WXK_DOWN, "down", "editing", NULL },
160 { WXK_SELECT, "select", "special", NULL },
161 { WXK_PRINT, "print", "special", NULL },
162 { WXK_EXECUTE, "execute", "special", NULL },
163 { WXK_SNAPSHOT, "snapshot", "special", NULL },
164 { WXK_INSERT, "insert", "editing", NULL },
165 { WXK_HELP, "help", "special", NULL },
166 { WXK_NUMPAD0, "numpad0", "numeric", NULL },
167 { WXK_NUMPAD1, "numpad1", "numeric", NULL },
168 { WXK_NUMPAD2, "numpad2", "numeric", NULL },
169 { WXK_NUMPAD3, "numpad3", "numeric", NULL },
170 { WXK_NUMPAD4, "numpad4", "numeric", NULL },
171 { WXK_NUMPAD5, "numpad5", "numeric", NULL },
172 { WXK_NUMPAD6, "numpad6", "numeric", NULL },
173 { WXK_NUMPAD7, "numpad7", "numeric", NULL },
174 { WXK_NUMPAD8, "numpad8", "numeric", NULL },
175 { WXK_NUMPAD9, "numpad9", "numeric", NULL },
176 { WXK_MULTIPLY, "multiply", "characters", NULL },
177 { WXK_ADD, "add", "characters", NULL },
178 { WXK_SEPARATOR, "separator", "characters", NULL },
179 { WXK_SUBTRACT, "subtract", "characters", NULL },
180 { WXK_DECIMAL, "decimal", "characters", NULL },
181 { WXK_DIVIDE, "divide", "characters", NULL },
182 { WXK_F1, "f1", "F-keys", NULL },
183 { WXK_F2, "f2", "F-keys", NULL },
184 { WXK_F3, "f3", "F-keys", NULL },
185 { WXK_F4, "f4", "F-keys", NULL },
186 { WXK_F5, "f5", "F-keys", NULL },
187 { WXK_F6, "f6", "F-keys", NULL },
188 { WXK_F7, "f7", "F-keys", NULL },
189 { WXK_F8, "f8", "F-keys", NULL },
190 { WXK_F9, "f9", "F-keys", NULL },
191 { WXK_F10, "f10", "F-keys", NULL },
192 { WXK_F11, "f11", "F-keys", NULL },
193 { WXK_F12, "f12", "F-keys", NULL },
194 { WXK_F13, "f13", "F-keys", NULL },
195 { WXK_F14, "f14", "F-keys", NULL },
196 { WXK_F15, "f15", "F-keys", NULL },
197 { WXK_F16, "f16", "F-keys", NULL },
198 { WXK_F17, "f17", "F-keys", NULL },
199 { WXK_F18, "f18", "F-keys", NULL },
200 { WXK_F19, "f19", "F-keys", NULL },
201 { WXK_F20, "f20", "F-keys", NULL },
202 { WXK_F21, "f21", "F-keys", NULL },
203 { WXK_F22, "f22", "F-keys", NULL },
204 { WXK_F23, "f23", "F-keys", NULL },
205 { WXK_F24, "f24", "F-keys", NULL },
206 { WXK_NUMLOCK, "numlock", "locks", NULL },
207 { WXK_SCROLL, "scroll", "locks", NULL },
208 { WXK_PAGEUP, "pageup", "editing", NULL },
209 { WXK_PAGEDOWN, "pagedown", "editing", NULL },
210 { WXK_NUMPAD_SPACE, "numpad_space", "editing", NULL },
211 { WXK_NUMPAD_TAB, "numpad_tab", "editing", NULL },
212 { WXK_NUMPAD_ENTER, "numpad_enter", "editing", NULL },
213 { WXK_NUMPAD_F1, "numpad_f1", "F-keys", NULL },
214 { WXK_NUMPAD_F2, "numpad_f2", "F-keys", NULL },
215 { WXK_NUMPAD_F3, "numpad_f3", "F-keys", NULL },
216 { WXK_NUMPAD_F4, "numpad_f4", "F-keys", NULL },
217 { WXK_NUMPAD_HOME, "numpad_home", "editing", NULL },
218 { WXK_NUMPAD_LEFT, "numpad_left", "editing", NULL },
219 { WXK_NUMPAD_UP, "numpad_up", "editing", NULL },
220 { WXK_NUMPAD_RIGHT, "numpad_right", "editing", NULL },
221 { WXK_NUMPAD_DOWN, "numpad_down", "editing", NULL },
222 { WXK_NUMPAD_PAGEUP, "numpad_pageup", "editing", NULL },
223 { WXK_NUMPAD_PAGEDOWN, "numpad_pagedown", "editing", NULL },
224 { WXK_NUMPAD_END, "numpad_end", "editing", NULL },
225 { WXK_NUMPAD_BEGIN, "numpad_begin", "editing", NULL },
226 { WXK_NUMPAD_INSERT, "numpad_insert", "editing", NULL },
227 { WXK_NUMPAD_DELETE, "numpad_delete", "editing", NULL },
228 { WXK_NUMPAD_EQUAL, "numpad_equal", "characters", NULL },
229 { WXK_NUMPAD_MULTIPLY, "numpad_multiply", "characters", NULL },
230 { WXK_NUMPAD_ADD, "numpad_add", "characters", NULL },
231 { WXK_NUMPAD_SEPARATOR, "numpad_separator", "characters", NULL },
232 { WXK_NUMPAD_SUBTRACT, "numpad_subtract", "characters", NULL },
233 { WXK_NUMPAD_DECIMAL, "numpad_decimal", "characters", NULL },
234 { WXK_NUMPAD_DIVIDE, "numpad_divide", "characters", NULL },
235 { WXK_WINDOWS_LEFT, "windows_left", "modifiers", NULL },
236 { WXK_WINDOWS_RIGHT, "windows_right", "modifiers", NULL },
237 { WXK_WINDOWS_MENU, "windows_menu", "modifiers", NULL },
238 { WXK_COMMAND, "command", "special", NULL },
239 { WXK_SPECIAL1, "special1", "special", NULL },
240 { WXK_SPECIAL2, "special2", "special", NULL },
241 { WXK_SPECIAL3, "special3", "special", NULL },
242 { WXK_SPECIAL4, "special4", "special", NULL },
243 { WXK_SPECIAL5, "special5", "special", NULL },
244 { WXK_SPECIAL6, "special6", "special", NULL },
245 { WXK_SPECIAL7, "special7", "special", NULL },
246 { WXK_SPECIAL8, "special8", "special", NULL },
247 { WXK_SPECIAL9, "special9", "special", NULL },
248 { WXK_SPECIAL10, "special10", "special", NULL },
249 { WXK_SPECIAL11, "special11", "special", NULL },
250 { WXK_SPECIAL12, "special12", "special", NULL },
251 { WXK_SPECIAL13, "special13", "special", NULL },
252 { WXK_SPECIAL14, "special14", "special", NULL },
253 { WXK_SPECIAL15, "special15", "special", NULL },
254 { WXK_SPECIAL16, "special16", "special", NULL },
255 { WXK_SPECIAL17, "special17", "special", NULL },
256 { WXK_SPECIAL18, "special18", "special", NULL },
257 { WXK_SPECIAL19, "special19", "special", NULL },
258 { WXK_SPECIAL20, "special20", "special", NULL },
259 { 0, NULL, NULL, NULL }
262 std::map<int, keyboard::modifier*> modifier_map;
263 std::map<int, keyboard::key_key*> key_map;
264 std::map<std::string, int> keys_allocated;
265 std::set<int> keys_held;
267 struct keypress_request
269 keyboard::modifier_set mods;
270 keyboard::key_key* key;
271 bool polarity;
274 //Request keypress event to happen.
275 void do_keypress(keyboard::modifier_set mods, keyboard::key_key& key, bool polarity)
277 struct keypress_request* req = new keypress_request;
278 req->mods = mods;
279 req->key = &key;
280 req->polarity = polarity;
281 platform::queue([](void* args) -> void {
282 struct keypress_request* x = reinterpret_cast<struct keypress_request*>(args);
283 x->key->set_state(x->mods, x->polarity ? 1 : 0);
284 delete x;
285 }, req, false);
289 std::string map_keycode_to_key(int kcode)
291 key_entry* k = keys;
292 while(k->name) {
293 if(k->keynum == kcode)
294 return k->name;
295 k++;
297 return "";
300 void handle_wx_keyboard(wxKeyEvent& e, bool polarity)
302 int mods = e.GetModifiers();
303 int keyc = e.GetKeyCode();
304 if(polarity) {
305 if(keyc == WXK_ESCAPE)
306 wx_escape_count++;
307 else
308 wx_escape_count = 0;
310 keyboard::modifier_set mset;
311 modifier_entry* m = modifiers;
312 while(m->name) {
313 if((mods & m->mod) == m->mod) {
314 mset.add(*m->allocated);
316 m++;
318 if(polarity) {
319 if(keys_held.count(keyc)) {
320 e.Skip();
321 return;
323 keys_held.insert(keyc);
324 } else
325 keys_held.erase(keyc);
326 key_entry* k = keys;
327 keyboard::key_key* grp = NULL;
328 while(k->name) {
329 if(k->keynum == keyc) {
330 grp = k->allocated;
331 break;
333 k++;
335 if(grp)
336 do_keypress(mset, *grp, polarity);
337 e.Skip();
340 void initialize_wx_keyboard()
342 static bool done = false;
343 if(done)
344 return;
345 modifier_entry* m = modifiers;
346 while(m->name) {
347 if(m->lname)
348 m->allocated = new keyboard::modifier(lsnes_kbd, m->name, m->lname);
349 else
350 m->allocated = new keyboard::modifier(lsnes_kbd, m->name);
351 modifier_map[m->mod] = m->allocated;
352 m++;
354 key_entry* k = keys;
355 while(k->name) {
356 if(!keys_allocated.count(k->name)) {
357 k->allocated = new keyboard::key_key(lsnes_kbd, k->name, k->clazz);
358 key_map[k->keynum] = k->allocated;
359 keys_allocated[k->name] = k->keynum;
360 } else
361 key_map[k->keynum] = key_map[keys_allocated[k->name]];
362 k++;
364 done = true;
367 void deinitialize_wx_keyboard()
369 modifier_map.clear();
370 key_map.clear();
371 keys_allocated.clear();
372 keys_held.clear();
373 modifier_entry* m = modifiers;
374 while(m->name) {
375 delete m->allocated;
376 m++;
378 key_entry* k = keys;
379 while(k->name) {
380 delete k->allocated;
381 k++;