]> git.tdb.fi Git - libs/gui.git/blob - source/input/keys.cpp
Reimplement reverse key lookup with a sorted vector
[libs/gui.git] / source / input / keys.cpp
1 #include "keys.h"
2 #include <stdexcept>
3 #include <vector>
4 #include <msp/core/algorithm.h>
5 #include <msp/strings/format.h>
6
7 using namespace std;
8
9 namespace Msp {
10 namespace Input {
11
12 extern unsigned sys_keymap[];
13
14 unsigned key_from_sys(unsigned code)
15 {
16         struct MappedKey
17         {
18                 unsigned code;
19                 Key key;
20         };
21
22         static vector<MappedKey> reverse_map;
23
24         if(reverse_map.empty())
25         {
26                 for(unsigned i=0; i<N_KEYS_; ++i)
27                         if(sys_keymap[i])
28                                 reverse_map.push_back({ sys_keymap[i], static_cast<Key>(i) });
29                 sort_member(reverse_map, &MappedKey::code);
30         }
31
32         auto i = lower_bound_member(reverse_map, code, &MappedKey::code);
33         if(i!=reverse_map.end() && i->code==code)
34                 return i->key;
35
36         return 0;
37 }
38
39 unsigned key_to_sys(unsigned key)
40 {
41         if(key>=N_KEYS_)
42                 throw invalid_argument("key_to_sys");
43         return sys_keymap[key];
44 }
45
46 void operator>>(const LexicalConverter &conv, Key &key)
47 {
48         const string &str = conv.get();
49         if(str.size()==1)
50         {
51                 switch(str[0])
52                 {
53                 case '0': { key = KEY_0; return; }
54                 case '1': { key = KEY_1; return; }
55                 case '2': { key = KEY_2; return; }
56                 case '3': { key = KEY_3; return; }
57                 case '4': { key = KEY_4; return; }
58                 case '5': { key = KEY_5; return; }
59                 case '6': { key = KEY_6; return; }
60                 case '7': { key = KEY_7; return; }
61                 case '8': { key = KEY_8; return; }
62                 case '9': { key = KEY_9; return; }
63                 case 'A': { key = KEY_A; return; }
64                 case 'B': { key = KEY_B; return; }
65                 case 'C': { key = KEY_C; return; }
66                 case 'D': { key = KEY_D; return; }
67                 case 'E': { key = KEY_E; return; }
68                 case 'F': { key = KEY_F; return; }
69                 case 'G': { key = KEY_G; return; }
70                 case 'H': { key = KEY_H; return; }
71                 case 'I': { key = KEY_I; return; }
72                 case 'J': { key = KEY_J; return; }
73                 case 'K': { key = KEY_K; return; }
74                 case 'L': { key = KEY_L; return; }
75                 case 'M': { key = KEY_M; return; }
76                 case 'N': { key = KEY_N; return; }
77                 case 'O': { key = KEY_O; return; }
78                 case 'P': { key = KEY_P; return; }
79                 case 'Q': { key = KEY_Q; return; }
80                 case 'R': { key = KEY_R; return; }
81                 case 'S': { key = KEY_S; return; }
82                 case 'T': { key = KEY_T; return; }
83                 case 'U': { key = KEY_U; return; }
84                 case 'V': { key = KEY_V; return; }
85                 case 'W': { key = KEY_W; return; }
86                 case 'X': { key = KEY_X; return; }
87                 case 'Y': { key = KEY_Y; return; }
88                 case 'Z': { key = KEY_Z; return; }
89                 }
90         }
91         else if(str.size()>1)
92         {
93                 switch(str[0])
94                 {
95                 case 'A':
96                         if(!str.compare(1, string::npos, "DIAERESIS")) { key = KEY_ADIAERESIS; return; }
97                         if(!str.compare(1, string::npos, "LT_L")) { key = KEY_ALT_L; return; }
98                         if(!str.compare(1, string::npos, "LT_R")) { key = KEY_ALT_R; return; }
99                         if(!str.compare(1, string::npos, "POSTROPHE")) { key = KEY_APOSTROPHE; return; }
100                         if(!str.compare(1, string::npos, "RING")) { key = KEY_ARING; return; }
101                         break;
102                 case 'B':
103                         if(!str.compare(1, string::npos, "ACK")) { key = KEY_BACK; return; }
104                         if(!str.compare(1, string::npos, "ACKSLASH")) { key = KEY_BACKSLASH; return; }
105                         if(!str.compare(1, string::npos, "ACKSPACE")) { key = KEY_BACKSPACE; return; }
106                         if(!str.compare(1, string::npos, "RACKET_L")) { key = KEY_BRACKET_L; return; }
107                         if(!str.compare(1, string::npos, "RACKET_R")) { key = KEY_BRACKET_R; return; }
108                         break;
109                 case 'C':
110                         if(!str.compare(1, string::npos, "APS_LOCK")) { key = KEY_CAPS_LOCK; return; }
111                         if(!str.compare(1, string::npos, "OMMA")) { key = KEY_COMMA; return; }
112                         if(!str.compare(1, string::npos, "TRL_L")) { key = KEY_CTRL_L; return; }
113                         if(!str.compare(1, string::npos, "TRL_R")) { key = KEY_CTRL_R; return; }
114                         break;
115                 case 'D':
116                         if(!str.compare(1, string::npos, "ELETE")) { key = KEY_DELETE; return; }
117                         if(!str.compare(1, string::npos, "OWN")) { key = KEY_DOWN; return; }
118                         break;
119                 case 'E':
120                         if(!str.compare(1, string::npos, "ND")) { key = KEY_END; return; }
121                         if(!str.compare(1, string::npos, "NTER")) { key = KEY_ENTER; return; }
122                         if(!str.compare(1, string::npos, "QUAL")) { key = KEY_EQUAL; return; }
123                         if(!str.compare(1, string::npos, "SC")) { key = KEY_ESC; return; }
124                         break;
125                 case 'F':
126                         if(!str.compare(1, string::npos, "1")) { key = KEY_F1; return; }
127                         if(!str.compare(1, string::npos, "2")) { key = KEY_F2; return; }
128                         if(!str.compare(1, string::npos, "3")) { key = KEY_F3; return; }
129                         if(!str.compare(1, string::npos, "4")) { key = KEY_F4; return; }
130                         if(!str.compare(1, string::npos, "5")) { key = KEY_F5; return; }
131                         if(!str.compare(1, string::npos, "6")) { key = KEY_F6; return; }
132                         if(!str.compare(1, string::npos, "7")) { key = KEY_F7; return; }
133                         if(!str.compare(1, string::npos, "8")) { key = KEY_F8; return; }
134                         if(!str.compare(1, string::npos, "9")) { key = KEY_F9; return; }
135                         if(!str.compare(1, string::npos, "10")) { key = KEY_F10; return; }
136                         if(!str.compare(1, string::npos, "11")) { key = KEY_F11; return; }
137                         if(!str.compare(1, string::npos, "12")) { key = KEY_F12; return; }
138                         break;
139                 case 'G':
140                         if(!str.compare(1, string::npos, "RAVE")) { key = KEY_GRAVE; return; }
141                         break;
142                 case 'H':
143                         if(!str.compare(1, string::npos, "OME")) { key = KEY_HOME; return; }
144                         break;
145                 case 'I':
146                         if(!str.compare(1, string::npos, "NSERT")) { key = KEY_INSERT; return; }
147                         break;
148                 case 'K':
149                         if(str[1]=='P')
150                         {
151                                 if(!str.compare(2, string::npos, "0")) { key = KEY_KP0; return; }
152                                 if(!str.compare(2, string::npos, "1")) { key = KEY_KP1; return; }
153                                 if(!str.compare(2, string::npos, "2")) { key = KEY_KP2; return; }
154                                 if(!str.compare(2, string::npos, "3")) { key = KEY_KP3; return; }
155                                 if(!str.compare(2, string::npos, "4")) { key = KEY_KP4; return; }
156                                 if(!str.compare(2, string::npos, "5")) { key = KEY_KP5; return; }
157                                 if(!str.compare(2, string::npos, "6")) { key = KEY_KP6; return; }
158                                 if(!str.compare(2, string::npos, "7")) { key = KEY_KP7; return; }
159                                 if(!str.compare(2, string::npos, "8")) { key = KEY_KP8; return; }
160                                 if(!str.compare(2, string::npos, "9")) { key = KEY_KP9; return; }
161                                 if(!str.compare(2, string::npos, "_ADD")) { key = KEY_KP_ADD; return; }
162                                 if(!str.compare(2, string::npos, "_DIVIDE")) { key = KEY_KP_DIVIDE; return; }
163                                 if(!str.compare(2, string::npos, "_MULTIPLY")) { key = KEY_KP_MULTIPLY; return; }
164                                 if(!str.compare(2, string::npos, "_SEPARATOR")) { key = KEY_KP_SEPARATOR; return; }
165                                 if(!str.compare(2, string::npos, "_SUBTRACT")) { key = KEY_KP_SUBTRACT; return; }
166                         }
167                         break;
168                 case 'L':
169                         if(!str.compare(1, string::npos, "EFT")) { key = KEY_LEFT; return; }
170                         if(!str.compare(1, string::npos, "ESS")) { key = KEY_LESS; return; }
171                         break;
172                 case 'M':
173                         if(!str.compare(1, string::npos, "ENU")) { key = KEY_MENU; return; }
174                         if(!str.compare(1, string::npos, "INUS")) { key = KEY_MINUS; return; }
175                         break;
176                 case 'N':
177                         if(!str.compare(1, string::npos, "ONE")) { key = KEY_NONE; return; }
178                         if(!str.compare(1, string::npos, "UM_LOCK")) { key = KEY_NUM_LOCK; return; }
179                         break;
180                 case 'O':
181                         if(!str.compare(1, string::npos, "DIAERESIS")) { key = KEY_ODIAERESIS; return; }
182                         break;
183                 case 'P':
184                         if(!str.compare(1, string::npos, "AUSE")) { key = KEY_PAUSE; return; }
185                         if(!str.compare(1, string::npos, "ERIOD")) { key = KEY_PERIOD; return; }
186                         if(!str.compare(1, string::npos, "GUP")) { key = KEY_PGUP; return; }
187                         if(!str.compare(1, string::npos, "GDN")) { key = KEY_PGDN; return; }
188                         if(!str.compare(1, string::npos, "LUS")) { key = KEY_PLUS; return; }
189                         if(!str.compare(1, string::npos, "RINT_SCREEN")) { key = KEY_PRINT_SCREEN; return; }
190                         break;
191                 case 'R':
192                         if(!str.compare(1, string::npos, "IGHT")) { key = KEY_RIGHT; return; }
193                         break;
194                 case 'S':
195                         if(!str.compare(1, string::npos, "CROLL_LOCK")) { key = KEY_SCROLL_LOCK; return; }
196                         if(!str.compare(1, string::npos, "EMICOLON")) { key = KEY_SEMICOLON; return; }
197                         if(!str.compare(1, string::npos, "HIFT_L")) { key = KEY_SHIFT_L; return; }
198                         if(!str.compare(1, string::npos, "HIFT_R")) { key = KEY_SHIFT_R; return; }
199                         if(!str.compare(1, string::npos, "LASH")) { key = KEY_SLASH; return; }
200                         if(!str.compare(1, string::npos, "PACE")) { key = KEY_SPACE; return; }
201                         if(!str.compare(1, string::npos, "UPER_R")) { key = KEY_SUPER_R; return; }
202                         if(!str.compare(1, string::npos, "UPER_L")) { key = KEY_SUPER_L; return; }
203                         break;
204                 case 'T':
205                         if(!str.compare(1, string::npos, "AB")) { key = KEY_TAB; return; }
206                         break;
207                 case 'U':
208                         if(!str.compare(1, string::npos, "P")) { key = KEY_UP; return; }
209                         break;
210                 case 'V':
211                         if(!str.compare(1, string::npos, "OLUME_DOWN")) { key = KEY_VOLUME_DOWN; return; }
212                         if(!str.compare(1, string::npos, "OLUME_UP")) { key = KEY_VOLUME_UP; return; }
213                         break;
214                 }
215         }
216
217         throw lexical_error(format("conversion of '%s' to Key", str));
218 }
219
220 void operator<<(LexicalConverter &conv, Key key)
221 {
222         switch(key)
223         {
224         case KEY_NONE: conv.result("NONE"); break;
225         case KEY_BACKSPACE: conv.result("BACKSPACE"); break;
226         case KEY_TAB: conv.result("TAB"); break;
227         case KEY_ENTER: conv.result("ENTER"); break;
228         case KEY_ESC: conv.result("ESC"); break;
229         case KEY_SPACE: conv.result("SPACE"); break;
230         case KEY_APOSTROPHE: conv.result("APOSTROPHE"); break;
231         case KEY_PLUS: conv.result("PLUS"); break;
232         case KEY_COMMA: conv.result("COMMA"); break;
233         case KEY_MINUS: conv.result("MINUS"); break;
234         case KEY_PERIOD: conv.result("PERIOD"); break;
235         case KEY_SLASH: conv.result("SLASH"); break;
236         case KEY_0: conv.result("0"); break;
237         case KEY_1: conv.result("1"); break;
238         case KEY_2: conv.result("2"); break;
239         case KEY_3: conv.result("3"); break;
240         case KEY_4: conv.result("4"); break;
241         case KEY_5: conv.result("5"); break;
242         case KEY_6: conv.result("6"); break;
243         case KEY_7: conv.result("7"); break;
244         case KEY_8: conv.result("8"); break;
245         case KEY_9: conv.result("9"); break;
246         case KEY_SEMICOLON: conv.result("SEMICOLON"); break;
247         case KEY_LESS: conv.result("LESS"); break;
248         case KEY_EQUAL: conv.result("EQUAL"); break;
249         case KEY_A: conv.result("A"); break;
250         case KEY_B: conv.result("B"); break;
251         case KEY_C: conv.result("C"); break;
252         case KEY_D: conv.result("D"); break;
253         case KEY_E: conv.result("E"); break;
254         case KEY_F: conv.result("F"); break;
255         case KEY_G: conv.result("G"); break;
256         case KEY_H: conv.result("H"); break;
257         case KEY_I: conv.result("I"); break;
258         case KEY_J: conv.result("J"); break;
259         case KEY_K: conv.result("K"); break;
260         case KEY_L: conv.result("L"); break;
261         case KEY_M: conv.result("M"); break;
262         case KEY_N: conv.result("N"); break;
263         case KEY_O: conv.result("O"); break;
264         case KEY_P: conv.result("P"); break;
265         case KEY_Q: conv.result("Q"); break;
266         case KEY_R: conv.result("R"); break;
267         case KEY_S: conv.result("S"); break;
268         case KEY_T: conv.result("T"); break;
269         case KEY_U: conv.result("U"); break;
270         case KEY_V: conv.result("V"); break;
271         case KEY_W: conv.result("W"); break;
272         case KEY_X: conv.result("X"); break;
273         case KEY_Y: conv.result("Y"); break;
274         case KEY_Z: conv.result("Z"); break;
275         case KEY_BRACKET_L: conv.result("BRACKET_L"); break;
276         case KEY_BACKSLASH: conv.result("BACKSLASH"); break;
277         case KEY_BRACKET_R: conv.result("BRACKET_R"); break;
278         case KEY_GRAVE: conv.result("GRAVE"); break;
279         case KEY_ADIAERESIS: conv.result("ADIAERESIS"); break;
280         case KEY_ODIAERESIS: conv.result("ODIAERESIS"); break;
281         case KEY_UDIAERESIS: conv.result("UDIAERESIS"); break;
282         case KEY_ARING: conv.result("ARING"); break;
283         case KEY_LEFT: conv.result("LEFT"); break;
284         case KEY_RIGHT: conv.result("RIGHT"); break;
285         case KEY_UP: conv.result("UP"); break;
286         case KEY_DOWN: conv.result("DOWN"); break;
287         case KEY_HOME: conv.result("HOME"); break;
288         case KEY_END: conv.result("END"); break;
289         case KEY_PGUP: conv.result("PGUP"); break;
290         case KEY_PGDN: conv.result("PGDN"); break;
291         case KEY_INSERT: conv.result("INSERT"); break;
292         case KEY_DELETE: conv.result("DELETE"); break;
293         case KEY_F1: conv.result("F1"); break;
294         case KEY_F2: conv.result("F2"); break;
295         case KEY_F3: conv.result("F3"); break;
296         case KEY_F4: conv.result("F4"); break;
297         case KEY_F5: conv.result("F5"); break;
298         case KEY_F6: conv.result("F6"); break;
299         case KEY_F7: conv.result("F7"); break;
300         case KEY_F8: conv.result("F8"); break;
301         case KEY_F9: conv.result("F9"); break;
302         case KEY_F10: conv.result("F10"); break;
303         case KEY_F11: conv.result("F11"); break;
304         case KEY_F12: conv.result("F12"); break;
305         case KEY_SHIFT_L: conv.result("SHIFT_L"); break;
306         case KEY_SHIFT_R: conv.result("SHIFT_R"); break;
307         case KEY_CTRL_L: conv.result("CTRL_L"); break;
308         case KEY_CTRL_R: conv.result("CTRL_R"); break;
309         case KEY_ALT_L: conv.result("ALT_L"); break;
310         case KEY_ALT_R: conv.result("ALT_R"); break;
311         case KEY_SUPER_L: conv.result("SUPER_L"); break;
312         case KEY_SUPER_R: conv.result("SUPER_R"); break;
313         case KEY_CAPS_LOCK: conv.result("CAPS_LOCK"); break;
314         case KEY_SCROLL_LOCK: conv.result("SCROLL_LOCK"); break;
315         case KEY_NUM_LOCK: conv.result("NUM_LOCK"); break;
316         case KEY_KP0: conv.result("KP0"); break;
317         case KEY_KP1: conv.result("KP1"); break;
318         case KEY_KP2: conv.result("KP2"); break;
319         case KEY_KP3: conv.result("KP3"); break;
320         case KEY_KP4: conv.result("KP4"); break;
321         case KEY_KP5: conv.result("KP5"); break;
322         case KEY_KP6: conv.result("KP6"); break;
323         case KEY_KP7: conv.result("KP7"); break;
324         case KEY_KP8: conv.result("KP8"); break;
325         case KEY_KP9: conv.result("KP9"); break;
326         case KEY_KP_ADD: conv.result("KP_ADD"); break;
327         case KEY_KP_SUBTRACT: conv.result("KP_SUBTRACT"); break;
328         case KEY_KP_MULTIPLY: conv.result("KP_MULTIPLY"); break;
329         case KEY_KP_DIVIDE: conv.result("KP_DIVIDE"); break;
330         case KEY_KP_SEPARATOR: conv.result("KP_SEPARATOR"); break;
331         case KEY_PAUSE: conv.result("PAUSE"); break;
332         case KEY_PRINT_SCREEN: conv.result("PRINT_SCREEN"); break;
333         case KEY_MENU: conv.result("MENU"); break;
334         case KEY_BACK: conv.result("BACK"); break;
335         case KEY_VOLUME_UP: conv.result("VOLUME_UP"); break;
336         case KEY_VOLUME_DOWN: conv.result("VOLUME_DOWN"); break;
337         default: conv.result(format("Key(%#x)", static_cast<int>(key)));
338         }
339 }
340
341 void operator>>(const LexicalConverter &conv, MouseAxis &axis)
342 {
343         if(conv.get()=="X")
344                 axis = MOUSE_X_AXIS;
345         else if(conv.get()=="Y")
346                 axis = MOUSE_Y_AXIS;
347         else
348                 throw lexical_error(format("conversion of '%s' to MouseAxis", conv.get()));
349 }
350
351 void operator<<(LexicalConverter &conv, MouseAxis axis)
352 {
353         switch(axis)
354         {
355         case MOUSE_X_AXIS: conv.result("X"); break;
356         case MOUSE_Y_AXIS: conv.result("Y"); break;
357         default: conv.result(format("MouseAxis(%#x)", static_cast<int>(axis)));
358         }
359 }
360
361 void operator>>(const LexicalConverter &conv, MouseButton &btn)
362 {
363         if(conv.get()=="LEFT")
364                 btn = MOUSE_LEFT;
365         else if(conv.get()=="MIDDLE")
366                 btn = MOUSE_MIDDLE;
367         else if(conv.get()=="RIGHT")
368                 btn = MOUSE_RIGHT;
369         else if(conv.get()=="WHEEL_UP")
370                 btn = MOUSE_WHEEL_UP;
371         else if(conv.get()=="WHEEL_DOWN")
372                 btn = MOUSE_WHEEL_DOWN;
373         else
374                 throw lexical_error(format("conversion of '%s' to MouseButton", conv.get()));
375 }
376
377 void operator<<(LexicalConverter &conv, MouseButton btn)
378 {
379         switch(btn)
380         {
381         case MOUSE_LEFT: conv.result("LEFT"); break;
382         case MOUSE_MIDDLE: conv.result("MIDDLE"); break;
383         case MOUSE_RIGHT: conv.result("RIGHT"); break;
384         case MOUSE_WHEEL_UP: conv.result("WHEEL_UP"); break;
385         case MOUSE_WHEEL_DOWN: conv.result("WHEEL_DOWN"); break;
386         default: conv.result(format("MouseButton(%#x)", static_cast<int>(btn)));
387         }
388 }
389
390 } // namespace Input
391 } // namespace Msp