openMSX
Keys.cc
Go to the documentation of this file.
1 #include "Keys.hh"
2 #include "StringOp.hh"
3 #include "cstd.hh"
4 #include "ranges.hh"
5 #include <array>
6 
7 using std::string;
8 using std::string_view;
9 
10 namespace openmsx::Keys {
11 
12 // can be std::pair in C++20
13 struct P {
14  constexpr P(string_view s, KeyCode k)
15  : first(s), second(k) {}
16 
17  // Needed for gcc-6.3. Compiler bug?
18  constexpr P& operator=(const P& o) {
19  first = o.first;
20  second = o.second;
21  return *this;
22  }
23  constexpr P(const P& p) = default;
24 
25  string_view first;
27 };
28 
29 struct CmpKeys {
30  // for cstd::sort
31  constexpr bool operator()(const P& x, const P& y) const {
32  return x.first < y.first; // shortcut: no need to ignore case
33  }
34 
35  // for lower_bound()
36  bool operator()(const P& x, string_view y) const {
38  return cmp(x.first, y);
39  }
40 };
41 
42 #ifdef _MSC_VER
43  // Workaround visual studio compiler bug, see
44  // https://developercommunity.visualstudio.com/content/problem/429980/wrong-code-with-constexpr-on-msvc-1916.html
45  // Disable compile-time sorting on msvc until that bug gets solved.
46  #define KEYS_CONSTEXPR
47  #define KEYS_SORT ranges::sort
48 #else
49  #define KEYS_CONSTEXPR constexpr
50  #define KEYS_SORT cstd::sort
51 #endif
52 static KEYS_CONSTEXPR auto getSortedKeys()
53 {
54  auto keys = std::array{
55  P("BACKSPACE", K_BACKSPACE),
56  P("TAB", K_TAB),
57  P("CLEAR", K_CLEAR),
58  P("RETURN", K_RETURN),
59  P("PAUSE", K_PAUSE),
60  P("ESCAPE", K_ESCAPE),
61  P("SPACE", K_SPACE),
62  P("EXCLAIM", K_EXCLAIM),
63  P("QUOTEDBL", K_QUOTEDBL),
64  P("HASH", K_HASH),
65  P("DOLLAR", K_DOLLAR),
66  P("AMPERSAND", K_AMPERSAND),
67  P("QUOTE", K_QUOTE),
68  P("LEFTPAREN", K_LEFTPAREN),
69  P("RIGHTPAREN", K_RIGHTPAREN),
70  P("ASTERISK", K_ASTERISK),
71  P("PLUS", K_PLUS),
72  P("COMMA", K_COMMA),
73  P("MINUS", K_MINUS),
74  P("PERIOD", K_PERIOD),
75  P("SLASH", K_SLASH),
76  P("0", K_0),
77  P("1", K_1),
78  P("2", K_2),
79  P("3", K_3),
80  P("4", K_4),
81  P("5", K_5),
82  P("6", K_6),
83  P("7", K_7),
84  P("8", K_8),
85  P("9", K_9),
86  P("COLON", K_COLON),
87  P("SEMICOLON", K_SEMICOLON),
88  P("LESS", K_LESS),
89  P("EQUALS", K_EQUALS),
90  P("GREATER", K_GREATER),
91  P("QUESTION", K_QUESTION),
92  P("AT", K_AT),
93 
94  P("LEFTBRACKET",K_LEFTBRACKET),
95  P("BACKSLASH", K_BACKSLASH),
96  P("RIGHTBRACKET",K_RIGHTBRACKET),
97  P("CARET", K_CARET),
98  P("UNDERSCORE", K_UNDERSCORE),
99  P("BACKQUOTE", K_BACKQUOTE),
100  P("A", K_A),
101  P("B", K_B),
102  P("C", K_C),
103  P("D", K_D),
104  P("E", K_E),
105  P("F", K_F),
106  P("G", K_G),
107  P("H", K_H),
108  P("I", K_I),
109  P("J", K_J),
110  P("K", K_K),
111  P("L", K_L),
112  P("M", K_M),
113  P("N", K_N),
114  P("O", K_O),
115  P("P", K_P),
116  P("Q", K_Q),
117  P("R", K_R),
118  P("S", K_S),
119  P("T", K_T),
120  P("U", K_U),
121  P("V", K_V),
122  P("W", K_W),
123  P("X", K_X),
124  P("Y", K_Y),
125  P("Z", K_Z),
126  P("DELETE", K_DELETE),
127 
128 /*
129  P("WORLD_0", K_WORLD_0),
130  P("WORLD_1", K_WORLD_1),
131  P("WORLD_2", K_WORLD_2),
132  P("WORLD_3", K_WORLD_3),
133  P("WORLD_4", K_WORLD_4),
134  P("WORLD_5", K_WORLD_5),
135  P("WORLD_6", K_WORLD_6),
136  P("WORLD_7", K_WORLD_7),
137  P("WORLD_8", K_WORLD_8),
138  P("WORLD_9", K_WORLD_9),
139  P("WORLD_10", K_WORLD_10),
140  P("WORLD_11", K_WORLD_11),
141  P("WORLD_12", K_WORLD_12),
142  P("WORLD_13", K_WORLD_13),
143  P("WORLD_14", K_WORLD_14),
144  P("WORLD_15", K_WORLD_15),
145  P("WORLD_16", K_WORLD_16),
146  P("WORLD_17", K_WORLD_17),
147  P("WORLD_18", K_WORLD_18),
148  P("WORLD_19", K_WORLD_19),
149  P("WORLD_20", K_WORLD_20),
150  P("WORLD_21", K_WORLD_21),
151  P("WORLD_22", K_WORLD_22),
152  P("WORLD_23", K_WORLD_23),
153  P("WORLD_24", K_WORLD_24),
154  P("WORLD_25", K_WORLD_25),
155  P("WORLD_26", K_WORLD_26),
156  P("WORLD_27", K_WORLD_27),
157  P("WORLD_28", K_WORLD_28),
158  P("WORLD_29", K_WORLD_29),
159  P("WORLD_30", K_WORLD_30),
160  P("WORLD_31", K_WORLD_31),
161  P("WORLD_32", K_WORLD_32),
162  P("WORLD_33", K_WORLD_33),
163  P("WORLD_34", K_WORLD_34),
164  P("WORLD_35", K_WORLD_35),
165  P("WORLD_36", K_WORLD_36),
166  P("WORLD_37", K_WORLD_37),
167  P("WORLD_38", K_WORLD_38),
168  P("WORLD_39", K_WORLD_39),
169  P("WORLD_40", K_WORLD_40),
170  P("WORLD_41", K_WORLD_41),
171  P("WORLD_42", K_WORLD_42),
172  P("WORLD_43", K_WORLD_43),
173  P("WORLD_44", K_WORLD_44),
174  P("WORLD_45", K_WORLD_45),
175  P("WORLD_46", K_WORLD_46),
176  P("WORLD_47", K_WORLD_47),
177  P("WORLD_48", K_WORLD_48),
178  P("WORLD_49", K_WORLD_49),
179  P("WORLD_50", K_WORLD_50),
180  P("WORLD_51", K_WORLD_51),
181  P("WORLD_52", K_WORLD_52),
182  P("WORLD_53", K_WORLD_53),
183  P("WORLD_54", K_WORLD_54),
184  P("WORLD_55", K_WORLD_55),
185  P("WORLD_56", K_WORLD_56),
186  P("WORLD_57", K_WORLD_57),
187  P("WORLD_58", K_WORLD_58),
188  P("WORLD_59", K_WORLD_59),
189  P("WORLD_60", K_WORLD_60),
190  P("WORLD_61", K_WORLD_61),
191  P("WORLD_62", K_WORLD_62),
192  P("WORLD_63", K_WORLD_63),
193  P("WORLD_64", K_WORLD_64),
194  P("WORLD_65", K_WORLD_65),
195  P("WORLD_66", K_WORLD_66),
196  P("WORLD_67", K_WORLD_67),
197  P("WORLD_68", K_WORLD_68),
198  P("WORLD_69", K_WORLD_69),
199  P("WORLD_70", K_WORLD_70),
200  P("WORLD_71", K_WORLD_71),
201  P("WORLD_72", K_WORLD_72),
202  P("WORLD_73", K_WORLD_73),
203  P("WORLD_74", K_WORLD_74),
204  P("WORLD_75", K_WORLD_75),
205  P("WORLD_76", K_WORLD_76),
206  P("WORLD_77", K_WORLD_77),
207  P("WORLD_78", K_WORLD_78),
208  P("WORLD_79", K_WORLD_79),
209  P("WORLD_80", K_WORLD_80),
210  P("WORLD_81", K_WORLD_81),
211  P("WORLD_82", K_WORLD_82),
212  P("WORLD_83", K_WORLD_83),
213  P("WORLD_84", K_WORLD_84),
214  P("WORLD_85", K_WORLD_85),
215  P("WORLD_86", K_WORLD_86),
216  P("WORLD_87", K_WORLD_87),
217  P("WORLD_88", K_WORLD_88),
218  P("WORLD_89", K_WORLD_89),
219  P("WORLD_90", K_WORLD_90),
220  P("WORLD_91", K_WORLD_91),
221  P("WORLD_92", K_WORLD_92),
222  P("WORLD_93", K_WORLD_93),
223  P("WORLD_94", K_WORLD_94),
224  P("WORLD_95", K_WORLD_95),
225 */
226 
227  // Numeric keypad
228  P("KP0", K_KP0),
229  P("KP1", K_KP1),
230  P("KP2", K_KP2),
231  P("KP3", K_KP3),
232  P("KP4", K_KP4),
233  P("KP5", K_KP5),
234  P("KP6", K_KP6),
235  P("KP7", K_KP7),
236  P("KP8", K_KP8),
237  P("KP9", K_KP9),
238  P("KP_PERIOD", K_KP_PERIOD),
239  P("KP_DIVIDE", K_KP_DIVIDE),
240  P("KP_MULTIPLY",K_KP_MULTIPLY),
241  P("KP_MINUS", K_KP_MINUS),
242  P("KP_PLUS", K_KP_PLUS),
243  P("KP_ENTER", K_KP_ENTER),
244  P("KP_EQUALS", K_KP_EQUALS),
245 
246  // Arrows + Home/End pad
247  P("UP", K_UP),
248  P("DOWN", K_DOWN),
249  P("RIGHT", K_RIGHT),
250  P("LEFT", K_LEFT),
251  P("INSERT", K_INSERT),
252  P("HOME", K_HOME),
253  P("END", K_END),
254  P("PAGEUP", K_PAGEUP),
255  P("PAGEDOWN", K_PAGEDOWN),
256 
257  // Function keys
258  P("F1", K_F1),
259  P("F2", K_F2),
260  P("F3", K_F3),
261  P("F4", K_F4),
262  P("F5", K_F5),
263  P("F6", K_F6),
264  P("F7", K_F7),
265  P("F8", K_F8),
266  P("F9", K_F9),
267  P("F10", K_F10),
268  P("F11", K_F11),
269  P("F12", K_F12),
270  P("F13", K_F13),
271  P("F14", K_F14),
272  P("F15", K_F15),
273  P("F16", K_F16),
274  P("F17", K_F17),
275  P("F18", K_F18),
276  P("F19", K_F19),
277  P("F20", K_F20),
278  P("F21", K_F21),
279  P("F22", K_F22),
280  P("F23", K_F23),
281  P("F24", K_F24),
282 
283  // Key state modifier keys
284  P("NUMLOCK", K_NUMLOCK),
285  P("CAPSLOCK", K_CAPSLOCK),
286  // Note: Older openMSX releases duplicated the SDL 1.2 spelling mistake
287  // in the scroll lock key symbol. Since the wrong spelling comes
288  // alphabetically after the right one, our to-string conversion
289  // will pick the right one.
290  P("SCROLLLOCK", K_SCROLLLOCK),
291  P("SCROLLOCK", K_SCROLLLOCK), // backwards compat
292  P("RSHIFT", K_RSHIFT),
293  P("LSHIFT", K_LSHIFT),
294  P("RCTRL", K_RCTRL),
295  P("LCTRL", K_LCTRL),
296  P("RALT", K_RALT),
297  P("LALT", K_LALT),
298 // P("RMETA", K_RMETA),
299 // P("LMETA", K_LMETA),
300  P("LSUPER", K_LSUPER), // Left "Windows" key
301  P("RSUPER", K_RSUPER), // Right "Windows" key
302  P("RMODE", K_MODE), // "Alt Gr" key
303 // P("COMPOSE", K_COMPOSE), // Multi-key compose key
304 
305  // Miscellaneous function keys
306  P("HELP", K_HELP),
307  P("PRINT", K_PRINT),
308  P("SYSREQ", K_SYSREQ),
309 // P("BREAK", K_BREAK),
310  P("MENU", K_MENU),
311  P("POWER", K_POWER), // Power Macintosh power key
312 // P("EURO", K_EURO), // Some european keyboards
313  P("UNDO", K_UNDO),
314 
315  // Application Control keys
316  P("BACK", K_BACK),
317 
318  // Japanese keyboard special keys
319  P("ZENKAKU_HENKAKU", K_ZENKAKU_HENKAKU),
320  P("MUHENKAN", K_MUHENKAN),
321  P("HENKAN_MODE", K_HENKAN_MODE),
322  P("HIRAGANA_KATAKANA", K_HIRAGANA_KATAKANA),
323 
324  // Modifiers
325  P("SHIFT", KM_SHIFT),
326  P("CTRL", KM_CTRL),
327  P("ALT", KM_ALT),
328  P("META", KM_META),
329  P("MODE", KM_MODE),
330 
331  // Direction modifiers
332  P("PRESS", KD_PRESS),
333  P("RELEASE", KD_RELEASE)
334  };
335  KEYS_SORT(keys, CmpKeys());
336  return keys;
337 }
338 
339 static KEYS_CONSTEXPR auto keys = getSortedKeys();
340 
341 KeyCode getCode(string_view name)
342 {
343  auto result = static_cast<KeyCode>(0);
344  string_view::size_type lastPos = 0;
345  while (lastPos != string_view::npos) {
346  auto pos = name.substr(lastPos).find_first_of(",+/");
347  auto part = (pos != string_view::npos)
348  ? name.substr(lastPos, pos)
349  : name.substr(lastPos);
350  auto it = ranges::lower_bound(keys, part, CmpKeys());
351  StringOp::casecmp cmp;
352  if ((it == std::end(keys)) || !cmp(it->first, part)) {
353  return K_NONE;
354  }
355  KeyCode partCode = it->second;
356  if ((partCode & K_MASK) && (result & K_MASK)) {
357  // more than one non-modifier component
358  // is not allowed
359  return K_NONE;
360  }
361  result = static_cast<KeyCode>(result | partCode);
362  lastPos = (pos != string_view::npos)
363  ? lastPos + pos + 1
364  : string_view::npos;
365  }
366  return result;
367 }
368 
369 KeyCode getCode(SDL_Keycode key, Uint16 mod, SDL_Scancode scancode, bool release)
370 {
371  KeyCode result;
372  switch (key) {
373  case SDLK_BACKSPACE: result = K_BACKSPACE; break;
374  case SDLK_TAB: result = K_TAB; break;
375  case SDLK_CLEAR: result = K_CLEAR; break;
376  case SDLK_RETURN: result = K_RETURN; break;
377  case SDLK_PAUSE: result = K_PAUSE; break;
378  case SDLK_ESCAPE: result = K_ESCAPE; break;
379  case SDLK_SPACE: result = K_SPACE; break;
380  case SDLK_EXCLAIM: result = K_EXCLAIM; break;
381  case SDLK_QUOTEDBL: result = K_QUOTEDBL; break;
382  case SDLK_HASH: result = K_HASH; break;
383  case SDLK_DOLLAR: result = K_DOLLAR; break;
384  case SDLK_AMPERSAND: result = K_AMPERSAND; break;
385  case SDLK_QUOTE: result = K_QUOTE; break;
386  case SDLK_LEFTPAREN: result = K_LEFTPAREN; break;
387  case SDLK_RIGHTPAREN: result = K_RIGHTPAREN; break;
388  case SDLK_ASTERISK: result = K_ASTERISK; break;
389  case SDLK_PLUS: result = K_PLUS; break;
390  case SDLK_COMMA: result = K_COMMA; break;
391  case SDLK_MINUS: result = K_MINUS; break;
392  case SDLK_PERIOD: result = K_PERIOD; break;
393  case SDLK_SLASH: result = K_SLASH; break;
394  case SDLK_0: result = K_0; break;
395  case SDLK_1: result = K_1; break;
396  case SDLK_2: result = K_2; break;
397  case SDLK_3: result = K_3; break;
398  case SDLK_4: result = K_4; break;
399  case SDLK_5: result = K_5; break;
400  case SDLK_6: result = K_6; break;
401  case SDLK_7: result = K_7; break;
402  case SDLK_8: result = K_8; break;
403  case SDLK_9: result = K_9; break;
404  case SDLK_COLON: result = K_COLON; break;
405  case SDLK_SEMICOLON: result = K_SEMICOLON; break;
406  case SDLK_LESS: result = K_LESS; break;
407  case SDLK_EQUALS: result = K_EQUALS; break;
408  case SDLK_GREATER: result = K_GREATER; break;
409  case SDLK_QUESTION: result = K_QUESTION; break;
410  case SDLK_AT: result = K_AT; break;
411 
412  case SDLK_LEFTBRACKET: result = K_LEFTBRACKET; break;
413  case SDLK_BACKSLASH: result = K_BACKSLASH; break;
414  case SDLK_RIGHTBRACKET: result = K_RIGHTBRACKET; break;
415  case SDLK_CARET: result = K_CARET; break;
416  case SDLK_UNDERSCORE: result = K_UNDERSCORE; break;
417  case SDLK_BACKQUOTE: result = K_BACKQUOTE; break;
418  case SDLK_a: result = K_A; break;
419  case SDLK_b: result = K_B; break;
420  case SDLK_c: result = K_C; break;
421  case SDLK_d: result = K_D; break;
422  case SDLK_e: result = K_E; break;
423  case SDLK_f: result = K_F; break;
424  case SDLK_g: result = K_G; break;
425  case SDLK_h: result = K_H; break;
426  case SDLK_i: result = K_I; break;
427  case SDLK_j: result = K_J; break;
428  case SDLK_k: result = K_K; break;
429  case SDLK_l: result = K_L; break;
430  case SDLK_m: result = K_M; break;
431  case SDLK_n: result = K_N; break;
432  case SDLK_o: result = K_O; break;
433  case SDLK_p: result = K_P; break;
434  case SDLK_q: result = K_Q; break;
435  case SDLK_r: result = K_R; break;
436  case SDLK_s: result = K_S; break;
437  case SDLK_t: result = K_T; break;
438  case SDLK_u: result = K_U; break;
439  case SDLK_v: result = K_V; break;
440  case SDLK_w: result = K_W; break;
441  case SDLK_x: result = K_X; break;
442  case SDLK_y: result = K_Y; break;
443  case SDLK_z: result = K_Z; break;
444  case SDLK_DELETE: result = K_DELETE; break;
445 
446  // Numeric keypad
447  case SDLK_KP_0: result = K_KP0; break;
448  case SDLK_KP_1: result = K_KP1; break;
449  case SDLK_KP_2: result = K_KP2; break;
450  case SDLK_KP_3: result = K_KP3; break;
451  case SDLK_KP_4: result = K_KP4; break;
452  case SDLK_KP_5: result = K_KP5; break;
453  case SDLK_KP_6: result = K_KP6; break;
454  case SDLK_KP_7: result = K_KP7; break;
455  case SDLK_KP_8: result = K_KP8; break;
456  case SDLK_KP_9: result = K_KP9; break;
457  case SDLK_KP_PERIOD: result = K_KP_PERIOD; break;
458  case SDLK_KP_DIVIDE: result = K_KP_DIVIDE; break;
459  case SDLK_KP_MULTIPLY: result = K_KP_MULTIPLY; break;
460  case SDLK_KP_MINUS: result = K_KP_MINUS; break;
461  case SDLK_KP_PLUS: result = K_KP_PLUS; break;
462  case SDLK_KP_ENTER: result = K_KP_ENTER; break;
463  case SDLK_KP_EQUALS: result = K_KP_EQUALS; break;
464 
465  // Arrows + Home/End pad
466  case SDLK_UP: result = K_UP; break;
467  case SDLK_DOWN: result = K_DOWN; break;
468  case SDLK_RIGHT: result = K_RIGHT; break;
469  case SDLK_LEFT: result = K_LEFT; break;
470  case SDLK_INSERT: result = K_INSERT; break;
471  case SDLK_HOME: result = K_HOME; break;
472  case SDLK_END: result = K_END; break;
473  case SDLK_PAGEUP: result = K_PAGEUP; break;
474  case SDLK_PAGEDOWN: result = K_PAGEDOWN; break;
475 
476  // Function keys
477  case SDLK_F1: result = K_F1; break;
478  case SDLK_F2: result = K_F2; break;
479  case SDLK_F3: result = K_F3; break;
480  case SDLK_F4: result = K_F4; break;
481  case SDLK_F5: result = K_F5; break;
482  case SDLK_F6: result = K_F6; break;
483  case SDLK_F7: result = K_F7; break;
484  case SDLK_F8: result = K_F8; break;
485  case SDLK_F9: result = K_F9; break;
486  case SDLK_F10: result = K_F10; break;
487  case SDLK_F11: result = K_F11; break;
488  case SDLK_F12: result = K_F12; break;
489  case SDLK_F13: result = K_F13; break;
490  case SDLK_F14: result = K_F14; break;
491  case SDLK_F15: result = K_F15; break;
492  case SDLK_F16: result = K_F16; break;
493  case SDLK_F17: result = K_F17; break;
494  case SDLK_F18: result = K_F18; break;
495  case SDLK_F19: result = K_F19; break;
496  case SDLK_F20: result = K_F20; break;
497  case SDLK_F21: result = K_F21; break;
498  case SDLK_F22: result = K_F22; break;
499  case SDLK_F23: result = K_F23; break;
500  case SDLK_F24: result = K_F24; break;
501 
502  // Key state modifier keys
503  case SDLK_NUMLOCKCLEAR: result = K_NUMLOCK; break;
504  case SDLK_CAPSLOCK: result = K_CAPSLOCK; break;
505  case SDLK_SCROLLLOCK: result = K_SCROLLLOCK; break;
506  case SDLK_RSHIFT: result = K_RSHIFT; break;
507  case SDLK_LSHIFT: result = K_LSHIFT; break;
508  case SDLK_RCTRL: result = K_RCTRL; break;
509  case SDLK_LCTRL: result = K_LCTRL; break;
510  case SDLK_RALT: result = K_RALT; break;
511  case SDLK_LALT: result = K_LALT; break;
512 // case SDLK_RMETA: result = K_RMETA; break;
513 // case SDLK_LMETA: result = K_LMETA; break;
514  case SDLK_LGUI: result = K_LSUPER; break; // Left "Windows" key
515  case SDLK_RGUI: result = K_RSUPER; break; // Right "Windows" key
516  case SDLK_MODE: result = K_MODE; break; // "Alt Gr" key
517 // case SDLK_COMPOSE: result = K_COMPOSE; break; // Multi-key compose key
518 
519  // Miscellaneous function keys
520  case SDLK_HELP: result = K_HELP; break;
521  case SDLK_PRINTSCREEN: result = K_PRINT; break;
522  case SDLK_SYSREQ: result = K_SYSREQ; break;
523 // case SDLK_BREAK: result = K_BREAK; break;
524  case SDLK_APPLICATION: result = K_MENU; break;
525  case SDLK_MENU: result = K_MENU; break;
526  case SDLK_POWER: result = K_POWER; break; // Power Macintosh power key
527 // case SDLK_EURO: result = K_EURO; break; // Some european keyboards
528  case SDLK_UNDO: result = K_UNDO; break;
529 
530  // Application Control keys
531  case SDLK_AC_BACK: result = K_BACK; break;
532 
533  default: result = K_UNKNOWN; break;
534  }
535 
536  // Handle keys that don't have a key code but do have a scan code.
537  if (result == K_UNKNOWN) {
538  // Assume it is a Japanese keyboard and check
539  // scancode to recognize a few japanese
540  // specific keys for which SDL does not have an
541  // SDL_Keycode keysym definition.
542  switch (scancode) {
543  // Keys found on Japanese keyboards:
544  case 49:
545  result = K_ZENKAKU_HENKAKU;
546  break;
547  case 129:
548  result = K_HENKAN_MODE;
549  break;
550  //case 131:
551  // result = K_MUHENKAN;
552  // break;
553  case 208:
554  result = K_HIRAGANA_KATAKANA;
555  break;
556  // Keys found on Korean keyboards:
557  case 56:
558  // On Korean keyboard this code is used for R-ALT key but SDL does
559  // not seem to recognize it, as reported by Miso Kim.
560  result = K_RALT;
561  default:
562  break; // nothing, silence compiler warning
563  }
564  }
565 
566  // Apply modifiers.
567  if (mod & KMOD_CTRL) {
568  result = static_cast<KeyCode>(result | KM_CTRL);
569  }
570  if (mod & KMOD_SHIFT) {
571  result = static_cast<KeyCode>(result | KM_SHIFT);
572  }
573  if (mod & KMOD_ALT) {
574  result = static_cast<KeyCode>(result | KM_ALT);
575  }
576  if (mod & KMOD_GUI) {
577  result = static_cast<KeyCode>(result | KM_META);
578  }
579  if (mod & KMOD_MODE) {
580  result = static_cast<KeyCode>(result | KM_MODE);
581  }
582 
583  if (release) {
584  result = static_cast<KeyCode>(result | KD_RELEASE);
585  }
586  return result;
587 }
588 
589 string getName(KeyCode keyCode)
590 {
591  string result;
592  for (const auto& [name, code] : keys) {
593  if (code == (keyCode & K_MASK)) {
594  result = name;
595  break;
596  }
597  }
598  if (result.empty()) {
599  return "unknown";
600  }
601  if (keyCode & KM_CTRL) {
602  result += "+CTRL";
603  }
604  if (keyCode & KM_SHIFT) {
605  result += "+SHIFT";
606  }
607  if (keyCode & KM_ALT) {
608  result += "+ALT";
609  }
610  if (keyCode & KM_META) {
611  result += "+META";
612  }
613  if (keyCode & KM_MODE) {
614  result += "+MODE";
615  }
616  if (keyCode & KD_RELEASE) {
617  result += ",RELEASE";
618  }
619  return result;
620 }
621 
622 } // namespace openmsx::Keys
constexpr P & operator=(const P &o)
Definition: Keys.cc:18
#define KEYS_SORT
Definition: Keys.cc:50
KeyCode second
Definition: Keys.cc:26
KeyCode
Constants that identify keys and key modifiers.
Definition: Keys.hh:25
string_view first
Definition: Keys.cc:25
constexpr bool operator()(const P &x, const P &y) const
Definition: Keys.cc:31
auto lower_bound(ForwardRange &&range, const T &value)
Definition: ranges.hh:71
string getName(KeyCode keyCode)
Translate key code to key name.
Definition: Keys.cc:589
constexpr KeyMatrixPosition x
Keyboard bindings.
Definition: Keyboard.cc:1377
bool operator()(const P &x, string_view y) const
Definition: Keys.cc:36
#define KEYS_CONSTEXPR
Definition: Keys.cc:49
KeyCode getCode(string_view name)
Definition: Keys.cc:341
constexpr P(string_view s, KeyCode k)
Definition: Keys.cc:14