1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "backends/keymapper/hardware-input.h"
24 
25 #include "backends/keymapper/keymapper.h"
26 
27 #include "common/tokenizer.h"
28 #include "common/translation.h"
29 
30 namespace Common {
31 
32 // TODO: Maybe make 'Command' a separate mac-specific modifier so we can define
33 //  defaults key bindings from the original mac game versions without binding
34 //  them to the meta key on other platforms?
35 #if defined(WIN32)
36 #define META_KEY_NAME "Win"
37 #elif defined(MACOSX) || defined(IPHONE)
38 #define META_KEY_NAME "Cmd"
39 #else
40 #define META_KEY_NAME "Meta"
41 #endif
42 
43 const KeyTableEntry defaultKeys[] = {
44 	{"BACKSPACE", KEYCODE_BACKSPACE, "Backspace"},
45 	{"TAB", KEYCODE_TAB, "Tab"},
46 	{"CLEAR", KEYCODE_CLEAR, "Clear"},
47 	{"RETURN", KEYCODE_RETURN, "Return"},
48 	{"PAUSE", KEYCODE_PAUSE, "Pause"},
49 	{"ESCAPE", KEYCODE_ESCAPE, "Esc"},
50 	{"SPACE", KEYCODE_SPACE, "Space"},
51 	{"EXCLAIM", KEYCODE_EXCLAIM, "!"},
52 	{"QUOTEDBL", KEYCODE_QUOTEDBL, "\""},
53 	{"HASH", KEYCODE_HASH, "#"},
54 	{"DOLLAR", KEYCODE_DOLLAR, "$"},
55 	{"PERCENT", KEYCODE_PERCENT, "%"},
56 	{"AMPERSAND", KEYCODE_AMPERSAND, "&"},
57 	{"QUOTE", KEYCODE_QUOTE, "'"},
58 	{"LEFTPAREN", KEYCODE_LEFTPAREN, "("},
59 	{"RIGHTPAREN", KEYCODE_RIGHTPAREN, ")"},
60 	{"ASTERISK", KEYCODE_ASTERISK, "*"},
61 	{"PLUS", KEYCODE_PLUS, "+"},
62 	{"COMMA", KEYCODE_COMMA, ","},
63 	{"MINUS", KEYCODE_MINUS, "-"},
64 	{"PERIOD", KEYCODE_PERIOD, "."},
65 	{"SLASH", KEYCODE_SLASH, "/"},
66 	{"0", KEYCODE_0, "0"},
67 	{"1", KEYCODE_1, "1"},
68 	{"2", KEYCODE_2, "2"},
69 	{"3", KEYCODE_3, "3"},
70 	{"4", KEYCODE_4, "4"},
71 	{"5", KEYCODE_5, "5"},
72 	{"6", KEYCODE_6, "6"},
73 	{"7", KEYCODE_7, "7"},
74 	{"8", KEYCODE_8, "8"},
75 	{"9", KEYCODE_9, "9"},
76 	{"COLON", KEYCODE_COLON, ":"},
77 	{"SEMICOLON", KEYCODE_SEMICOLON, ";"},
78 	{"LESS", KEYCODE_LESS, "<"},
79 	{"EQUALS", KEYCODE_EQUALS, "="},
80 	{"GREATER", KEYCODE_GREATER, ">"},
81 	{"QUESTION", KEYCODE_QUESTION, "?"},
82 	{"AT", KEYCODE_AT, "@"},
83 
84 	{"LEFTBRACKET", KEYCODE_LEFTBRACKET, "["},
85 	{"BACKSLASH", KEYCODE_BACKSLASH, "\\"},
86 	{"RIGHTBRACKET", KEYCODE_RIGHTBRACKET, "]"},
87 	{"CARET", KEYCODE_CARET, "^"},
88 	{"UNDERSCORE", KEYCODE_UNDERSCORE, "_"},
89 	{"BACKQUOTE", KEYCODE_BACKQUOTE, "`"},
90 	{"a", KEYCODE_a, "a"},
91 	{"b", KEYCODE_b, "b"},
92 	{"c", KEYCODE_c, "c"},
93 	{"d", KEYCODE_d, "d"},
94 	{"e", KEYCODE_e, "e"},
95 	{"f", KEYCODE_f, "f"},
96 	{"g", KEYCODE_g, "g"},
97 	{"h", KEYCODE_h, "h"},
98 	{"i", KEYCODE_i, "i"},
99 	{"j", KEYCODE_j, "j"},
100 	{"k", KEYCODE_k, "k"},
101 	{"l", KEYCODE_l, "l"},
102 	{"m", KEYCODE_m, "m"},
103 	{"n", KEYCODE_n, "n"},
104 	{"o", KEYCODE_o, "o"},
105 	{"p", KEYCODE_p, "p"},
106 	{"q", KEYCODE_q, "q"},
107 	{"r", KEYCODE_r, "r"},
108 	{"s", KEYCODE_s, "s"},
109 	{"t", KEYCODE_t, "t"},
110 	{"u", KEYCODE_u, "u"},
111 	{"v", KEYCODE_v, "v"},
112 	{"w", KEYCODE_w, "w"},
113 	{"x", KEYCODE_x, "x"},
114 	{"y", KEYCODE_y, "y"},
115 	{"z", KEYCODE_z, "z"},
116 	{"DELETE", KEYCODE_DELETE, "Del"},
117 
118 	// Numeric keypad
119 	{"KP0", KEYCODE_KP0, "KP0"},
120 	{"KP1", KEYCODE_KP1, "KP1"},
121 	{"KP2", KEYCODE_KP2, "KP2"},
122 	{"KP3", KEYCODE_KP3, "KP3"},
123 	{"KP4", KEYCODE_KP4, "KP4"},
124 	{"KP5", KEYCODE_KP5, "KP5"},
125 	{"KP6", KEYCODE_KP6, "KP6"},
126 	{"KP7", KEYCODE_KP7, "KP7"},
127 	{"KP8", KEYCODE_KP8, "KP8"},
128 	{"KP9", KEYCODE_KP9, "KP9"},
129 	{"KP_PERIOD", KEYCODE_KP_PERIOD, "KP."},
130 	{"KP_DIVIDE", KEYCODE_KP_DIVIDE, "KP/"},
131 	{"KP_MULTIPLY", KEYCODE_KP_MULTIPLY, "KP*"},
132 	{"KP_MINUS", KEYCODE_KP_MINUS, "KP-"},
133 	{"KP_PLUS", KEYCODE_KP_PLUS, "KP+"},
134 	{"KP_ENTER", KEYCODE_KP_ENTER, "KP Enter"},
135 	{"KP_EQUALS", KEYCODE_KP_EQUALS, "KP="},
136 
137 	// Arrows + Home/End pad
138 	{"UP", KEYCODE_UP, "Up"},
139 	{"DOWN", KEYCODE_DOWN, "Down"},
140 	{"RIGHT", KEYCODE_RIGHT, "Right"},
141 	{"LEFT", KEYCODE_LEFT, "Left"},
142 	{"INSERT", KEYCODE_INSERT, "Insert"},
143 	{"HOME", KEYCODE_HOME, "Home"},
144 	{"END", KEYCODE_END, "End"},
145 	{"PAGEUP", KEYCODE_PAGEUP, "PgUp"},
146 	{"PAGEDOWN", KEYCODE_PAGEDOWN, "PgDn"},
147 
148 	// Function keys
149 	{"F1", KEYCODE_F1, "F1"},
150 	{"F2", KEYCODE_F2, "F2"},
151 	{"F3", KEYCODE_F3, "F3"},
152 	{"F4", KEYCODE_F4, "F4"},
153 	{"F5", KEYCODE_F5, "F5"},
154 	{"F6", KEYCODE_F6, "F6"},
155 	{"F7", KEYCODE_F7, "F7"},
156 	{"F8", KEYCODE_F8, "F8"},
157 	{"F9", KEYCODE_F9, "F9"},
158 	{"F10", KEYCODE_F10, "F10"},
159 	{"F11", KEYCODE_F11, "F11"},
160 	{"F12", KEYCODE_F12, "F12"},
161 	{"F13", KEYCODE_F13, "F13"},
162 	{"F14", KEYCODE_F14, "F14"},
163 	{"F15", KEYCODE_F15, "F15"},
164 	{"F16", KEYCODE_F16, "F16"},
165 	{"F17", KEYCODE_F17, "F17"},
166 	{"F18", KEYCODE_F18, "F18"},
167 
168 	// Miscellaneous function keys
169 	{"HELP", KEYCODE_HELP, "Help"},
170 	{"PRINT", KEYCODE_PRINT, "Print"},
171 	{"SYSREQ", KEYCODE_SYSREQ, "SysRq"},
172 	{"BREAK", KEYCODE_BREAK, "Break"},
173 	{"MENU", KEYCODE_MENU, "Menu"},
174 		// Power Macintosh power key
175 	{"POWER", KEYCODE_POWER, "Power"},
176 		// Some european keyboards
177 	{"EURO", KEYCODE_EURO, "Euro"},
178 		// Atari keyboard has Undo
179 	{"UNDO", KEYCODE_UNDO, "Undo"},
180 	{"SLEEP", KEYCODE_SLEEP, "Sleep"},
181 	{"MUTE", KEYCODE_MUTE, "Mute"},
182 	{"EJECT", KEYCODE_EJECT, "Eject"},
183 	{"VOLUMEUP", KEYCODE_VOLUMEUP, "Volume Up"},
184 	{"VOLUMEDOWN", KEYCODE_VOLUMEDOWN, "Volume Down"},
185 	{"LEFTSOFT", KEYCODE_LEFTSOFT, "Left Soft"},
186 	{"RIGHTSOFT", KEYCODE_RIGHTSOFT, "Right Soft"},
187 	{"CALL", KEYCODE_CALL, "Call"},
188 	{"HANGUP", KEYCODE_HANGUP, "Hang up"},
189 	{"CAMERA", KEYCODE_CAMERA, "Camera"},
190 	{"WWW", KEYCODE_WWW, "WWW"},
191 	{"MAIL", KEYCODE_MAIL, "Mail"},
192 	{"CALCULATOR", KEYCODE_CALCULATOR, "Calculator"},
193 	{"CUT", KEYCODE_CUT, "Cut"},
194 	{"COPY", KEYCODE_COPY, "Copy"},
195 	{"PASTE", KEYCODE_PASTE, "Paste"},
196 	{"SELECT", KEYCODE_SELECT, "Select"},
197 	{"CANCEL", KEYCODE_CANCEL, "Cancel"},
198 
199 	// Action keys
200 	{"AC_SEARCH", KEYCODE_AC_SEARCH, "AC Search"},
201 	{"AC_HOME", KEYCODE_AC_HOME, "AC Home"},
202 	{"AC_BACK", KEYCODE_AC_BACK, "AC Back"},
203 	{"AC_FORWARD", KEYCODE_AC_FORWARD, "AC Forward"},
204 	{"AC_STOP", KEYCODE_AC_STOP, "AC Stop"},
205 	{"AC_REFRESH", KEYCODE_AC_REFRESH, "AC Refresh"},
206 	{"AC_BOOKMARKS", KEYCODE_AC_BOOKMARKS, "AC Bookmarks"},
207 
208 	// Audio keys
209 	{"AUDIONEXT", KEYCODE_AUDIONEXT, "Audio Next"},
210 	{"AUDIOPREV", KEYCODE_AUDIOPREV, "Audio Previous"},
211 	{"AUDIOSTOP", KEYCODE_AUDIOSTOP, "Audio Stop"},
212 	{"AUDIOPLAY", KEYCODE_AUDIOPLAY, "Audio Play"},
213 	{"AUDIOPAUSE", KEYCODE_AUDIOPAUSE, "Audio Pause"},
214 	{"AUDIOPLAYPAUSE", KEYCODE_AUDIOPLAYPAUSE, "Audio Play/Pause"},
215 	{"AUDIOMUTE", KEYCODE_AUDIOMUTE, "Audio Mute"},
216 	{"AUDIOREWIND", KEYCODE_AUDIOREWIND, "Audio Rewind"},
217 	{"AUDIOFASTFORWARD", KEYCODE_AUDIOFASTFORWARD, "Audio Fast-Forward"},
218 
219 	// Modifier keys
220 	{"SCROLLOCK", KEYCODE_SCROLLOCK, "Scroll Lock"          },
221 	{"CAPSLOCK",  KEYCODE_CAPSLOCK,  "Caps Lock"            },
222 	{"NUMLOCK",   KEYCODE_NUMLOCK,   "Num Lock"             },
223 	{"LSHIFT",    KEYCODE_LSHIFT,    "Left Shift"           },
224 	{"RSHIFT",    KEYCODE_RSHIFT,    "Right Shift"          },
225 	{"LALT",      KEYCODE_LALT,      "Left Alt"             },
226 	{"RALT",      KEYCODE_RALT,      "Right Alt"            },
227 	{"LCTRL",     KEYCODE_LCTRL,     "Left Control"         },
228 	{"RCTRL",     KEYCODE_RCTRL,     "Right Control"        },
229 	{"LMETA",     KEYCODE_LMETA,     "Left "  META_KEY_NAME },
230 	{"RMETA",     KEYCODE_RMETA,     "Right " META_KEY_NAME },
231 
232 	{0, KEYCODE_INVALID, 0}
233 };
234 
235 // TODO: Add NUM_LOCK
236 const ModifierTableEntry defaultModifiers[] = {
237 	{ KBD_CTRL,  "C", "Ctrl+"            },
238 	{ KBD_SHIFT, "S", "Shift+"           },
239 	{ KBD_ALT,   "A", "Alt+"             },
240 	{ KBD_META,  "M", META_KEY_NAME "+"  },
241 	{ 0,     nullptr, nullptr            }
242 };
243 
244 const HardwareInputTableEntry defaultMouseButtons[] = {
245 	{ "MOUSE_LEFT",       MOUSE_BUTTON_LEFT,   _s("Left Mouse Button")   },
246 	{ "MOUSE_RIGHT",      MOUSE_BUTTON_RIGHT,  _s("Right Mouse Button")  },
247 	{ "MOUSE_MIDDLE",     MOUSE_BUTTON_MIDDLE, _s("Middle Mouse Button") },
248 	{ "MOUSE_WHEEL_UP",   MOUSE_WHEEL_UP,      _s("Mouse Wheel Up")      },
249 	{ "MOUSE_WHEEL_DOWN", MOUSE_WHEEL_DOWN,    _s("Mouse Wheel Down")    },
250 	{ "MOUSE_X1",         MOUSE_BUTTON_X1,     _s("X1 Mouse Button")     },
251 	{ "MOUSE_X2",         MOUSE_BUTTON_X2,     _s("X2 Mouse Button")     },
252 	{ nullptr,            0,                   nullptr                   }
253 };
254 
255 const HardwareInputTableEntry defaultJoystickButtons[] = {
256 	{ "JOY_A",              JOYSTICK_BUTTON_A,              _s("Joy A")          },
257 	{ "JOY_B",              JOYSTICK_BUTTON_B,              _s("Joy B")          },
258 	{ "JOY_X",              JOYSTICK_BUTTON_X,              _s("Joy X")          },
259 	{ "JOY_Y",              JOYSTICK_BUTTON_Y,              _s("Joy Y")          },
260 	{ "JOY_BACK",           JOYSTICK_BUTTON_BACK,           _s("Joy Back")       },
261 	{ "JOY_GUIDE",          JOYSTICK_BUTTON_GUIDE,          _s("Joy Guide")      },
262 	{ "JOY_START",          JOYSTICK_BUTTON_START,          _s("Joy Start")      },
263 	{ "JOY_LEFT_STICK",     JOYSTICK_BUTTON_LEFT_STICK,     _s("Left Stick")     },
264 	{ "JOY_RIGHT_STICK",    JOYSTICK_BUTTON_RIGHT_STICK,    _s("Right Stick")    },
265 	{ "JOY_LEFT_SHOULDER",  JOYSTICK_BUTTON_LEFT_SHOULDER,  _s("Left Shoulder")  },
266 	{ "JOY_RIGHT_SHOULDER", JOYSTICK_BUTTON_RIGHT_SHOULDER, _s("Right Shoulder") },
267 	{ "JOY_UP",             JOYSTICK_BUTTON_DPAD_UP,        _s("D-pad Up")       },
268 	{ "JOY_DOWN",           JOYSTICK_BUTTON_DPAD_DOWN,      _s("D-pad Down")     },
269 	{ "JOY_LEFT",           JOYSTICK_BUTTON_DPAD_LEFT,      _s("D-pad Left")     },
270 	{ "JOY_RIGHT",          JOYSTICK_BUTTON_DPAD_RIGHT,     _s("D-pad Right")    },
271 	{ nullptr,              0,                              nullptr              }
272 };
273 
274 const AxisTableEntry defaultJoystickAxes[] = {
275 	{ "JOY_LEFT_TRIGGER",  JOYSTICK_AXIS_LEFT_TRIGGER,  kAxisTypeHalf, _s("Left Trigger")  },
276 	{ "JOY_RIGHT_TRIGGER", JOYSTICK_AXIS_RIGHT_TRIGGER, kAxisTypeHalf, _s("Right Trigger") },
277 	{ "JOY_LEFT_STICK_X",  JOYSTICK_AXIS_LEFT_STICK_X,  kAxisTypeFull, _s("Left Stick X")  },
278 	{ "JOY_LEFT_STICK_Y",  JOYSTICK_AXIS_LEFT_STICK_Y,  kAxisTypeFull, _s("Left Stick Y")  },
279 	{ "JOY_RIGHT_STICK_X", JOYSTICK_AXIS_RIGHT_STICK_X, kAxisTypeFull, _s("Right Stick X") },
280 	{ "JOY_RIGHT_STICK_Y", JOYSTICK_AXIS_RIGHT_STICK_Y, kAxisTypeFull, _s("Right Stick Y") },
281 	{ nullptr,             0,                           kAxisTypeFull, nullptr             }
282 };
283 
~HardwareInputSet()284 HardwareInputSet::~HardwareInputSet() {
285 }
286 
KeyboardHardwareInputSet(const KeyTableEntry * keys,const ModifierTableEntry * modifiers)287 KeyboardHardwareInputSet::KeyboardHardwareInputSet(const KeyTableEntry *keys, const ModifierTableEntry *modifiers) :
288 		_keys(keys),
289 		_modifiers(modifiers) {
290 	assert(_keys);
291 	assert(_modifiers);
292 }
293 
findHardwareInput(const String & id) const294 HardwareInput KeyboardHardwareInputSet::findHardwareInput(const String &id) const {
295 	StringTokenizer tokenizer(id, "+");
296 
297 	byte modifierFlags = 0;
298 
299 	// TODO: Normalize modifier order
300 	U32String fullKeyDesc;
301 
302 	String token;
303 	while (!tokenizer.empty()) {
304 		token = tokenizer.nextToken();
305 
306 		const ModifierTableEntry *modifier = nullptr;
307 		for (modifier = _modifiers;  modifier->id; modifier++) {
308 			if (token == modifier->id) {
309 				break;
310 			}
311 		}
312 
313 		if (modifier && modifier->id) {
314 			modifierFlags |= modifier->flag;
315 			fullKeyDesc += _(modifier->desc);
316 		} else {
317 			// We reached the end of the modifiers, the token is a keycode
318 			break;
319 		}
320 	}
321 
322 	if (!tokenizer.empty()) {
323 		return HardwareInput();
324 	}
325 
326 	const KeyTableEntry *key = nullptr;
327 	for (key = _keys;  key->hwId; key++) {
328 		if (token.equals(key->hwId)) {
329 			break;
330 		}
331 	}
332 
333 	if (!key || !key->hwId) {
334 		return HardwareInput();
335 	}
336 
337 	const KeyState keystate = KeyState(key->keycode, 0, modifierFlags);
338 	return HardwareInput::createKeyboard(id, keystate, fullKeyDesc + _(key->desc));
339 }
340 
findHardwareInput(const Event & event) const341 HardwareInput KeyboardHardwareInputSet::findHardwareInput(const Event &event) const {
342 	switch (event.type) {
343 	case EVENT_KEYDOWN:
344 	case EVENT_KEYUP: {
345 		KeyState normalizedKeystate = normalizeKeyState(event.kbd);
346 
347 		const KeyTableEntry *key = nullptr;
348 		for (key = _keys;  key->hwId; key++) {
349 			if (normalizedKeystate.keycode == key->keycode) {
350 				break;
351 			}
352 		}
353 
354 		if (!key || !key->hwId) {
355 			return HardwareInput();
356 		}
357 
358 		String id;
359 		U32String fullKeyDesc;
360 		byte modifierFlags = 0;
361 
362 		for (const ModifierTableEntry *modifier = _modifiers;  modifier->id; modifier++) {
363 			if (normalizedKeystate.flags & modifier->flag) {
364 				id += modifier->id;
365 				id += "+";
366 				fullKeyDesc += _(modifier->desc);
367 				modifierFlags |= modifier->flag;
368 			}
369 		}
370 
371 		const KeyState keystate = KeyState(key->keycode, 0, modifierFlags);
372 		return HardwareInput::createKeyboard(id + key->hwId, keystate, fullKeyDesc + _(key->desc));
373 	}
374 	default:
375 		return HardwareInput();
376 	}
377 }
378 
normalizeKeyState(const KeyState & keystate)379 KeyState KeyboardHardwareInputSet::normalizeKeyState(const KeyState &keystate) {
380 	KeyState normalizedKeystate = keystate;
381 
382 	// We ignore the sticky modifiers as they traditionally
383 	// have no impact on the outcome of key presses.
384 	// TODO: Maybe Num Lock should act as a modifier for the keypad.
385 	normalizedKeystate.flags &= ~KBD_STICKY;
386 
387 	// Modifier keypresses ignore the corresponding modifier flag.
388 	// That way, for example, `Left Shift` is not identified
389 	// as `Shift+Left Shift` by the keymapper.
390 	switch (normalizedKeystate.keycode) {
391 	case KEYCODE_LSHIFT:
392 	case KEYCODE_RSHIFT:
393 		normalizedKeystate.flags &= ~KBD_SHIFT;
394 		break;
395 	case KEYCODE_LCTRL:
396 	case KEYCODE_RCTRL:
397 		normalizedKeystate.flags &= ~KBD_CTRL;
398 		break;
399 	case KEYCODE_LALT:
400 	case KEYCODE_RALT:
401 		normalizedKeystate.flags &= ~KBD_ALT;
402 		break;
403 	case KEYCODE_LMETA:
404 	case KEYCODE_RMETA:
405 		normalizedKeystate.flags &= ~KBD_META;
406 		break;
407 	case KEYCODE_SCROLLOCK:
408 		normalizedKeystate.flags &= ~KBD_SCRL;
409 		break;
410 	case KEYCODE_CAPSLOCK:
411 		normalizedKeystate.flags &= ~KBD_CAPS;
412 		break;
413 	case KEYCODE_NUMLOCK:
414 		normalizedKeystate.flags &= ~KBD_NUM;
415 		break;
416 	default:
417 		break;
418 	}
419 
420 	return normalizedKeystate;
421 }
422 
MouseHardwareInputSet(const HardwareInputTableEntry * buttonEntries)423 MouseHardwareInputSet::MouseHardwareInputSet(const HardwareInputTableEntry *buttonEntries) :
424 		_buttonEntries(buttonEntries) {
425 	assert(_buttonEntries);
426 }
427 
findHardwareInput(const String & id) const428 HardwareInput MouseHardwareInputSet::findHardwareInput(const String &id) const {
429 	const HardwareInputTableEntry *hw = HardwareInputTableEntry::findWithId(_buttonEntries, id);
430 	if (!hw || !hw->hwId) {
431 		return HardwareInput();
432 	}
433 
434 	return HardwareInput::createMouse(hw->hwId, hw->code, _(hw->desc));
435 }
436 
findHardwareInput(const Event & event) const437 HardwareInput MouseHardwareInputSet::findHardwareInput(const Event &event) const {
438 	int button;
439 	switch (event.type) {
440 	case EVENT_LBUTTONDOWN:
441 	case EVENT_LBUTTONUP:
442 		button = MOUSE_BUTTON_LEFT;
443 		break;
444 	case EVENT_RBUTTONDOWN:
445 	case EVENT_RBUTTONUP:
446 		button = MOUSE_BUTTON_RIGHT;
447 		break;
448 	case EVENT_MBUTTONDOWN:
449 	case EVENT_MBUTTONUP:
450 		button = MOUSE_BUTTON_MIDDLE;
451 		break;
452 	case Common::EVENT_WHEELUP:
453 		button = MOUSE_WHEEL_UP;
454 		break;
455 	case Common::EVENT_WHEELDOWN:
456 		button = MOUSE_WHEEL_DOWN;
457 		break;
458 	case EVENT_X1BUTTONDOWN:
459 	case EVENT_X1BUTTONUP:
460 		button = MOUSE_BUTTON_X1;
461 		break;
462 	case EVENT_X2BUTTONDOWN:
463 	case EVENT_X2BUTTONUP:
464 		button = MOUSE_BUTTON_X2;
465 		break;
466 	default:
467 		button = -1;
468 		break;
469 	}
470 
471 	if (button == -1) {
472 		return HardwareInput();
473 	}
474 
475 	const HardwareInputTableEntry *hw = HardwareInputTableEntry::findWithCode(_buttonEntries, button);
476 	if (!hw || !hw->hwId) {
477 		return HardwareInput();
478 	}
479 
480 	return HardwareInput::createMouse(hw->hwId, hw->code, _(hw->desc));
481 }
482 
JoystickHardwareInputSet(const HardwareInputTableEntry * buttonEntries,const AxisTableEntry * axisEntries)483 JoystickHardwareInputSet::JoystickHardwareInputSet(const HardwareInputTableEntry *buttonEntries, const AxisTableEntry *axisEntries) :
484 		_buttonEntries(buttonEntries),
485 		_axisEntries(axisEntries) {
486 	assert(_buttonEntries);
487 	assert(_axisEntries);
488 }
489 
findHardwareInput(const String & id) const490 HardwareInput JoystickHardwareInputSet::findHardwareInput(const String &id) const {
491 	const HardwareInputTableEntry *hw = HardwareInputTableEntry::findWithId(_buttonEntries, id);
492 	if (hw && hw->hwId) {
493 		return HardwareInput::createJoystickButton(hw->hwId, hw->code, _(hw->desc));
494 	}
495 
496 	bool hasHalfSuffix = id.lastChar() == '-' || id.lastChar() == '+';
497 	Common::String tableId = hasHalfSuffix ? Common::String(id.c_str(), id.size() - 1) : id;
498 	const AxisTableEntry *axis = AxisTableEntry::findWithId(_axisEntries, tableId);
499 	if (axis && axis->hwId) {
500 		if (hasHalfSuffix && axis->type == kAxisTypeHalf) {
501 			return HardwareInput(); // Half axes can't be split in halves
502 		} else if (!hasHalfSuffix && axis->type == kAxisTypeFull) {
503 			return HardwareInput(); // For now it's only possible to bind half axes
504 		}
505 
506 		if (axis->type == kAxisTypeHalf) {
507 			return HardwareInput::createJoystickHalfAxis(axis->hwId, axis->code, true, _(axis->desc));
508 		} else {
509 			bool positiveHalf = id.lastChar() == '+';
510 			Common::U32String desc = U32String::format("%S%c", _(axis->desc).c_str(), id.lastChar());
511 			return HardwareInput::createJoystickHalfAxis(id, axis->code, positiveHalf, desc);
512 		}
513 	}
514 
515 	return HardwareInput();
516 }
517 
findHardwareInput(const Event & event) const518 HardwareInput JoystickHardwareInputSet::findHardwareInput(const Event &event) const {
519 	switch (event.type) {
520 	case EVENT_JOYBUTTON_DOWN:
521 	case EVENT_JOYBUTTON_UP: {
522 		const HardwareInputTableEntry *hw = HardwareInputTableEntry::findWithCode(_buttonEntries, event.joystick.button);
523 		if (!hw || !hw->hwId) {
524 			return HardwareInput();
525 		}
526 
527 		return HardwareInput::createJoystickButton(hw->hwId, hw->code, _(hw->desc));
528 	}
529 	case EVENT_JOYAXIS_MOTION: {
530 		if (ABS(event.joystick.position) < (JOYAXIS_MAX / 2)) {
531 			return HardwareInput(); // Ignore incomplete presses for remapping purposes
532 		}
533 
534 		const AxisTableEntry *hw = AxisTableEntry::findWithCode(_axisEntries, event.joystick.axis);
535 		if (!hw || !hw->hwId) {
536 			return HardwareInput();
537 		}
538 
539 		if (hw->type == kAxisTypeHalf) {
540 			return HardwareInput::createJoystickHalfAxis(hw->hwId, hw->code, true, _(hw->desc));
541 		} else {
542 			bool positiveHalf = event.joystick.position >= 0;
543 			char halfSuffix = positiveHalf ? '+' : '-';
544 			Common::String hwId = String::format("%s%c", hw->hwId, halfSuffix);
545 			Common::U32String desc = U32String::format("%S%c", _(hw->desc).c_str(), halfSuffix);
546 			return HardwareInput::createJoystickHalfAxis(hwId, hw->code, positiveHalf, desc);
547 		}
548 	}
549 
550 	default:
551 		return HardwareInput();
552 	}
553 }
554 
CustomHardwareInputSet(const HardwareInputTableEntry * hardwareEntries)555 CustomHardwareInputSet::CustomHardwareInputSet(const HardwareInputTableEntry *hardwareEntries) :
556 		_hardwareEntries(hardwareEntries) {
557 	assert(_hardwareEntries);
558 }
559 
findHardwareInput(const String & id) const560 HardwareInput CustomHardwareInputSet::findHardwareInput(const String &id) const {
561 	const HardwareInputTableEntry *hw = HardwareInputTableEntry::findWithId(_hardwareEntries, id);
562 	if (!hw || !hw->hwId) {
563 		return HardwareInput();
564 	}
565 
566 	return HardwareInput::createCustom(hw->hwId, hw->code, _(hw->desc));
567 }
568 
findHardwareInput(const Event & event) const569 HardwareInput CustomHardwareInputSet::findHardwareInput(const Event &event) const {
570 	switch (event.type) {
571 	case EVENT_CUSTOM_BACKEND_HARDWARE: {
572 		const HardwareInputTableEntry *hw = HardwareInputTableEntry::findWithCode(_hardwareEntries, event.customType);
573 		if (!hw || !hw->hwId) {
574 			return HardwareInput();
575 		}
576 
577 		return HardwareInput::createCustom(hw->hwId, hw->code, _(hw->desc));
578 	}
579 	default:
580 		return HardwareInput();
581 	}
582 }
583 
~CompositeHardwareInputSet()584 CompositeHardwareInputSet::~CompositeHardwareInputSet() {
585 	for (uint i = 0; i < _inputSets.size(); i++) {
586 		delete _inputSets[i];
587 	}
588 }
589 
findHardwareInput(const String & id) const590 HardwareInput CompositeHardwareInputSet::findHardwareInput(const String &id) const {
591 	for (uint i = 0; i < _inputSets.size(); i++) {
592 		HardwareInput hardwareInput = _inputSets[i]->findHardwareInput(id);
593 		if (hardwareInput.type != kHardwareInputTypeInvalid) {
594 			return hardwareInput;
595 		}
596 	}
597 
598 	return HardwareInput();
599 }
600 
findHardwareInput(const Event & event) const601 HardwareInput CompositeHardwareInputSet::findHardwareInput(const Event &event) const {
602 	for (uint i = 0; i < _inputSets.size(); i++) {
603 		HardwareInput hardwareInput = _inputSets[i]->findHardwareInput(event);
604 		if (hardwareInput.type != kHardwareInputTypeInvalid) {
605 			return hardwareInput;
606 		}
607 	}
608 
609 	return HardwareInput();
610 }
611 
addHardwareInputSet(HardwareInputSet * hardwareInputSet)612 void CompositeHardwareInputSet::addHardwareInputSet(HardwareInputSet *hardwareInputSet) {
613 	_inputSets.push_back(hardwareInputSet);
614 }
615 
616 } //namespace Common
617