| 71 | } |
| 72 | |
| 73 | std::optional<KeySpec> KeySpec::parse(std::string spec, std::string* err) { |
| 74 | KeySpec out; |
| 75 | |
| 76 | // Determine focus string, if present |
| 77 | size_t focus_idx = spec.find('@'); |
| 78 | if (focus_idx != std::string::npos) { |
| 79 | split_string(&out.focus, spec.substr(focus_idx + 1), "|"); |
| 80 | spec.erase(focus_idx); |
| 81 | } |
| 82 | |
| 83 | // Treat remaining keyspec as lowercase for case-insensitivity. |
| 84 | std::transform(spec.begin(), spec.end(), spec.begin(), tolower); |
| 85 | |
| 86 | // Determine modifier flags |
| 87 | auto match_modifier = [&out, &spec](std::string_view prefix, int mod) { |
| 88 | bool found = spec.starts_with(prefix); |
| 89 | if (found) { |
| 90 | out.modifiers |= mod; |
| 91 | spec.erase(0, prefix.size()); |
| 92 | } |
| 93 | return found; |
| 94 | }; |
| 95 | while (match_modifier("shift-", DFH_MOD_SHIFT) |
| 96 | || match_modifier("ctrl-", DFH_MOD_CTRL) |
| 97 | || match_modifier("alt-", DFH_MOD_ALT) |
| 98 | || match_modifier("super-", DFH_MOD_SUPER)) {} |
| 99 | |
| 100 | out.sym = DFSDL::DFSDL_GetKeyFromName(spec.c_str()); |
| 101 | if (out.sym != SDLK_UNKNOWN) |
| 102 | return out; |
| 103 | |
| 104 | // Attempt to parse as a mouse binding |
| 105 | if (spec.starts_with("mouse")) { |
| 106 | spec.erase(0, 5); |
| 107 | // Read button number, ensuring between 4 and 15 inclusive |
| 108 | try { |
| 109 | int mbutton = std::stoi(spec); |
| 110 | if (mbutton >= 4 && mbutton <= 15) { |
| 111 | out.sym = -mbutton; |
| 112 | return out; |
| 113 | } |
| 114 | } catch (...) { |
| 115 | // If integer parsing fails, it isn't valid |
| 116 | } |
| 117 | if (err) |
| 118 | *err = "Invalid mouse button '" + spec + "', only 4-15 are valid"; |
| 119 | return std::nullopt; |
| 120 | } |
| 121 | |
| 122 | if (err) |
| 123 | *err = "Unknown key '" + spec + "'"; |
| 124 | |
| 125 | // Invalid key binding |
| 126 | return std::nullopt; |
| 127 | } |
| 128 | |
| 129 | bool KeySpec::isDisruptive() const { |
| 130 | // SDLK enum uses the actual characters for a key as its value. |