Add large-video option to force hires dumping
[lsnes.git] / keymapper.hpp
blobb5b179a2c40e4d321be21b4ae37530d8ec7afe27
1 #ifndef _keymapper__hpp__included__
2 #define _keymapper__hpp__included__
4 #include <string>
5 #include <sstream>
6 #include <stdexcept>
7 #include <list>
8 #include <set>
9 #include <iostream>
10 #include "window.hpp"
11 #include "misc.hpp"
13 /**
14 * \brief Fixup command according to key polarity.
16 * Takes in a raw command and returns the command that should be actually executed given the key polarity.
18 * \param cmd Raw command.
19 * \param polarity Polarity (True => Being pressed, False => Being released).
20 * \return The fixed command, "" if no command should be executed.
21 * \throws std::bad_alloc Not enough memory.
23 std::string fixup_command_polarity(std::string cmd, bool polarity) throw(std::bad_alloc);
26 /**
27 * \brief Keyboard mapper.
29 * This class handles internals of mapping events from keyboard buttons and pseudo-buttons. The helper class T has
30 * to have the following:
32 * unsigned T::mod_str(const std::string& mod): Translate modifiers set mod into modifier mask.
33 * typedef T::internal_keysymbol: Key symbol to match against. Needs to have == operator available.
34 * T::internal_keysymbol key_str(const std::string& keyname): Translate key name to key to match against.
35 * typedef T::keysymbol: Key symbol from keyboard (or pseudo-button). Carries modifiers too.
36 * unsigned mod_key(T::keysymbol key): Get modifier mask for keyboard key.
37 * T::internal_keysymbol key_key(T::keysymbol key): Get key symbol to match against for given keyboard key.
38 * std::string T::name_key(unsigned mod, unsigned modmask, T::internal_keysymbol key): Print name of key with mods.
40 template<class T>
41 class keymapper
43 public:
44 /**
45 * \brief Bind a key.
47 * Binds a key, erroring out if binding would conflict with existing one.
49 * \param mod Modifier set to require to be pressed.
50 * \param modmask Modifier set to take into account.
51 * \param keyname Key to bind the action to.
52 * \param command The command to bind.
53 * \throws std::bad_alloc Not enough memory.
54 * \throws std::runtime_error The binding would conflict with existing one.
56 void bind(std::string mod, std::string modmask, std::string keyname, std::string command) throw(std::bad_alloc,
57 std::runtime_error)
59 unsigned _mod = T::mod_str(mod);
60 unsigned _modmask = T::mod_str(modmask);
61 if(_mod & ~_modmask)
62 throw std::runtime_error("Mod must be subset of modmask");
63 typename T::internal_keysymbol _keyname = T::key_str(keyname);
64 /* Check for collisions. */
65 for(auto i = bindings.begin(); i != bindings.end(); i++) {
66 if(!(_keyname == i->symbol))
67 continue;
68 if((_mod & _modmask & i->modmask) != (i->mod & _modmask & i->modmask))
69 continue;
70 throw std::runtime_error("Would conflict with " + T::name_key(i->mod, i->modmask, i->symbol));
72 struct kdata k;
73 k.mod = _mod;
74 k.modmask = _modmask;
75 k.symbol = _keyname;
76 k.command = command;
77 bindings.push_back(k);
80 /**
81 * \brief Unbind a key.
83 * Unbinds a key, erroring out if binding does not exist..
85 * \param mod Modifier set to require to be pressed.
86 * \param modmask Modifier set to take into account.
87 * \param keyname Key to bind the action to.
88 * \throws std::bad_alloc Not enough memory.
89 * \throws std::runtime_error The binding does not exist.
91 void unbind(std::string mod, std::string modmask, std::string keyname) throw(std::bad_alloc,
92 std::runtime_error)
94 unsigned _mod = T::mod_str(mod);
95 unsigned _modmask = T::mod_str(modmask);
96 typename T::internal_keysymbol _keyname = T::key_str(keyname);
97 for(auto i = bindings.begin(); i != bindings.end(); i++) {
98 if(!(_keyname == i->symbol) || _mod != i->mod || _modmask != i->modmask)
99 continue;
100 bindings.erase(i);
101 return;
103 throw std::runtime_error("No such binding");
107 * \brief Map key symbol from keyboard + polarity into a command.
109 * Takes in symbol from keyboard and polarity. Outputs command to run.
111 * \param sym Symbol from keyboard (with its mods).
112 * \param polarity True if key is being pressed, false if being released.
113 * \return The command to run. "" if none.
114 * \throws std::bad_alloc Not enough memory.
116 std::string map(typename T::keysymbol sym, bool polarity) throw(std::bad_alloc)
118 unsigned _mod = T::mod_key(sym);
119 typename T::internal_keysymbol _keyname = T::key_key(sym);
120 for(auto i = bindings.begin(); i != bindings.end(); i++) {
121 if((!(_keyname == i->symbol)) || ((_mod & i->modmask) != (i->mod & i->modmask)))
122 continue;
123 std::string x = fixup_command_polarity(i->command, polarity);
124 if(x == "")
125 continue;
126 return x;
128 return "";
132 * \brief Dump list of bindigns as messages to specified graphics handle.
134 * \param win The graphics system handle.
135 * \throws std::bad_alloc Not enough memory.
137 void dumpbindings(window* win) throw(std::bad_alloc)
139 for(auto i = bindings.begin(); i != bindings.end(); i++)
140 out(win) << "bind " << T::name_key(i->mod, i->modmask, i->symbol) << " " << i->command
141 << std::endl;
143 private:
144 struct kdata
146 unsigned mod;
147 unsigned modmask;
148 typename T::internal_keysymbol symbol;
149 std::string command;
151 std::list<kdata> bindings;
154 #endif